Merge pull request #12927 from stash86/main-stash
number_assets in RemotePairlist becomes optional
This commit is contained in:
@@ -304,6 +304,8 @@ The optional `mode` option specifies if the pairlist should be used as a `blackl
|
|||||||
|
|
||||||
The optional `processing_mode` option in the RemotePairList configuration determines how the retrieved pairlist is processed. It can have two values: "filter" or "append". The default value is "filter".
|
The optional `processing_mode` option in the RemotePairList configuration determines how the retrieved pairlist is processed. It can have two values: "filter" or "append". The default value is "filter".
|
||||||
|
|
||||||
|
The optional `number_assets` option in the RemotePairList configuration determines how many pairs will be returned if used in whitelist `mode`. By default, all pairs will be returned. In blacklist `mode`, this option will be ignored.
|
||||||
|
|
||||||
In "filter" mode, the retrieved pairlist is used as a filter. Only the pairs present in both the original pairlist and the retrieved pairlist are included in the final pairlist. Other pairs are filtered out.
|
In "filter" mode, the retrieved pairlist is used as a filter. Only the pairs present in both the original pairlist and the retrieved pairlist are included in the final pairlist. Other pairs are filtered out.
|
||||||
|
|
||||||
In "append" mode, the retrieved pairlist is added to the original pairlist. All pairs from both lists are included in the final pairlist without any filtering.
|
In "append" mode, the retrieved pairlist is added to the original pairlist. All pairs from both lists are included in the final pairlist without any filtering.
|
||||||
|
|||||||
@@ -31,12 +31,6 @@ class RemotePairList(IPairList):
|
|||||||
def __init__(self, *args, **kwargs) -> None:
|
def __init__(self, *args, **kwargs) -> None:
|
||||||
super().__init__(*args, **kwargs)
|
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:
|
if "pairlist_url" not in self._pairlistconfig:
|
||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
"`pairlist_url` not specified. Please check your configuration "
|
"`pairlist_url` not specified. Please check your configuration "
|
||||||
@@ -45,7 +39,7 @@ class RemotePairList(IPairList):
|
|||||||
|
|
||||||
self._mode = self._pairlistconfig.get("mode", "whitelist")
|
self._mode = self._pairlistconfig.get("mode", "whitelist")
|
||||||
self._processing_mode = self._pairlistconfig.get("processing_mode", "filter")
|
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._refresh_period: int = self._pairlistconfig.get("refresh_period", 1800)
|
||||||
self._keep_pairlist_on_failure = self._pairlistconfig.get("keep_pairlist_on_failure", True)
|
self._keep_pairlist_on_failure = self._pairlistconfig.get("keep_pairlist_on_failure", True)
|
||||||
self._pair_cache: FtTTLCache = FtTTLCache(maxsize=1, ttl=self._refresh_period)
|
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 = expand_pairlist(pairlist, list(self._exchange.get_markets().keys()))
|
||||||
pairlist = self._whitelist_for_active_markets(pairlist)
|
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:
|
if pairlist:
|
||||||
self._pair_cache["pairlist"] = pairlist.copy()
|
self._pair_cache["pairlist"] = pairlist.copy()
|
||||||
@@ -305,5 +300,6 @@ class RemotePairList(IPairList):
|
|||||||
if filtered:
|
if filtered:
|
||||||
self.log_once(f"Blacklist - Filtered out pairs: {filtered}", logger.info)
|
self.log_once(f"Blacklist - Filtered out pairs: {filtered}", logger.info)
|
||||||
|
|
||||||
merged_list = merged_list[: self._number_pairs]
|
if self._number_pairs and (self._mode == "whitelist"):
|
||||||
|
merged_list = merged_list[: self._number_pairs]
|
||||||
return merged_list
|
return merged_list
|
||||||
|
|||||||
@@ -137,25 +137,6 @@ def test_remote_pairlist_init_no_pairlist_url(mocker, rpl_config):
|
|||||||
get_patched_freqtradebot(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):
|
def test_fetch_pairlist_mock_response_valid(mocker, rpl_config):
|
||||||
rpl_config["pairlists"] = [
|
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"], {})
|
whitelist = remote_pairlist.filter_pairlist(rpl_config["exchange"]["pair_whitelist"], {})
|
||||||
assert whitelist == (["XRP/USDT"] if processing_mode == "filter" else ["ETH/USDT", "XRP/USDT"])
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user