diff --git a/freqtrade/optimize/optimize_reports.py b/freqtrade/optimize/optimize_reports.py index a97f85637..a2590c10b 100644 --- a/freqtrade/optimize/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports.py @@ -219,12 +219,14 @@ def _get_resample_from_period(period: str) -> str: if period == 'week': return '1w' if period == 'month': - return '1m' + return '1M' raise ValueError(f"Period {period} is not supported.") def generate_periodic_breakdown_stats(trade_list: List, period: str) -> List[Dict[str, Any]]: results = DataFrame.from_records(trade_list) + if len(results) == 0: + return [] results['close_date'] = to_datetime(results['close_date'], utc=True) resample = _get_resample_from_period(period) period = results.resample(resample, on='close_date') diff --git a/tests/optimize/test_backtesting.py b/tests/optimize/test_backtesting.py index 2248cd4c1..b5fa44d01 100644 --- a/tests/optimize/test_backtesting.py +++ b/tests/optimize/test_backtesting.py @@ -1102,6 +1102,7 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat '--timerange', '1510694220-1510700340', '--enable-position-stacking', '--disable-max-market-positions', + '--breakdown', 'day', '--strategy-list', 'StrategyTestV2', 'TestStrategyLegacyV1', @@ -1130,6 +1131,7 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat captured = capsys.readouterr() assert 'BACKTESTING REPORT' in captured.out assert 'SELL REASON STATS' in captured.out + assert 'DAY BREAKDOWN' in captured.out assert 'LEFT OPEN TRADES REPORT' in captured.out assert '2017-11-14 21:17:00 -> 2017-11-14 22:58:00 | Max open trades : 1' in captured.out assert 'STRATEGY SUMMARY' in captured.out diff --git a/tests/optimize/test_optimize_reports.py b/tests/optimize/test_optimize_reports.py index 83caefd2d..4bf20e547 100644 --- a/tests/optimize/test_optimize_reports.py +++ b/tests/optimize/test_optimize_reports.py @@ -13,9 +13,9 @@ from freqtrade.data import history from freqtrade.data.btanalysis import get_latest_backtest_filename, load_backtest_data from freqtrade.edge import PairInfo from freqtrade.enums import SellType -from freqtrade.optimize.optimize_reports import (generate_backtest_stats, generate_daily_stats, - generate_edge_table, generate_pair_metrics, - generate_sell_reason_stats, +from freqtrade.optimize.optimize_reports import (_get_resample_from_period, generate_backtest_stats, + generate_daily_stats, generate_edge_table, + generate_pair_metrics, generate_periodic_breakdown_stats, generate_sell_reason_stats, generate_strategy_comparison, generate_trading_stats, store_backtest_stats, text_table_bt_results, text_table_sell_reason, @@ -377,3 +377,31 @@ def test_generate_edge_table(): assert generate_edge_table(results).count('| ETH/BTC |') == 1 assert generate_edge_table(results).count( '| Risk Reward Ratio | Required Risk Reward | Expectancy |') == 1 + + +def test_generate_periodic_breakdown_stats(testdatadir): + filename = testdatadir / "backtest-result_new.json" + bt_data = load_backtest_data(filename).to_dict(orient='records') + + res = generate_periodic_breakdown_stats(bt_data, 'day') + assert isinstance(res, list) + assert len(res) == 21 + day = res[0] + assert 'date' in day + assert 'draws' in day + assert 'loses' in day + assert 'wins' in day + assert 'profit_abs' in day + + # Select empty dataframe! + res = generate_periodic_breakdown_stats([], 'day') + assert res == [] + + +def test__get_resample_from_period(): + + assert _get_resample_from_period('day') == '1d' + assert _get_resample_from_period('week') == '1w' + assert _get_resample_from_period('month') == '1M' + with pytest.raises(ValueError, match=r"Period noooo is not supported."): + _get_resample_from_period('noooo')