From f5a9001dc05effd378f07de663a30a88fa6201ec Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 20 Aug 2020 19:51:36 +0200 Subject: [PATCH 1/2] Handle backtest results without any trades --- freqtrade/optimize/optimize_reports.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 0799ebb23..0681eed7b 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -31,6 +31,7 @@ def store_backtest_stats(recordfilename: Path, stats: Dict[str, DataFrame]) -> N recordfilename.parent, f'{recordfilename.stem}-{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}' ).with_suffix(recordfilename.suffix) + print(stats) file_dump_json(filename, stats) latest_filename = Path.joinpath(filename.parent, LAST_BT_RESULT_FN) @@ -185,6 +186,16 @@ def generate_edge_table(results: dict) -> str: def generate_daily_stats(results: DataFrame) -> Dict[str, Any]: + if len(results) == 0: + return { + 'backtest_best_day': 0, + 'backtest_worst_day': 0, + 'winning_days': 0, + 'draw_days': 0, + 'losing_days': 0, + 'winner_holding_avg': timedelta(), + 'loser_holding_avg': timedelta(), + } daily_profit = results.resample('1d', on='close_date')['profit_percent'].sum() worst = min(daily_profit) best = max(daily_profit) @@ -249,7 +260,7 @@ def generate_backtest_stats(config: Dict, btdata: Dict[str, DataFrame], 'sell_reason_summary': sell_reason_stats, 'left_open_trades': left_open_results, 'total_trades': len(results), - 'profit_mean': results['profit_percent'].mean(), + 'profit_mean': results['profit_percent'].mean() if len(results) > 0 else 0, 'profit_total': results['profit_percent'].sum(), 'profit_total_abs': results['profit_abs'].sum(), 'backtest_start': min_date.datetime, @@ -258,7 +269,7 @@ def generate_backtest_stats(config: Dict, btdata: Dict[str, DataFrame], 'backtest_end_ts': max_date.timestamp * 1000, '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 0, 'market_change': market_change, 'pairlist': list(btdata.keys()), 'stake_amount': config['stake_amount'], From 4f1179d85c3d3aa11a76768c8aaa6af922157e96 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 20 Aug 2020 19:56:41 +0200 Subject: [PATCH 2/2] Test for empty case --- freqtrade/optimize/optimize_reports.py | 1 - tests/optimize/test_optimize_reports.py | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index 0681eed7b..94729b6a5 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -31,7 +31,6 @@ def store_backtest_stats(recordfilename: Path, stats: Dict[str, DataFrame]) -> N recordfilename.parent, f'{recordfilename.stem}-{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}' ).with_suffix(recordfilename.suffix) - print(stats) file_dump_json(filename, stats) latest_filename = Path.joinpath(filename.parent, LAST_BT_RESULT_FN) diff --git a/tests/optimize/test_optimize_reports.py b/tests/optimize/test_optimize_reports.py index e5d98ca43..4f62e2e23 100644 --- a/tests/optimize/test_optimize_reports.py +++ b/tests/optimize/test_optimize_reports.py @@ -204,6 +204,14 @@ def test_generate_daily_stats(testdatadir): assert res['winner_holding_avg'] == timedelta(seconds=1440) assert res['loser_holding_avg'] == timedelta(days=1, seconds=21420) + # Select empty dataframe! + res = generate_daily_stats(bt_data.loc[bt_data['open_date'] == '2000-01-01', :]) + assert isinstance(res, dict) + assert round(res['backtest_best_day'], 4) == 0.0 + assert res['winning_days'] == 0 + assert res['draw_days'] == 0 + assert res['losing_days'] == 0 + def test_text_table_sell_reason(default_conf):