From 5fce7f3b22e50b23944737f60758178a428c133b Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 25 Jun 2020 20:39:55 +0200 Subject: [PATCH] Add market Change closes #2524 and #3518 --- freqtrade/data/btanalysis.py | 20 ++++++++++++++++++++ freqtrade/optimize/optimize_reports.py | 12 ++++++++---- tests/data/test_btanalysis.py | 9 +++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/freqtrade/data/btanalysis.py b/freqtrade/data/btanalysis.py index b169850ba..8601f8176 100644 --- a/freqtrade/data/btanalysis.py +++ b/freqtrade/data/btanalysis.py @@ -168,6 +168,26 @@ def extract_trades_of_period(dataframe: pd.DataFrame, trades: pd.DataFrame, return trades +def calculate_market_change(data: Dict[str, pd.DataFrame], column: str = "close") -> float: + """ + Calculate market change based on "column". + Calculation is done by taking the first non-null and the last non-null element of each column + and calculating the pctchange as "(last - first) / first". + Then the results per pair are combined as mean. + + :param data: Dict of Dataframes, dict key should be pair. + :param column: Column in the original dataframes to use + :return: + """ + tmp_means = [] + for pair, df in data.items(): + start = df[column].dropna().iloc[0] + end = df[column].dropna().iloc[-1] + tmp_means.append((end - start) / start) + + return np.mean(tmp_means) + + def combine_dataframes_with_mean(data: Dict[str, pd.DataFrame], column: str = "close") -> pd.DataFrame: """ diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 1e2d41e32..4ec3dc3ad 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -8,7 +8,7 @@ from pandas import DataFrame from tabulate import tabulate from freqtrade.constants import DATETIME_PRINT_FORMAT -from freqtrade.data.btanalysis import calculate_max_drawdown +from freqtrade.data.btanalysis import calculate_max_drawdown, calculate_market_change from freqtrade.misc import file_dump_json logger = logging.getLogger(__name__) @@ -208,6 +208,8 @@ def generate_backtest_stats(config: Dict, btdata: Dict[str, DataFrame], stake_currency = config['stake_currency'] max_open_trades = config['max_open_trades'] result: Dict[str, Any] = {'strategy': {}} + market_change = calculate_market_change(btdata, 'close') + for strategy, results in all_results.items(): pair_results = generate_pair_metrics(btdata, stake_currency=stake_currency, @@ -232,8 +234,9 @@ def generate_backtest_stats(config: Dict, btdata: Dict[str, DataFrame], 'backtest_end': max_date.datetime, 'backtest_end_ts': max_date.timestamp, 'backtest_days': backtest_days, - 'trades_per_day': round(len(results) / backtest_days, 2) if backtest_days > 0 else None - } + 'trades_per_day': round(len(results) / backtest_days, 2) if backtest_days > 0 else None, + 'market_change': market_change, + } result['strategy'][strategy] = strat_stats try: @@ -348,11 +351,12 @@ def text_table_add_metrics(strategy_results: Dict) -> str: ('Max Drawdown', f"{round(strategy_results['max_drawdown'] * 100, 2)}%"), ('Drawdown Start', strategy_results['drawdown_start'].strftime(DATETIME_PRINT_FORMAT)), ('Drawdown End', strategy_results['drawdown_end'].strftime(DATETIME_PRINT_FORMAT)), + ('Market change', f"{round(strategy_results['market_change'] * 100, 2)}%"), ] return tabulate(metrics, headers=["Metric", "Value"], tablefmt="orgtbl") else: - return + return '' def show_backtest_results(config: Dict, backtest_stats: Dict): diff --git a/tests/data/test_btanalysis.py b/tests/data/test_btanalysis.py index b65db7fd8..d571569b9 100644 --- a/tests/data/test_btanalysis.py +++ b/tests/data/test_btanalysis.py @@ -8,6 +8,7 @@ from pandas import DataFrame, DateOffset, Timestamp, to_datetime from freqtrade.configuration import TimeRange from freqtrade.data.btanalysis import (BT_DATA_COLUMNS, analyze_trade_parallelism, + calculate_market_change, calculate_max_drawdown, combine_dataframes_with_mean, create_cum_profit, @@ -135,6 +136,14 @@ def test_load_trades(default_conf, mocker): assert bt_mock.call_count == 0 +def test_calculate_market_change(testdatadir): + pairs = ["ETH/BTC", "ADA/BTC"] + data = load_data(datadir=testdatadir, pairs=pairs, timeframe='5m') + result = calculate_market_change(data) + assert isinstance(result, float) + assert pytest.approx(result) == 0.00955514 + + def test_combine_dataframes_with_mean(testdatadir): pairs = ["ETH/BTC", "ADA/BTC"] data = load_data(datadir=testdatadir, pairs=pairs, timeframe='5m')