From a10b2d003f99f684e2457724e95547e680e4d05c Mon Sep 17 00:00:00 2001 From: Matthias Date: Sun, 9 Oct 2022 14:36:12 +0200 Subject: [PATCH] Add freqai timeframe validation (incl. test) closes #7543 --- freqtrade/configuration/config_validation.py | 21 ++++++++++++++++ tests/freqai/test_freqai_backtesting.py | 2 +- tests/test_configuration.py | 25 ++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py index 7055d9551..98f69c030 100644 --- a/freqtrade/configuration/config_validation.py +++ b/freqtrade/configuration/config_validation.py @@ -86,6 +86,7 @@ def validate_config_consistency(conf: Dict[str, Any], preliminary: bool = False) _validate_unlimited_amount(conf) _validate_ask_orderbook(conf) _validate_freqai_hyperopt(conf) + _validate_freqai_include_timeframes(conf) _validate_consumers(conf) validate_migrated_strategy_settings(conf) @@ -334,6 +335,26 @@ def _validate_freqai_hyperopt(conf: Dict[str, Any]) -> None: 'Using analyze-per-epoch parameter is not supported with a FreqAI strategy.') +def _validate_freqai_include_timeframes(conf: Dict[str, Any]) -> None: + freqai_enabled = conf.get('freqai', {}).get('enabled', False) + if freqai_enabled: + main_tf = conf.get('timeframe', '5m') + freqai_include_timeframes = conf.get('freqai', {}).get('feature_parameters', {} + ).get('include_timeframes', []) + + from freqtrade.exchange import timeframe_to_seconds + main_tf_s = timeframe_to_seconds(main_tf) + offending_lines = [] + for tf in freqai_include_timeframes: + tf_s = timeframe_to_seconds(tf) + if tf_s < main_tf_s: + offending_lines.append(tf) + if offending_lines: + raise OperationalException( + f"Main timeframe of {main_tf} must be smaller or equal to FreqAI " + f"`include_timeframes`.Offending include-timeframes: {', '.join(offending_lines)}") + + def _validate_consumers(conf: Dict[str, Any]) -> None: emc_conf = conf.get('external_message_consumer', {}) if emc_conf.get('enabled', False): diff --git a/tests/freqai/test_freqai_backtesting.py b/tests/freqai/test_freqai_backtesting.py index b1881b2f5..5b9d3aefd 100644 --- a/tests/freqai/test_freqai_backtesting.py +++ b/tests/freqai/test_freqai_backtesting.py @@ -26,7 +26,7 @@ def test_freqai_backtest_start_backtest_list(freqai_conf, mocker, testdatadir, c '--config', 'config.json', '--datadir', str(testdatadir), '--strategy-path', str(Path(__file__).parents[1] / 'strategy/strats'), - '--timeframe', '1h', + '--timeframe', '1m', '--strategy-list', CURRENT_TEST_STRATEGY ] args = get_args(args) diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 2336e3585..ed3c84b1e 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -1028,6 +1028,31 @@ def test__validate_pricing_rules(default_conf, caplog) -> None: validate_config_consistency(conf) +def test__validate_freqai_include_timeframes(default_conf, caplog) -> None: + conf = deepcopy(default_conf) + conf.update({ + "freqai": { + "enabled": True, + "feature_parameters": { + "include_timeframes": ["1m", "5m"], + "include_corr_pairlist": [], + }, + "data_split_parameters": {}, + "model_training_parameters": {} + } + }) + with pytest.raises(OperationalException, match=r"Main timeframe of .*"): + validate_config_consistency(conf) + # Validation pass + conf.update({'timeframe': '1m'}) + validate_config_consistency(conf) + conf.update({'analyze_per_epoch': True}) + + with pytest.raises(OperationalException, + match=r"Using analyze-per-epoch .* not supported with a FreqAI strategy."): + validate_config_consistency(conf) + + def test__validate_consumers(default_conf, caplog) -> None: conf = deepcopy(default_conf) conf.update({