diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 65b4baff2..1ac2b6351 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -173,6 +173,7 @@ class Backtesting: self.disable_database_use() self.init_backtest_detail() self.pairlists = PairListManager(self.exchange, self.config, self.dataprovider) + self.dinamic_pairlist = False self._validate_pairlists_for_backtesting() self.dataprovider.add_pairlisthandler(self.pairlists) @@ -226,6 +227,9 @@ class Backtesting: "PrecisionFilter not allowed for backtesting multiple strategies." ) + if "ShuffleFilter" in self.pairlists.name_list: + self.dinamic_pairlist = True + def log_once(self, msg: str) -> None: """ Partial reimplementation of log_once from the Login mixin. @@ -1582,6 +1586,11 @@ class Backtesting: for current_time in self._time_generator(start_date, end_date): # Loop for each main candle. self.check_abort() + + if self.dinamic_pairlist: + self.pairlists.refresh_pairlist() + pairs = self.pairlists.whitelist + # Reset open trade count for this candle # Critical to avoid exceeding max_open_trades in backtesting # when timeframe-detail is used and trades close within the opening candle. diff --git a/freqtrade/plugins/pairlist/ShuffleFilter.py b/freqtrade/plugins/pairlist/ShuffleFilter.py index be536e705..86d618160 100644 --- a/freqtrade/plugins/pairlist/ShuffleFilter.py +++ b/freqtrade/plugins/pairlist/ShuffleFilter.py @@ -93,6 +93,8 @@ class ShuffleFilter(IPairList): return pairlist_new # Shuffle is done inplace self._random.shuffle(pairlist) - self.__pairlist_cache[pairlist_bef] = pairlist + + if self._config.get("runmode") in (RunMode.LIVE, RunMode.DRY_RUN): + self.__pairlist_cache[pairlist_bef] = pairlist return pairlist diff --git a/tests/plugins/test_pairlist.py b/tests/plugins/test_pairlist.py index f2c3c69e3..ad4ed0f47 100644 --- a/tests/plugins/test_pairlist.py +++ b/tests/plugins/test_pairlist.py @@ -1274,27 +1274,37 @@ def test_ShuffleFilter_init(mocker, whitelist_conf, caplog) -> None: {"method": "StaticPairList"}, {"method": "ShuffleFilter", "seed": 43}, ] - whitelist_conf["runmode"] = "backtest" + whitelist_conf["runmode"] = RunMode.BACKTEST exchange = get_patched_exchange(mocker, whitelist_conf) plm = PairListManager(exchange, whitelist_conf) assert log_has("Backtesting mode detected, applying seed value: 43", caplog) + plm.refresh_pairlist() + pl1 = deepcopy(plm.whitelist) + plm.refresh_pairlist() + assert plm.whitelist != pl1 + assert set(plm.whitelist) == set(pl1) + + caplog.clear() + whitelist_conf["runmode"] = RunMode.DRY_RUN + plm = PairListManager(exchange, whitelist_conf) + assert not log_has("Backtesting mode detected, applying seed value: 42", caplog) + assert log_has("Live mode detected, not applying seed.", caplog) + with time_machine.travel("2021-09-01 05:01:00 +00:00") as t: plm.refresh_pairlist() pl1 = deepcopy(plm.whitelist) plm.refresh_pairlist() assert plm.whitelist == pl1 + target = plm._pairlist_handlers[1]._random + shuffle_mock = mocker.patch.object(target, "shuffle", wraps=target.shuffle) + t.shift(timedelta(minutes=10)) plm.refresh_pairlist() - assert plm.whitelist != pl1 - - caplog.clear() - whitelist_conf["runmode"] = RunMode.DRY_RUN - plm = PairListManager(exchange, whitelist_conf) - assert not log_has("Backtesting mode detected, applying seed value: 42", caplog) - assert log_has("Live mode detected, not applying seed.", caplog) + assert shuffle_mock.call_count == 1 + assert set(plm.whitelist) == set(pl1) @pytest.mark.usefixtures("init_persistence")