diff --git a/freqtrade/plugins/pairlist/MarketCapFilter.py b/freqtrade/plugins/pairlist/MarketCapFilter.py index c9dfa7769..1231d7752 100644 --- a/freqtrade/plugins/pairlist/MarketCapFilter.py +++ b/freqtrade/plugins/pairlist/MarketCapFilter.py @@ -21,7 +21,7 @@ from pycoingecko import CoinGeckoAPI logger = logging.getLogger(__name__) -SORT_VALUES = ['quoteVolume'] +MODE_VALUES = ['top_rank', 'total_assets'] class MarketCapFilter(IPairList): @@ -33,23 +33,28 @@ class MarketCapFilter(IPairList): pairlist_pos: int) -> None: super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos) - if 'max_rank' not in self._pairlistconfig: + if 'limit' not in self._pairlistconfig: raise OperationalException( - '`max_rank` not specified. Please check your configuration ' - 'for "pairlist.config.max_rank"') + '`limit` not specified. Please check your configuration ' + 'for "pairlist.config.limit"') self._stake_currency = config['stake_currency'] - self._max_rank = self._pairlistconfig['max_rank'] + self._mode = self._pairlistconfig.get('mode', 'top_rank') + self._limit = self._pairlistconfig['limit'] self._refresh_period = self._pairlistconfig.get('refresh_period', 86400) self._marketcap_cache: TTLCache = TTLCache(maxsize=1, ttl=self._refresh_period) self._def_candletype = self._config['candle_type_def'] self._coingekko: CoinGeckoAPI = CoinGeckoAPI() - if self._max_rank > 250: + if self._limit > 250: raise OperationalException( "This filter only support up to rank 250." ) + if not self._validate_keys(self._mode): + raise OperationalException( + f'key {self._mode} not in {MODE_VALUES}') + @property def needstickers(self) -> bool: @@ -61,13 +66,13 @@ class MarketCapFilter(IPairList): return False def _validate_keys(self, key): - return key in SORT_VALUES + return key in MODE_VALUES def short_desc(self) -> str: """ Short whitelist method description - used for startup-messages """ - return f"{self.name} - Only use top {self._pairlistconfig['max_rank']} market cap pairs." + return f"{self.name} - Only use top {self._pairlistconfig['limit']} market cap pairs." @staticmethod def description() -> str: @@ -76,11 +81,18 @@ class MarketCapFilter(IPairList): @staticmethod def available_parameters() -> Dict[str, PairlistParameter]: return { - "max_rank": { + "limit": { "type": "number", "default": 30, "description": "Max market cap rank", - "help": "Only use assets that ranked within top max_rank market cap", + "help": "Only use assets with high market cap rank", + }, + "mode": { + "type": "option", + "default": "top_rank", + "options": MODE_VALUES, + "description": "Mode of number", + "help": "How to interpret the number", }, "refresh_period": { "type": "number", @@ -156,24 +168,24 @@ class MarketCapFilter(IPairList): if can_filter: filtered_pairlist = [] - # option A - # top_marketcap = marketcap_list[:self._max_rank:] + if self._mode == 'top_rank': + top_marketcap = marketcap_list[:self._limit:] - # for pair in pairlist: - # base = pair.split('/')[0] - # if base.lower() in top_marketcap: - # filtered_pairlist.append(pair) - # else: - # logger.info(f"Remove {pair} from whitelist because it's not in " - # f"top {self._max_rank} market cap") + for pair in pairlist: + base = pair.split('/')[0] + if base.lower() in top_marketcap: + filtered_pairlist.append(pair) + else: + logger.info(f"Remove {pair} from whitelist because it's not ranked " + f"within top {self._limit} market cap") - # option B - for mc_pair in marketcap_list: - test_pair = f"{mc_pair.upper()}/{self._stake_currency.upper()}" - if test_pair in pairlist: - filtered_pairlist.append(test_pair) - if len(filtered_pairlist) == self._max_rank: - break + else: + for mc_pair in marketcap_list: + test_pair = f"{mc_pair.upper()}/{self._stake_currency.upper()}" + if test_pair in pairlist: + filtered_pairlist.append(test_pair) + if len(filtered_pairlist) == self._limit: + break if len(filtered_pairlist) > 0: return filtered_pairlist