diff --git a/freqtrade/pairlist/AgeFilter.py b/freqtrade/pairlist/AgeFilter.py index 21e1b1a01..cc61fd4c3 100644 --- a/freqtrade/pairlist/AgeFilter.py +++ b/freqtrade/pairlist/AgeFilter.py @@ -2,9 +2,11 @@ Minimum age (days listed) pair list filter """ import logging -from typing import Any, Dict, List +from copy import deepcopy +from typing import Any, Dict, List, Optional import arrow +from pandas import DataFrame from freqtrade.exceptions import OperationalException from freqtrade.misc import plural @@ -64,17 +66,34 @@ class AgeFilter(IPairList): .shift(days=-self._min_days_listed - 1) .float_timestamp) * 1000 candles = self._exchange.refresh_latest_ohlcv(needed_pairs, since_ms=since_ms, cache=False) - pairlist_new = [] if self._enabled: - for p, _ in needed_pairs: + for p in deepcopy(pairlist): + daily_candles = candles[(p, '1d')] if (p, '1d') in candles else None + if not self._validate_pair_loc(p, daily_candles): + pairlist.remove(p) + logger.info(f"Validated {len(pairlist)} pairs.") + return pairlist - age = len(candles[(p, '1d')]) if (p, '1d') in candles else 0 - if age > self._min_days_listed: - pairlist_new.append(p) - self._symbolsChecked[p] = int(arrow.utcnow().float_timestamp) * 1000 - else: - self.log_once(f"Removed {p} from whitelist, because age " - f"{age} is less than {self._min_days_listed} " - f"{plural(self._min_days_listed, 'day')}", logger.info) - logger.info(f"Validated {len(pairlist_new)} pairs.") - return pairlist_new + def _validate_pair_loc(self, pair: str, daily_candles: Optional[DataFrame]) -> bool: + """ + Validate age for the ticker + :param pair: Pair that's currently validated + :param ticker: ticker dict as returned from ccxt.load_markets() + :return: True if the pair can stay, false if it should be removed + """ + # Check symbol in cache + if pair in self._symbolsChecked: + return True + + if daily_candles is not None: + if len(daily_candles) > self._min_days_listed: + # We have fetched at least the minimum required number of daily candles + # Add to cache, store the time we last checked this symbol + self._symbolsChecked[pair] = int(arrow.utcnow().float_timestamp) * 1000 + return True + else: + self.log_once(f"Removed {pair} from whitelist, because age " + f"{len(daily_candles)} is less than {self._min_days_listed} " + f"{plural(self._min_days_listed, 'day')}", logger.info) + return False + return False diff --git a/tests/plugins/test_pairlist.py b/tests/plugins/test_pairlist.py index 171f0e037..c4b370e15 100644 --- a/tests/plugins/test_pairlist.py +++ b/tests/plugins/test_pairlist.py @@ -588,7 +588,6 @@ def test_agefilter_caching(mocker, markets, whitelist_conf_agefilter, tickers, o ('ETH/BTC', '1d'): ohlcv_history, ('TKN/BTC', '1d'): ohlcv_history, ('LTC/BTC', '1d'): ohlcv_history, - ('XRP/BTC', '1d'): ohlcv_history, } mocker.patch.multiple('freqtrade.exchange.Exchange', markets=PropertyMock(return_value=markets), @@ -603,12 +602,15 @@ def test_agefilter_caching(mocker, markets, whitelist_conf_agefilter, tickers, o freqtrade = get_patched_freqtradebot(mocker, whitelist_conf_agefilter) assert freqtrade.exchange.refresh_latest_ohlcv.call_count == 0 freqtrade.pairlists.refresh_pairlist() + assert len(freqtrade.pairlists.whitelist) == 3 assert freqtrade.exchange.refresh_latest_ohlcv.call_count > 0 + # freqtrade.config['exchange']['pair_whitelist'].append('HOT/BTC') previous_call_count = freqtrade.exchange.refresh_latest_ohlcv.call_count freqtrade.pairlists.refresh_pairlist() - # Should not have increased since first call. - assert freqtrade.exchange.refresh_latest_ohlcv.call_count == previous_call_count + assert len(freqtrade.pairlists.whitelist) == 3 + # Called once for XRP/BTC + assert freqtrade.exchange.refresh_latest_ohlcv.call_count == previous_call_count + 1 def test_rangestabilityfilter_checks(mocker, default_conf, markets, tickers):