Merge pull request #7867 from Bloodhunter4rc/remotepairlist
Add Remotepairlist
This commit is contained in:
@@ -22,6 +22,11 @@ from tests.conftest import (create_mock_trades_usdt, get_patched_exchange, get_p
|
||||
log_has, log_has_re, num_log_has)
|
||||
|
||||
|
||||
# Exclude RemotePairList from tests.
|
||||
# It has a mandatory parameter, and requires special handling, which happens in test_remotepairlist.
|
||||
TESTABLE_PAIRLISTS = [p for p in AVAILABLE_PAIRLISTS if p not in ['RemotePairList']]
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def whitelist_conf(default_conf):
|
||||
default_conf['stake_currency'] = 'BTC'
|
||||
@@ -824,7 +829,7 @@ def test_pair_whitelist_not_supported_Spread(mocker, default_conf, tickers) -> N
|
||||
get_patched_freqtradebot(mocker, default_conf)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("pairlist", AVAILABLE_PAIRLISTS)
|
||||
@pytest.mark.parametrize("pairlist", TESTABLE_PAIRLISTS)
|
||||
def test_pairlist_class(mocker, whitelist_conf, markets, pairlist):
|
||||
whitelist_conf['pairlists'][0]['method'] = pairlist
|
||||
mocker.patch.multiple('freqtrade.exchange.Exchange',
|
||||
@@ -839,7 +844,7 @@ def test_pairlist_class(mocker, whitelist_conf, markets, pairlist):
|
||||
assert isinstance(freqtrade.pairlists.blacklist, list)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("pairlist", AVAILABLE_PAIRLISTS)
|
||||
@pytest.mark.parametrize("pairlist", TESTABLE_PAIRLISTS)
|
||||
@pytest.mark.parametrize("whitelist,log_message", [
|
||||
(['ETH/BTC', 'TKN/BTC'], ""),
|
||||
# TRX/ETH not in markets
|
||||
@@ -872,7 +877,7 @@ def test__whitelist_for_active_markets(mocker, whitelist_conf, markets, pairlist
|
||||
assert log_message in caplog.text
|
||||
|
||||
|
||||
@pytest.mark.parametrize("pairlist", AVAILABLE_PAIRLISTS)
|
||||
@pytest.mark.parametrize("pairlist", TESTABLE_PAIRLISTS)
|
||||
def test__whitelist_for_active_markets_empty(mocker, whitelist_conf, pairlist, tickers):
|
||||
whitelist_conf['pairlists'][0]['method'] = pairlist
|
||||
|
||||
|
185
tests/plugins/test_remotepairlist.py
Normal file
185
tests/plugins/test_remotepairlist.py
Normal file
@@ -0,0 +1,185 @@
|
||||
import json
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
from freqtrade.exceptions import OperationalException
|
||||
from freqtrade.plugins.pairlist.RemotePairList import RemotePairList
|
||||
from freqtrade.plugins.pairlistmanager import PairListManager
|
||||
from tests.conftest import get_patched_exchange, get_patched_freqtradebot, log_has
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def rpl_config(default_conf):
|
||||
default_conf['stake_currency'] = 'USDT'
|
||||
|
||||
default_conf['exchange']['pair_whitelist'] = [
|
||||
'ETH/USDT',
|
||||
'BTC/USDT',
|
||||
]
|
||||
default_conf['exchange']['pair_blacklist'] = [
|
||||
'BLK/USDT'
|
||||
]
|
||||
return default_conf
|
||||
|
||||
|
||||
def test_gen_pairlist_with_local_file(mocker, rpl_config):
|
||||
|
||||
mock_file = MagicMock()
|
||||
mock_file.read.return_value = '{"pairs": ["TKN/USDT","ETH/USDT","NANO/USDT"]}'
|
||||
mocker.patch('freqtrade.plugins.pairlist.RemotePairList.open', return_value=mock_file)
|
||||
|
||||
mock_file_path = mocker.patch('freqtrade.plugins.pairlist.RemotePairList.Path')
|
||||
mock_file_path.exists.return_value = True
|
||||
|
||||
jsonparse = json.loads(mock_file.read.return_value)
|
||||
mocker.patch('freqtrade.plugins.pairlist.RemotePairList.json.load', return_value=jsonparse)
|
||||
|
||||
rpl_config['pairlists'] = [
|
||||
{
|
||||
"method": "RemotePairList",
|
||||
'number_assets': 2,
|
||||
'refresh_period': 1800,
|
||||
'keep_pairlist_on_failure': True,
|
||||
'pairlist_url': 'file:///pairlist.json',
|
||||
'bearer_token': '',
|
||||
'read_timeout': 60
|
||||
}
|
||||
]
|
||||
|
||||
exchange = get_patched_exchange(mocker, rpl_config)
|
||||
pairlistmanager = PairListManager(exchange, rpl_config)
|
||||
|
||||
remote_pairlist = RemotePairList(exchange, pairlistmanager, rpl_config,
|
||||
rpl_config['pairlists'][0], 0)
|
||||
|
||||
result = remote_pairlist.gen_pairlist([])
|
||||
|
||||
assert result == ['TKN/USDT', 'ETH/USDT']
|
||||
|
||||
|
||||
def test_fetch_pairlist_mock_response_html(mocker, rpl_config):
|
||||
mock_response = MagicMock()
|
||||
mock_response.headers = {'content-type': 'text/html'}
|
||||
|
||||
rpl_config['pairlists'] = [
|
||||
{
|
||||
"method": "RemotePairList",
|
||||
"pairlist_url": "http://example.com/pairlist",
|
||||
"number_assets": 10,
|
||||
"read_timeout": 10,
|
||||
"keep_pairlist_on_failure": True,
|
||||
}
|
||||
]
|
||||
|
||||
exchange = get_patched_exchange(mocker, rpl_config)
|
||||
pairlistmanager = PairListManager(exchange, rpl_config)
|
||||
|
||||
mocker.patch("freqtrade.plugins.pairlist.RemotePairList.requests.get",
|
||||
return_value=mock_response)
|
||||
remote_pairlist = RemotePairList(exchange, pairlistmanager, rpl_config,
|
||||
rpl_config['pairlists'][0], 0)
|
||||
|
||||
with pytest.raises(OperationalException, match='RemotePairList is not of type JSON, abort.'):
|
||||
remote_pairlist.fetch_pairlist()
|
||||
|
||||
|
||||
def test_fetch_pairlist_timeout_keep_last_pairlist(mocker, rpl_config, caplog):
|
||||
rpl_config['pairlists'] = [
|
||||
{
|
||||
"method": "RemotePairList",
|
||||
"pairlist_url": "http://example.com/pairlist",
|
||||
"number_assets": 10,
|
||||
"read_timeout": 10,
|
||||
"keep_pairlist_on_failure": True,
|
||||
}
|
||||
]
|
||||
|
||||
exchange = get_patched_exchange(mocker, rpl_config)
|
||||
pairlistmanager = PairListManager(exchange, rpl_config)
|
||||
|
||||
mocker.patch("freqtrade.plugins.pairlist.RemotePairList.requests.get",
|
||||
side_effect=requests.exceptions.RequestException)
|
||||
|
||||
remote_pairlist = RemotePairList(exchange, pairlistmanager, rpl_config,
|
||||
rpl_config['pairlists'][0], 0)
|
||||
|
||||
remote_pairlist._last_pairlist = ["BTC/USDT", "ETH/USDT", "LTC/USDT"]
|
||||
|
||||
pairs, time_elapsed = remote_pairlist.fetch_pairlist()
|
||||
assert log_has(f"Was not able to fetch pairlist from: {remote_pairlist._pairlist_url}", caplog)
|
||||
assert log_has("Keeping last fetched pairlist", caplog)
|
||||
assert pairs == ["BTC/USDT", "ETH/USDT", "LTC/USDT"]
|
||||
|
||||
|
||||
def test_remote_pairlist_init_no_pairlist_url(mocker, rpl_config):
|
||||
|
||||
rpl_config['pairlists'] = [
|
||||
{
|
||||
"method": "RemotePairList",
|
||||
"number_assets": 10,
|
||||
"keep_pairlist_on_failure": True,
|
||||
}
|
||||
]
|
||||
|
||||
get_patched_exchange(mocker, rpl_config)
|
||||
with pytest.raises(OperationalException, match=r'`pairlist_url` not specified.'
|
||||
r' Please check your configuration for "pairlist.config.pairlist_url"'):
|
||||
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'] = [
|
||||
{
|
||||
"method": "RemotePairList",
|
||||
"pairlist_url": "http://example.com/pairlist",
|
||||
"number_assets": 10,
|
||||
"refresh_period": 10,
|
||||
"read_timeout": 10,
|
||||
"keep_pairlist_on_failure": True,
|
||||
}
|
||||
]
|
||||
|
||||
mock_response = MagicMock()
|
||||
|
||||
mock_response.json.return_value = {
|
||||
"pairs": ["ETH/USDT", "XRP/USDT", "LTC/USDT", "EOS/USDT"],
|
||||
"refresh_period": 60
|
||||
}
|
||||
|
||||
mock_response.headers = {
|
||||
"content-type": "application/json"
|
||||
}
|
||||
|
||||
mock_response.elapsed.total_seconds.return_value = 0.4
|
||||
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, time_elapsed = remote_pairlist.fetch_pairlist()
|
||||
|
||||
assert pairs == ["ETH/USDT", "XRP/USDT", "LTC/USDT", "EOS/USDT"]
|
||||
assert time_elapsed == 0.4
|
||||
assert remote_pairlist._refresh_period == 60
|
Reference in New Issue
Block a user