Add Tests for AgeFilter caching

closes #5552
This commit is contained in:
Matthias 2021-09-14 06:45:26 +02:00
parent c9ba52d732
commit 3ce5197e8d
4 changed files with 54 additions and 31 deletions

View File

@ -1,8 +1,8 @@
# flake8: noqa: F401 # flake8: noqa: F401
from freqtrade.configuration.PeriodicCache import PeriodicCache
from freqtrade.configuration.check_exchange import check_exchange, remove_credentials from freqtrade.configuration.check_exchange import check_exchange, remove_credentials
from freqtrade.configuration.config_setup import setup_utils_configuration from freqtrade.configuration.config_setup import setup_utils_configuration
from freqtrade.configuration.config_validation import validate_config_consistency from freqtrade.configuration.config_validation import validate_config_consistency
from freqtrade.configuration.configuration import Configuration from freqtrade.configuration.configuration import Configuration
from freqtrade.configuration.PeriodicCache import PeriodicCache
from freqtrade.configuration.timerange import TimeRange from freqtrade.configuration.timerange import TimeRange

View File

@ -8,10 +8,10 @@ from typing import Any, Dict, List, Optional
import arrow import arrow
from pandas import DataFrame from pandas import DataFrame
from freqtrade.configuration import PeriodicCache
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
from freqtrade.misc import plural from freqtrade.misc import plural
from freqtrade.plugins.pairlist.IPairList import IPairList from freqtrade.plugins.pairlist.IPairList import IPairList
from freqtrade.configuration import PeriodicCache
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -26,7 +26,7 @@ class AgeFilter(IPairList):
# Checked symbols cache (dictionary of ticker symbol => timestamp) # Checked symbols cache (dictionary of ticker symbol => timestamp)
self._symbolsChecked: Dict[str, int] = {} self._symbolsChecked: Dict[str, int] = {}
self._too_young_pairs = PeriodicCache(maxsize=1000, ttl=86_400) self._symbolsCheckFailed = PeriodicCache(maxsize=1000, ttl=86_400)
self._min_days_listed = pairlistconfig.get('min_days_listed', 10) self._min_days_listed = pairlistconfig.get('min_days_listed', 10)
self._max_days_listed = pairlistconfig.get('max_days_listed', None) self._max_days_listed = pairlistconfig.get('max_days_listed', None)
@ -73,9 +73,10 @@ class AgeFilter(IPairList):
""" """
needed_pairs = [ needed_pairs = [
(p, '1d') for p in pairlist (p, '1d') for p in pairlist
if p not in self._symbolsChecked and p not in self._too_young_pairs] if p not in self._symbolsChecked and p not in self._symbolsCheckFailed]
if not needed_pairs: if not needed_pairs:
return pairlist # Remove pairs that have been removed before
return [p for p in pairlist if p not in self._symbolsCheckFailed]
logger.info(f"needed pairs {needed_pairs}") logger.info(f"needed pairs {needed_pairs}")
since_days = -( since_days = -(
self._max_days_listed if self._max_days_listed else self._min_days_listed self._max_days_listed if self._max_days_listed else self._min_days_listed
@ -122,6 +123,6 @@ class AgeFilter(IPairList):
" or more than " " or more than "
f"{self._max_days_listed} {plural(self._max_days_listed, 'day')}" f"{self._max_days_listed} {plural(self._max_days_listed, 'day')}"
) if self._max_days_listed else ''), logger.info) ) if self._max_days_listed else ''), logger.info)
self._too_young_pairs[pair] = arrow.utcnow().int_timestamp * 1000 self._symbolsCheckFailed[pair] = arrow.utcnow().int_timestamp * 1000
return False return False
return False return False

View File

@ -4,6 +4,7 @@ import time
from unittest.mock import MagicMock, PropertyMock from unittest.mock import MagicMock, PropertyMock
import pytest import pytest
import time_machine
from freqtrade.constants import AVAILABLE_PAIRLISTS from freqtrade.constants import AVAILABLE_PAIRLISTS
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
@ -815,18 +816,18 @@ def test_agefilter_min_days_listed_too_large(mocker, default_conf, markets, tick
def test_agefilter_caching(mocker, markets, whitelist_conf_agefilter, tickers, ohlcv_history): def test_agefilter_caching(mocker, markets, whitelist_conf_agefilter, tickers, ohlcv_history):
with time_machine.travel("2021-09-01 05:00:00 +00:00") as t:
ohlcv_data = { ohlcv_data = {
('ETH/BTC', '1d'): ohlcv_history, ('ETH/BTC', '1d'): ohlcv_history,
('TKN/BTC', '1d'): ohlcv_history, ('TKN/BTC', '1d'): ohlcv_history,
('LTC/BTC', '1d'): ohlcv_history, ('LTC/BTC', '1d'): ohlcv_history,
('XRP/BTC', '1d'): ohlcv_history.iloc[[0]],
} }
mocker.patch.multiple('freqtrade.exchange.Exchange',
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers
)
mocker.patch.multiple( mocker.patch.multiple(
'freqtrade.exchange.Exchange', 'freqtrade.exchange.Exchange',
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers,
refresh_latest_ohlcv=MagicMock(return_value=ohlcv_data), refresh_latest_ohlcv=MagicMock(return_value=ohlcv_data),
) )
@ -839,9 +840,29 @@ def test_agefilter_caching(mocker, markets, whitelist_conf_agefilter, tickers, o
previous_call_count = freqtrade.exchange.refresh_latest_ohlcv.call_count previous_call_count = freqtrade.exchange.refresh_latest_ohlcv.call_count
freqtrade.pairlists.refresh_pairlist() freqtrade.pairlists.refresh_pairlist()
assert len(freqtrade.pairlists.whitelist) == 3 assert len(freqtrade.pairlists.whitelist) == 3
# Called once for XRP/BTC # Call to XRP/BTC cached
assert freqtrade.exchange.refresh_latest_ohlcv.call_count == previous_call_count
# Move to next day
t.move_to("2021-09-02 01:00:00 +00:00")
freqtrade.pairlists.refresh_pairlist()
assert len(freqtrade.pairlists.whitelist) == 3
assert freqtrade.exchange.refresh_latest_ohlcv.call_count == previous_call_count + 1 assert freqtrade.exchange.refresh_latest_ohlcv.call_count == previous_call_count + 1
# Move another day with fresh mocks (now the pair is old enough)
t.move_to("2021-09-03 01:00:00 +00:00")
# Called once for XRP/BTC
ohlcv_data = {
('ETH/BTC', '1d'): ohlcv_history,
('TKN/BTC', '1d'): ohlcv_history,
('LTC/BTC', '1d'): ohlcv_history,
('XRP/BTC', '1d'): ohlcv_history,
}
mocker.patch('freqtrade.exchange.Exchange.refresh_latest_ohlcv', return_value=ohlcv_data)
freqtrade.pairlists.refresh_pairlist()
assert len(freqtrade.pairlists.whitelist) == 4
# Called once (only for XRP/BTC)
assert freqtrade.exchange.refresh_latest_ohlcv.call_count == 1
def test_OffsetFilter_error(mocker, whitelist_conf) -> None: def test_OffsetFilter_error(mocker, whitelist_conf) -> None:
whitelist_conf['pairlists'] = ( whitelist_conf['pairlists'] = (

View File

@ -1,6 +1,7 @@
from freqtrade.configuration import PeriodicCache
import time_machine import time_machine
from freqtrade.configuration import PeriodicCache
def test_ttl_cache(): def test_ttl_cache():