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). 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.** 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( 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",