mirror of
https://github.com/freqtrade/freqtrade.git
synced 2025-12-16 12:51:14 +00:00
Fix ShuffleFilter behavior in backtesting
This commit is contained in:
@@ -173,6 +173,7 @@ class Backtesting:
|
|||||||
self.disable_database_use()
|
self.disable_database_use()
|
||||||
self.init_backtest_detail()
|
self.init_backtest_detail()
|
||||||
self.pairlists = PairListManager(self.exchange, self.config, self.dataprovider)
|
self.pairlists = PairListManager(self.exchange, self.config, self.dataprovider)
|
||||||
|
self.dinamic_pairlist = False
|
||||||
self._validate_pairlists_for_backtesting()
|
self._validate_pairlists_for_backtesting()
|
||||||
|
|
||||||
self.dataprovider.add_pairlisthandler(self.pairlists)
|
self.dataprovider.add_pairlisthandler(self.pairlists)
|
||||||
@@ -226,6 +227,9 @@ class Backtesting:
|
|||||||
"PrecisionFilter not allowed for backtesting multiple strategies."
|
"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:
|
def log_once(self, msg: str) -> None:
|
||||||
"""
|
"""
|
||||||
Partial reimplementation of log_once from the Login mixin.
|
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):
|
for current_time in self._time_generator(start_date, end_date):
|
||||||
# Loop for each main candle.
|
# Loop for each main candle.
|
||||||
self.check_abort()
|
self.check_abort()
|
||||||
|
|
||||||
|
if self.dinamic_pairlist:
|
||||||
|
self.pairlists.refresh_pairlist()
|
||||||
|
pairs = self.pairlists.whitelist
|
||||||
|
|
||||||
# Reset open trade count for this candle
|
# Reset open trade count for this candle
|
||||||
# Critical to avoid exceeding max_open_trades in backtesting
|
# Critical to avoid exceeding max_open_trades in backtesting
|
||||||
# when timeframe-detail is used and trades close within the opening candle.
|
# when timeframe-detail is used and trades close within the opening candle.
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ class ShuffleFilter(IPairList):
|
|||||||
return pairlist_new
|
return pairlist_new
|
||||||
# Shuffle is done inplace
|
# Shuffle is done inplace
|
||||||
self._random.shuffle(pairlist)
|
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
|
return pairlist
|
||||||
|
|||||||
@@ -1274,27 +1274,37 @@ def test_ShuffleFilter_init(mocker, whitelist_conf, caplog) -> None:
|
|||||||
{"method": "StaticPairList"},
|
{"method": "StaticPairList"},
|
||||||
{"method": "ShuffleFilter", "seed": 43},
|
{"method": "ShuffleFilter", "seed": 43},
|
||||||
]
|
]
|
||||||
whitelist_conf["runmode"] = "backtest"
|
whitelist_conf["runmode"] = RunMode.BACKTEST
|
||||||
|
|
||||||
exchange = get_patched_exchange(mocker, whitelist_conf)
|
exchange = get_patched_exchange(mocker, whitelist_conf)
|
||||||
plm = PairListManager(exchange, whitelist_conf)
|
plm = PairListManager(exchange, whitelist_conf)
|
||||||
assert log_has("Backtesting mode detected, applying seed value: 43", caplog)
|
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:
|
with time_machine.travel("2021-09-01 05:01:00 +00:00") as t:
|
||||||
plm.refresh_pairlist()
|
plm.refresh_pairlist()
|
||||||
pl1 = deepcopy(plm.whitelist)
|
pl1 = deepcopy(plm.whitelist)
|
||||||
plm.refresh_pairlist()
|
plm.refresh_pairlist()
|
||||||
assert plm.whitelist == pl1
|
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))
|
t.shift(timedelta(minutes=10))
|
||||||
plm.refresh_pairlist()
|
plm.refresh_pairlist()
|
||||||
assert plm.whitelist != pl1
|
assert shuffle_mock.call_count == 1
|
||||||
|
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)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("init_persistence")
|
@pytest.mark.usefixtures("init_persistence")
|
||||||
|
|||||||
Reference in New Issue
Block a user