Merge pull request #9821 from freqtrade/feat/volumepairlist_caching
improve volumepairlist "advanced filter mode" caching
This commit is contained in:
@@ -2303,6 +2303,66 @@ def test_refresh_latest_ohlcv_cache(mocker, default_conf, candle_type, time_mach
|
||||
assert res[pair2].at[0, 'open']
|
||||
|
||||
|
||||
def test_refresh_ohlcv_with_cache(mocker, default_conf, time_machine) -> None:
|
||||
start = datetime(2021, 8, 1, 0, 0, 0, 0, tzinfo=timezone.utc)
|
||||
ohlcv = generate_test_data_raw('1h', 100, start.strftime('%Y-%m-%d'))
|
||||
time_machine.move_to(start, tick=False)
|
||||
pairs = [
|
||||
('ETH/BTC', '1d', CandleType.SPOT),
|
||||
('TKN/BTC', '1d', CandleType.SPOT),
|
||||
('LTC/BTC', '1d', CandleType.SPOT),
|
||||
('LTC/BTC', '5m', CandleType.SPOT),
|
||||
('LTC/BTC', '1h', CandleType.SPOT),
|
||||
]
|
||||
|
||||
ohlcv_data = {
|
||||
p: ohlcv for p in pairs
|
||||
}
|
||||
ohlcv_mock = mocker.patch(f"{EXMS}.refresh_latest_ohlcv", return_value=ohlcv_data)
|
||||
mocker.patch(f"{EXMS}.ohlcv_candle_limit", return_value=100)
|
||||
exchange = get_patched_exchange(mocker, default_conf)
|
||||
|
||||
assert len(exchange._expiring_candle_cache) == 0
|
||||
|
||||
res = exchange.refresh_ohlcv_with_cache(pairs, start.timestamp())
|
||||
assert ohlcv_mock.call_count == 1
|
||||
assert ohlcv_mock.call_args_list[0][0][0] == pairs
|
||||
assert len(ohlcv_mock.call_args_list[0][0][0]) == 5
|
||||
|
||||
assert len(res) == 5
|
||||
# length of 3 - as we have 3 different timeframes
|
||||
assert len(exchange._expiring_candle_cache) == 3
|
||||
|
||||
ohlcv_mock.reset_mock()
|
||||
res = exchange.refresh_ohlcv_with_cache(pairs, start.timestamp())
|
||||
assert ohlcv_mock.call_count == 0
|
||||
|
||||
# Expire 5m cache
|
||||
time_machine.move_to(start + timedelta(minutes=6), tick=False)
|
||||
|
||||
ohlcv_mock.reset_mock()
|
||||
res = exchange.refresh_ohlcv_with_cache(pairs, start.timestamp())
|
||||
assert ohlcv_mock.call_count == 1
|
||||
assert len(ohlcv_mock.call_args_list[0][0][0]) == 1
|
||||
|
||||
# Expire 5m and 1h cache
|
||||
time_machine.move_to(start + timedelta(hours=2), tick=False)
|
||||
|
||||
ohlcv_mock.reset_mock()
|
||||
res = exchange.refresh_ohlcv_with_cache(pairs, start.timestamp())
|
||||
assert ohlcv_mock.call_count == 1
|
||||
assert len(ohlcv_mock.call_args_list[0][0][0]) == 2
|
||||
|
||||
# Expire all caches
|
||||
time_machine.move_to(start + timedelta(days=1, hours=2), tick=False)
|
||||
|
||||
ohlcv_mock.reset_mock()
|
||||
res = exchange.refresh_ohlcv_with_cache(pairs, start.timestamp())
|
||||
assert ohlcv_mock.call_count == 1
|
||||
assert len(ohlcv_mock.call_args_list[0][0][0]) == 5
|
||||
assert ohlcv_mock.call_args_list[0][0][0] == pairs
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
||||
async def test__async_get_candle_history(default_conf, mocker, caplog, exchange_name):
|
||||
ohlcv = [
|
||||
|
||||
@@ -621,13 +621,20 @@ def test_VolumePairList_whitelist_gen(mocker, whitelist_conf, shitcoinmarkets, t
|
||||
([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume",
|
||||
"lookback_timeframe": "1d", "lookback_period": 6, "refresh_period": 86400}],
|
||||
"BTC", "binance", ['LTC/BTC', 'XRP/BTC', 'ETH/BTC', 'HOT/BTC', 'NEO/BTC']),
|
||||
# VolumePairlist in range mode as filter.
|
||||
# TKN/BTC is removed because it doesn't have enough candles
|
||||
([{"method": "VolumePairList", "number_assets": 5},
|
||||
{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume",
|
||||
"lookback_timeframe": "1d", "lookback_period": 2, "refresh_period": 86400}],
|
||||
"BTC", "binance", ['LTC/BTC', 'XRP/BTC', 'ETH/BTC', 'TKN/BTC', 'HOT/BTC']),
|
||||
# ftx data is already in Quote currency, therefore won't require conversion
|
||||
# ([{"method": "VolumePairList", "number_assets": 5, "sort_key": "quoteVolume",
|
||||
# "lookback_timeframe": "1d", "lookback_period": 1, "refresh_period": 86400}],
|
||||
# "BTC", "ftx", ['HOT/BTC', 'LTC/BTC', 'ETH/BTC', 'TKN/BTC', 'XRP/BTC']),
|
||||
])
|
||||
def test_VolumePairList_range(mocker, whitelist_conf, shitcoinmarkets, tickers, ohlcv_history,
|
||||
pairlists, base_currency, exchange, volumefilter_result) -> None:
|
||||
def test_VolumePairList_range(
|
||||
mocker, whitelist_conf, shitcoinmarkets, tickers, ohlcv_history,
|
||||
pairlists, base_currency, exchange, volumefilter_result, time_machine) -> None:
|
||||
whitelist_conf['pairlists'] = pairlists
|
||||
whitelist_conf['stake_currency'] = base_currency
|
||||
whitelist_conf['exchange']['name'] = exchange
|
||||
@@ -686,23 +693,36 @@ def test_VolumePairList_range(mocker, whitelist_conf, shitcoinmarkets, tickers,
|
||||
get_tickers=tickers,
|
||||
markets=PropertyMock(return_value=shitcoinmarkets)
|
||||
)
|
||||
|
||||
start_dt = dt_now()
|
||||
time_machine.move_to(start_dt)
|
||||
# remove ohlcv when looback_timeframe != 1d
|
||||
# to enforce fallback to ticker data
|
||||
if 'lookback_timeframe' in pairlists[0]:
|
||||
if pairlists[0]['lookback_timeframe'] != '1d':
|
||||
ohlcv_data = []
|
||||
ohlcv_data = {}
|
||||
|
||||
mocker.patch.multiple(
|
||||
EXMS,
|
||||
refresh_latest_ohlcv=MagicMock(return_value=ohlcv_data),
|
||||
)
|
||||
ohclv_mock = mocker.patch(f"{EXMS}.refresh_latest_ohlcv", return_value=ohlcv_data)
|
||||
|
||||
freqtrade.pairlists.refresh_pairlist()
|
||||
whitelist = freqtrade.pairlists.whitelist
|
||||
assert ohclv_mock.call_count == 1
|
||||
|
||||
assert isinstance(whitelist, list)
|
||||
assert whitelist == volumefilter_result
|
||||
# Test caching
|
||||
ohclv_mock.reset_mock()
|
||||
freqtrade.pairlists.refresh_pairlist()
|
||||
# in "filter" mode, caching is disabled.
|
||||
assert ohclv_mock.call_count == 0
|
||||
whitelist = freqtrade.pairlists.whitelist
|
||||
assert whitelist == volumefilter_result
|
||||
|
||||
time_machine.move_to(start_dt + timedelta(days=2))
|
||||
ohclv_mock.reset_mock()
|
||||
freqtrade.pairlists.refresh_pairlist()
|
||||
assert ohclv_mock.call_count == 1
|
||||
whitelist = freqtrade.pairlists.whitelist
|
||||
assert whitelist == volumefilter_result
|
||||
|
||||
|
||||
def test_PrecisionFilter_error(mocker, whitelist_conf) -> None:
|
||||
|
||||
Reference in New Issue
Block a user