From a2c3729254728ebc1520bd48945ccc6f6f3c9657 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 8 Sep 2025 19:52:15 +0200 Subject: [PATCH 1/4] feat: Override order types for lookahead analysis this avoids false positives - but could cause false-negatives if the problem is in a pricing callback. `--allow-limit-orders` can re-allow limit orders to test for this scenario. part of #12168 --- freqtrade/commands/arguments.py | 7 ++++++- freqtrade/commands/cli_options.py | 8 ++++++++ freqtrade/optimize/analysis/lookahead_helpers.py | 11 +++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/freqtrade/commands/arguments.py b/freqtrade/commands/arguments.py index 17d8f43d7..8c3ddbcdb 100755 --- a/freqtrade/commands/arguments.py +++ b/freqtrade/commands/arguments.py @@ -260,7 +260,12 @@ ARGS_LOOKAHEAD_ANALYSIS = [ a for a in ARGS_BACKTEST if a not in ("position_stacking", "backtest_cache", "backtest_breakdown", "backtest_notes") -] + ["minimum_trade_amount", "targeted_trade_amount", "lookahead_analysis_exportfilename"] +] + [ + "minimum_trade_amount", + "targeted_trade_amount", + "lookahead_analysis_exportfilename", + "lookahead_allow_limit_orders", +] ARGS_RECURSIVE_ANALYSIS = ["timeframe", "timerange", "dataformat_ohlcv", "pairs", "startup_candle"] diff --git a/freqtrade/commands/cli_options.py b/freqtrade/commands/cli_options.py index 62a007f59..c00af1e97 100755 --- a/freqtrade/commands/cli_options.py +++ b/freqtrade/commands/cli_options.py @@ -806,6 +806,14 @@ AVAILABLE_CLI_OPTIONS = { help="Specify startup candles to be checked (`199`, `499`, `999`, `1999`).", nargs="+", ), + "lookahead_allow_limit_orders": Arg( + "--allow-limit-orders", + help=( + "Allow limit orders in lookahead analysis (could cause false positives " + "in lookahead analysis results)." + ), + action="store_true", + ), "show_sensitive": Arg( "--show-sensitive", help="Show secrets in the output.", diff --git a/freqtrade/optimize/analysis/lookahead_helpers.py b/freqtrade/optimize/analysis/lookahead_helpers.py index bc892727a..c9434c3d8 100644 --- a/freqtrade/optimize/analysis/lookahead_helpers.py +++ b/freqtrade/optimize/analysis/lookahead_helpers.py @@ -147,6 +147,17 @@ class LookaheadAnalysisSubFunctions: "Protections were enabled. " "Disabling protections now since they can produce false positives." ) + if not config.get("lookahead_allow_limit_orders", False): + logger.info("Forced order_types to market orders.") + config["order_types"] = { + "entry": "market", + "exit": "market", + "stoploss": "market", + "stoploss_on_exchange": False, + } + else: + logger.info("Using configured order_types, skipping order_types override.") + if config["targeted_trade_amount"] < config["minimum_trade_amount"]: # this combo doesn't make any sense. raise OperationalException( From 7ae89711dd1890666fe6f306abab122da330f053 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 8 Sep 2025 19:52:38 +0200 Subject: [PATCH 2/4] docs: update docs for lookahead analysis override --- docs/lookahead-analysis.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/lookahead-analysis.md b/docs/lookahead-analysis.md index d8fb8b7bb..cf2eb9140 100644 --- a/docs/lookahead-analysis.md +++ b/docs/lookahead-analysis.md @@ -22,6 +22,7 @@ This is done by not looking at the strategy code itself, but at changed indicato - `--dry-run-wallet` is forced to be basically infinite (1 billion). - `--stake-amount` is forced to be a static 10000 (10k). - `--enable-protections` is forced to be off. +- `order_types` are forced to be "market" (late entries) unless `--lookahead-allow-limit-orders` is set. These are set to avoid users accidentally generating false positives. @@ -99,6 +100,9 @@ This would lead to a false-negative, i.e. the strategy will be reported as non-b Please don't use any options like enabling position stacking as this will distort the number of checked signals. If you decide to do so, then make doubly sure that you won't ever run out of `max_open_trades` slots, and that you have enough capital in the backtest wallet configuration. +- limit orders in combination with `custom_entry_price()` and `custom_exit_price()` callbacks can cause late / delayed entries and exists, causing false positives. +To avoid this - market orders are forced for this command. This implicitly means that `custom_entry_price()` and `custom_exit_price()` callbacks are not called. +Using `--lookahead-allow-limit-orders` will skip the override and use your configured order types - however has shown to eventually produce false positives. - In the results table, the `biased_indicators` column will falsely flag FreqAI target indicators defined in `set_freqai_targets()` as biased. **These are not biased and can safely be ignored.** From 7b8f0583a4f2f1288ee486a946c9332974ec1d83 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 8 Sep 2025 20:02:09 +0200 Subject: [PATCH 3/4] test: add test for order_type force behavior --- tests/optimize/test_lookahead_analysis.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/optimize/test_lookahead_analysis.py b/tests/optimize/test_lookahead_analysis.py index 3ecabc0b1..2b8331608 100644 --- a/tests/optimize/test_lookahead_analysis.py +++ b/tests/optimize/test_lookahead_analysis.py @@ -123,7 +123,7 @@ def test_lookahead_helper_no_strategy_defined(lookahead_conf): LookaheadAnalysisSubFunctions.start(conf) -def test_lookahead_helper_start(lookahead_conf, mocker) -> None: +def test_lookahead_helper_start(lookahead_conf, mocker, caplog) -> None: single_mock = MagicMock() text_table_mock = MagicMock() mocker.patch.multiple( @@ -131,13 +131,22 @@ def test_lookahead_helper_start(lookahead_conf, mocker) -> None: initialize_single_lookahead_analysis=single_mock, text_table_lookahead_analysis_instances=text_table_mock, ) - LookaheadAnalysisSubFunctions.start(lookahead_conf) + LookaheadAnalysisSubFunctions.start(deepcopy(lookahead_conf)) assert single_mock.call_count == 1 assert text_table_mock.call_count == 1 + assert log_has_re("Forced order_types to market orders.", caplog) + assert single_mock.call_args_list[0][0][0]["order_types"]["entry"] == "market" single_mock.reset_mock() text_table_mock.reset_mock() + lookahead_conf["lookahead_allow_limit_orders"] = True + LookaheadAnalysisSubFunctions.start(lookahead_conf) + assert single_mock.call_count == 1 + assert text_table_mock.call_count == 1 + assert log_has_re("Using configured order_types, skipping order_types override.", caplog) + assert "order_types" not in single_mock.call_args_list[0][0][0] + @pytest.mark.parametrize( "indicators, expected_caption_text", From b35172a3b86b9df7696f66d7482177986b908213 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 8 Sep 2025 20:06:43 +0200 Subject: [PATCH 4/4] chore: export lookahead command partial --- docs/commands/lookahead-analysis.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/commands/lookahead-analysis.md b/docs/commands/lookahead-analysis.md index 880c41ce1..922e1f757 100644 --- a/docs/commands/lookahead-analysis.md +++ b/docs/commands/lookahead-analysis.md @@ -21,6 +21,7 @@ usage: freqtrade lookahead-analysis [-h] [-v] [--no-color] [--logfile FILE] [--minimum-trade-amount INT] [--targeted-trade-amount INT] [--lookahead-analysis-exportfilename LOOKAHEAD_ANALYSIS_EXPORTFILENAME] + [--allow-limit-orders] options: -h, --help show this help message and exit @@ -79,6 +80,8 @@ options: --lookahead-analysis-exportfilename LOOKAHEAD_ANALYSIS_EXPORTFILENAME Use this csv-filename to store lookahead-analysis- results + --allow-limit-orders Allow limit orders in lookahead analysis (could cause + false positives in lookahead analysis results). Common arguments: -v, --verbose Verbose mode (-vv for more, -vvv to get all messages).