diff --git a/freqtrade/plugins/pairlist/RemotePairList.py b/freqtrade/plugins/pairlist/RemotePairList.py index 0966663a3..8af7a07fd 100644 --- a/freqtrade/plugins/pairlist/RemotePairList.py +++ b/freqtrade/plugins/pairlist/RemotePairList.py @@ -31,12 +31,6 @@ class RemotePairList(IPairList): def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) - if "number_assets" not in self._pairlistconfig: - raise OperationalException( - "`number_assets` not specified. Please check your configuration " - 'for "pairlist.config.number_assets"' - ) - if "pairlist_url" not in self._pairlistconfig: raise OperationalException( "`pairlist_url` not specified. Please check your configuration " @@ -45,7 +39,7 @@ class RemotePairList(IPairList): self._mode = self._pairlistconfig.get("mode", "whitelist") self._processing_mode = self._pairlistconfig.get("processing_mode", "filter") - self._number_pairs = self._pairlistconfig["number_assets"] + self._number_pairs: int | None = self._pairlistconfig.get("number_assets", None) self._refresh_period: int = self._pairlistconfig.get("refresh_period", 1800) self._keep_pairlist_on_failure = self._pairlistconfig.get("keep_pairlist_on_failure", True) self._pair_cache: FtTTLCache = FtTTLCache(maxsize=1, ttl=self._refresh_period) @@ -248,7 +242,8 @@ class RemotePairList(IPairList): pairlist = expand_pairlist(pairlist, list(self._exchange.get_markets().keys())) pairlist = self._whitelist_for_active_markets(pairlist) - pairlist = pairlist[: self._number_pairs] + if self._number_pairs and (self._mode == "whitelist"): + pairlist = pairlist[: self._number_pairs] if pairlist: self._pair_cache["pairlist"] = pairlist.copy() @@ -305,5 +300,6 @@ class RemotePairList(IPairList): if filtered: self.log_once(f"Blacklist - Filtered out pairs: {filtered}", logger.info) - merged_list = merged_list[: self._number_pairs] + if self._number_pairs: + merged_list = merged_list[: self._number_pairs] return merged_list diff --git a/tests/plugins/test_remotepairlist.py b/tests/plugins/test_remotepairlist.py index 2c1e80bf4..9f4459904 100644 --- a/tests/plugins/test_remotepairlist.py +++ b/tests/plugins/test_remotepairlist.py @@ -137,25 +137,6 @@ def test_remote_pairlist_init_no_pairlist_url(mocker, rpl_config): get_patched_freqtradebot(mocker, rpl_config) -def test_remote_pairlist_init_no_number_assets(mocker, rpl_config): - rpl_config["pairlists"] = [ - { - "method": "RemotePairList", - "pairlist_url": "http://example.com/pairlist", - "keep_pairlist_on_failure": True, - } - ] - - get_patched_exchange(mocker, rpl_config) - - with pytest.raises( - OperationalException, - match=r"`number_assets` not specified. " - 'Please check your configuration for "pairlist.config.number_assets"', - ): - get_patched_freqtradebot(mocker, rpl_config) - - def test_fetch_pairlist_mock_response_valid(mocker, rpl_config): rpl_config["pairlists"] = [ { @@ -341,3 +322,60 @@ def test_remote_pairlist_whitelist(mocker, rpl_config, processing_mode, markets, whitelist = remote_pairlist.filter_pairlist(rpl_config["exchange"]["pair_whitelist"], {}) assert whitelist == (["XRP/USDT"] if processing_mode == "filter" else ["ETH/USDT", "XRP/USDT"]) + + +@pytest.mark.parametrize( + "number_assets, result", + [ + (1, ["ETH/USDT"]), + (2, ["ETH/USDT", "XRP/USDT"]), + (500, ["ETH/USDT", "XRP/USDT"]), + (None, ["ETH/USDT", "XRP/USDT"]), + ], +) +def test_remote_pairlist_whitelist_number_assets( + mocker, rpl_config, number_assets, result, markets, tickers +): + mock_response = MagicMock() + + mock_response.json.return_value = { + "pairs": ["ETH/USDT", "XRP/USDT", "TKN/USDT"], + "refresh_period": 60, + } + + mock_response.headers = {"content-type": "application/json"} + + rpl_config["pairlists"] = [ + { + "method": "RemotePairList", + "mode": "whitelist", + "pairlist_url": "http://example.com/pairlist", + "number_assets": number_assets, + }, + ] + + mocker.patch.multiple( + EXMS, + markets=PropertyMock(return_value=markets), + exchange_has=MagicMock(return_value=True), + get_tickers=tickers, + ) + + mocker.patch( + "freqtrade.plugins.pairlist.RemotePairList.requests.get", return_value=mock_response + ) + + exchange = get_patched_exchange(mocker, rpl_config) + + pairlistmanager = PairListManager(exchange, rpl_config) + + remote_pairlist = RemotePairList( + exchange, pairlistmanager, rpl_config, rpl_config["pairlists"][0], 0 + ) + + pairs, _ = remote_pairlist.fetch_pairlist() + + assert pairs == ["ETH/USDT", "XRP/USDT", "TKN/USDT"] + + whitelist = remote_pairlist.filter_pairlist(rpl_config["exchange"]["pair_whitelist"], {}) + assert whitelist == result