Move pairlist validation to exchange (we need to use .quote) from

markets
This commit is contained in:
Matthias 2020-02-24 21:22:58 +01:00
parent 6581ba56ca
commit 3e4f663418
4 changed files with 45 additions and 24 deletions

View File

@ -150,15 +150,3 @@ def _validate_whitelist(conf: Dict[str, Any]) -> None:
if (pl.get('method') == 'StaticPairList' if (pl.get('method') == 'StaticPairList'
and not conf.get('exchange', {}).get('pair_whitelist')): and not conf.get('exchange', {}).get('pair_whitelist')):
raise OperationalException("StaticPairList requires pair_whitelist to be set.") raise OperationalException("StaticPairList requires pair_whitelist to be set.")
if pl.get('method') == 'StaticPairList':
stake = conf['stake_currency']
invalid_pairs = []
for pair in conf['exchange'].get('pair_whitelist'):
if not pair.endswith(f'/{stake}'):
invalid_pairs.append(pair)
if invalid_pairs:
raise OperationalException(
f"Stake-currency '{stake}' not compatible with pair-whitelist. "
f"Please remove the following pairs: {invalid_pairs}")

View File

@ -300,7 +300,7 @@ class Exchange:
if not self.markets: if not self.markets:
logger.warning('Unable to validate pairs (assuming they are correct).') logger.warning('Unable to validate pairs (assuming they are correct).')
return return
invalid_pairs = []
for pair in pairs: for pair in pairs:
# Note: ccxt has BaseCurrency/QuoteCurrency format for pairs # Note: ccxt has BaseCurrency/QuoteCurrency format for pairs
# TODO: add a support for having coins in BTC/USDT format # TODO: add a support for having coins in BTC/USDT format
@ -322,6 +322,12 @@ class Exchange:
logger.warning(f"Pair {pair} is restricted for some users on this exchange." logger.warning(f"Pair {pair} is restricted for some users on this exchange."
f"Please check if you are impacted by this restriction " f"Please check if you are impacted by this restriction "
f"on the exchange and eventually remove {pair} from your whitelist.") f"on the exchange and eventually remove {pair} from your whitelist.")
if not self.markets[pair].get('quote') == self._config['stake_currency']:
invalid_pairs.append(pair)
if invalid_pairs:
raise OperationalException(
f"Stake-currency '{self._config['stake_currency']}' not compatible with "
f"pair-whitelist. Please remove the following pairs: {invalid_pairs}")
def get_valid_pair_combination(self, curr_1: str, curr_2: str) -> str: def get_valid_pair_combination(self, curr_1: str, curr_2: str) -> str:
""" """

View File

@ -406,7 +406,10 @@ def test_get_quote_currencies(default_conf, mocker):
def test_validate_pairs(default_conf, mocker): # test exchange.validate_pairs directly def test_validate_pairs(default_conf, mocker): # test exchange.validate_pairs directly
api_mock = MagicMock() api_mock = MagicMock()
type(api_mock).markets = PropertyMock(return_value={ type(api_mock).markets = PropertyMock(return_value={
'ETH/BTC': {}, 'LTC/BTC': {}, 'XRP/BTC': {}, 'NEO/BTC': {} 'ETH/BTC': {'quote': 'BTC'},
'LTC/BTC': {'quote': 'BTC'},
'XRP/BTC': {'quote': 'BTC'},
'NEO/BTC': {'quote': 'BTC'},
}) })
id_mock = PropertyMock(return_value='test_exchange') id_mock = PropertyMock(return_value='test_exchange')
type(api_mock).id = id_mock type(api_mock).id = id_mock
@ -454,9 +457,9 @@ def test_validate_pairs_exception(default_conf, mocker, caplog):
def test_validate_pairs_restricted(default_conf, mocker, caplog): def test_validate_pairs_restricted(default_conf, mocker, caplog):
api_mock = MagicMock() api_mock = MagicMock()
type(api_mock).markets = PropertyMock(return_value={ type(api_mock).markets = PropertyMock(return_value={
'ETH/BTC': {}, 'LTC/BTC': {}, 'ETH/BTC': {'quote': 'BTC'}, 'LTC/BTC': {'quote': 'BTC'},
'XRP/BTC': {'info': {'IsRestricted': True}}, 'XRP/BTC': {'quote': 'BTC', 'info': {'IsRestricted': True}},
'NEO/BTC': {'info': 'TestString'}, # info can also be a string ... 'NEO/BTC': {'quote': 'BTC', 'info': 'TestString'}, # info can also be a string ...
}) })
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes') mocker.patch('freqtrade.exchange.Exchange.validate_timeframes')
@ -469,6 +472,37 @@ def test_validate_pairs_restricted(default_conf, mocker, caplog):
f"on the exchange and eventually remove XRP/BTC from your whitelist.", caplog) f"on the exchange and eventually remove XRP/BTC from your whitelist.", caplog)
def test_validate_pairs_stakecompatibility(default_conf, mocker, caplog):
api_mock = MagicMock()
type(api_mock).markets = PropertyMock(return_value={
'ETH/BTC': {'quote': 'BTC'}, 'LTC/BTC': {'quote': 'BTC'},
'XRP/BTC': {'quote': 'BTC'}, 'NEO/BTC': {'quote': 'BTC'},
'HELLO-WORLD': {'quote': 'BTC'},
})
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes')
mocker.patch('freqtrade.exchange.Exchange._load_async_markets')
mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency')
Exchange(default_conf)
def test_validate_pairs_stakecompatibility_fail(default_conf, mocker, caplog):
default_conf['exchange']['pair_whitelist'].append('HELLO-WORLD')
api_mock = MagicMock()
type(api_mock).markets = PropertyMock(return_value={
'ETH/BTC': {'quote': 'BTC'}, 'LTC/BTC': {'quote': 'BTC'},
'XRP/BTC': {'quote': 'BTC'}, 'NEO/BTC': {'quote': 'BTC'},
'HELLO-WORLD': {'quote': 'USDT'},
})
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes')
mocker.patch('freqtrade.exchange.Exchange._load_async_markets')
mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency')
with pytest.raises(OperationalException, match=r"Stake-currency 'BTC' not compatible with.*"):
Exchange(default_conf)
@pytest.mark.parametrize("timeframe", [ @pytest.mark.parametrize("timeframe", [
('5m'), ("1m"), ("15m"), ("1h") ('5m'), ("1m"), ("15m"), ("1h")
]) ])

View File

@ -810,13 +810,6 @@ def test_validate_whitelist(default_conf):
validate_config_consistency(conf) validate_config_consistency(conf)
conf = deepcopy(default_conf)
conf['stake_currency'] = 'USDT'
with pytest.raises(OperationalException,
match=r"Stake-currency 'USDT' not compatible with pair-whitelist.*"):
validate_config_consistency(conf)
def test_load_config_test_comments() -> None: def test_load_config_test_comments() -> None:
""" """
Load config with comments Load config with comments