Warn when using restricted pairs

As noted in https://github.com/ccxt/ccxt/issues/5624, there is currently
no way to detect if a user is impacted by this or not prior to creating
a order.
This commit is contained in:
Matthias 2019-08-03 13:11:51 +02:00
parent 4c005e7086
commit bbd58e772e
3 changed files with 35 additions and 12 deletions

View File

@ -260,7 +260,7 @@ class Exchange(object):
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
for pair in pairs: for pair in pairs:
# Note: ccxt has BaseCurrency/QuoteCurrency format for pairs # Note: ccxt has BaseCurrency/QuoteCurrency format for pairs
@ -269,6 +269,12 @@ class Exchange(object):
raise OperationalException( raise OperationalException(
f'Pair {pair} is not available on {self.name}. ' f'Pair {pair} is not available on {self.name}. '
f'Please remove {pair} from your whitelist.') f'Please remove {pair} from your whitelist.')
elif self.markets[pair].get('info', {}).get('IsRestricted', False):
# Warn users about restricted pairs in whitelist.
# We cannot determine reliably if Users are affected.
logger.warning(f"Pair {pair} is restricted for some users on this exchange."
f"Please check if you are impacted by this restriction "
f"on the exchange and eventually remove {pair} from your whitelist.")
def get_valid_pair_combination(self, curr_1, curr_2) -> str: def get_valid_pair_combination(self, curr_1, curr_2) -> str:
""" """

View File

@ -304,7 +304,7 @@ def markets():
'max': 500000, 'max': 500000,
}, },
}, },
'info': '', 'info': {},
}, },
'TKN/BTC': { 'TKN/BTC': {
'id': 'tknbtc', 'id': 'tknbtc',
@ -329,7 +329,7 @@ def markets():
'max': 500000, 'max': 500000,
}, },
}, },
'info': '', 'info': {},
}, },
'BLK/BTC': { 'BLK/BTC': {
'id': 'blkbtc', 'id': 'blkbtc',
@ -354,7 +354,7 @@ def markets():
'max': 500000, 'max': 500000,
}, },
}, },
'info': '', 'info': {},
}, },
'LTC/BTC': { 'LTC/BTC': {
'id': 'ltcbtc', 'id': 'ltcbtc',
@ -379,7 +379,7 @@ def markets():
'max': 500000, 'max': 500000,
}, },
}, },
'info': '', 'info': {},
}, },
'XRP/BTC': { 'XRP/BTC': {
'id': 'xrpbtc', 'id': 'xrpbtc',
@ -404,7 +404,7 @@ def markets():
'max': 500000, 'max': 500000,
}, },
}, },
'info': '', 'info': {},
}, },
'NEO/BTC': { 'NEO/BTC': {
'id': 'neobtc', 'id': 'neobtc',
@ -429,7 +429,7 @@ def markets():
'max': 500000, 'max': 500000,
}, },
}, },
'info': '', 'info': {},
}, },
'BTT/BTC': { 'BTT/BTC': {
'id': 'BTTBTC', 'id': 'BTTBTC',
@ -457,7 +457,7 @@ def markets():
'max': None 'max': None
} }
}, },
'info': "", 'info': {},
}, },
'ETH/USDT': { 'ETH/USDT': {
'id': 'USDT-ETH', 'id': 'USDT-ETH',
@ -479,7 +479,7 @@ def markets():
} }
}, },
'active': True, 'active': True,
'info': "" 'info': {},
}, },
'LTC/USDT': { 'LTC/USDT': {
'id': 'USDT-LTC', 'id': 'USDT-LTC',
@ -501,7 +501,7 @@ def markets():
'max': None 'max': None
} }
}, },
'info': "" 'info': {},
} }
} }

View File

@ -318,7 +318,7 @@ def test__reload_markets_exception(default_conf, mocker, caplog):
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': {}, 'LTC/BTC': {}, 'XRP/BTC': {}, 'NEO/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
@ -332,7 +332,7 @@ def test_validate_pairs(default_conf, mocker): # test exchange.validate_pairs d
def test_validate_pairs_not_available(default_conf, mocker): def test_validate_pairs_not_available(default_conf, mocker):
api_mock = MagicMock() api_mock = MagicMock()
type(api_mock).markets = PropertyMock(return_value={ type(api_mock).markets = PropertyMock(return_value={
'XRP/BTC': 'inactive' 'XRP/BTC': {'inactive'}
}) })
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', MagicMock()) mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
@ -361,6 +361,23 @@ def test_validate_pairs_exception(default_conf, mocker, caplog):
caplog.record_tuples) caplog.record_tuples)
def test_validate_pairs_restricted(default_conf, mocker, caplog):
api_mock = MagicMock()
type(api_mock).markets = PropertyMock(return_value={
'ETH/BTC': {}, 'LTC/BTC': {}, 'NEO/BTC': {},
'XRP/BTC': {'info': {'IsRestricted': True}}
})
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
mocker.patch('freqtrade.exchange.Exchange._load_async_markets', MagicMock())
Exchange(default_conf)
assert log_has(f"Pair XRP/BTC is restricted for some users on this exchange."
f"Please check if you are impacted by this restriction "
f"on the exchange and eventually remove XRP/BTC from your whitelist.",
caplog.record_tuples)
def test_validate_timeframes(default_conf, mocker): def test_validate_timeframes(default_conf, mocker):
default_conf["ticker_interval"] = "5m" default_conf["ticker_interval"] = "5m"
api_mock = MagicMock() api_mock = MagicMock()