Merge pull request #979 from creslinux/Check_timeframes
Handle if ticker_interval in config.json is not supported on exchange.
This commit is contained in:
commit
050afe2bc0
@ -70,6 +70,10 @@ class Exchange(object):
|
||||
# Check if all pairs are available
|
||||
self.validate_pairs(config['exchange']['pair_whitelist'])
|
||||
|
||||
if config.get('ticker_interval'):
|
||||
# Check if timeframe is available
|
||||
self.validate_timeframes(config['ticker_interval'])
|
||||
|
||||
def _init_ccxt(self, exchange_config: dict) -> ccxt.Exchange:
|
||||
"""
|
||||
Initialize ccxt with given config and return valid
|
||||
@ -128,6 +132,15 @@ class Exchange(object):
|
||||
raise OperationalException(
|
||||
f'Pair {pair} is not available at {self.name}')
|
||||
|
||||
def validate_timeframes(self, timeframe: List[str]) -> None:
|
||||
"""
|
||||
Checks if ticker interval from config is a supported timeframe on the exchange
|
||||
"""
|
||||
timeframes = self._api.timeframes
|
||||
if timeframe not in timeframes:
|
||||
raise OperationalException(
|
||||
f'Invalid ticker {timeframe}, this Exchange supports {timeframes}')
|
||||
|
||||
def exchange_has(self, endpoint: str) -> bool:
|
||||
"""
|
||||
Checks if exchange implements a specific API endpoint.
|
||||
|
@ -29,6 +29,7 @@ def log_has(line, logs):
|
||||
|
||||
def patch_exchange(mocker, api_mock=None) -> None:
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||
if api_mock:
|
||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||
else:
|
||||
|
@ -61,6 +61,7 @@ def test_validate_pairs(default_conf, mocker):
|
||||
type(api_mock).id = id_mock
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||
Exchange(default_conf)
|
||||
|
||||
|
||||
@ -68,6 +69,7 @@ def test_validate_pairs_not_available(default_conf, mocker):
|
||||
api_mock = MagicMock()
|
||||
api_mock.load_markets = MagicMock(return_value={})
|
||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||
|
||||
with pytest.raises(OperationalException, match=r'not available'):
|
||||
Exchange(default_conf)
|
||||
@ -81,7 +83,7 @@ def test_validate_pairs_not_compatible(default_conf, mocker):
|
||||
conf = deepcopy(default_conf)
|
||||
conf['stake_currency'] = 'ETH'
|
||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||
with pytest.raises(OperationalException, match=r'not compatible'):
|
||||
Exchange(conf)
|
||||
|
||||
@ -93,6 +95,7 @@ def test_validate_pairs_exception(default_conf, mocker, caplog):
|
||||
|
||||
api_mock.load_markets = MagicMock(return_value={})
|
||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', api_mock)
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||
|
||||
with pytest.raises(OperationalException, match=r'Pair ETH/BTC is not available at Binance'):
|
||||
Exchange(default_conf)
|
||||
@ -112,6 +115,7 @@ def test_validate_pairs_stake_exception(default_conf, mocker, caplog):
|
||||
api_mock = MagicMock()
|
||||
api_mock.name = MagicMock(return_value='binance')
|
||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', api_mock)
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||
|
||||
with pytest.raises(
|
||||
OperationalException,
|
||||
@ -120,6 +124,55 @@ def test_validate_pairs_stake_exception(default_conf, mocker, caplog):
|
||||
Exchange(conf)
|
||||
|
||||
|
||||
def test_validate_timeframes(default_conf, mocker):
|
||||
default_conf["ticker_interval"] = "5m"
|
||||
api_mock = MagicMock()
|
||||
id_mock = PropertyMock(return_value='test_exchange')
|
||||
type(api_mock).id = id_mock
|
||||
timeframes = PropertyMock(return_value={'1m': '1m',
|
||||
'5m': '5m',
|
||||
'15m': '15m',
|
||||
'1h': '1h'})
|
||||
type(api_mock).timeframes = timeframes
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
|
||||
Exchange(default_conf)
|
||||
|
||||
|
||||
def test_validate_timeframes_failed(default_conf, mocker):
|
||||
default_conf["ticker_interval"] = "3m"
|
||||
api_mock = MagicMock()
|
||||
id_mock = PropertyMock(return_value='test_exchange')
|
||||
type(api_mock).id = id_mock
|
||||
timeframes = PropertyMock(return_value={'1m': '1m',
|
||||
'5m': '5m',
|
||||
'15m': '15m',
|
||||
'1h': '1h'})
|
||||
type(api_mock).timeframes = timeframes
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
|
||||
with pytest.raises(OperationalException, match=r'Invalid ticker 3m, this Exchange supports.*'):
|
||||
Exchange(default_conf)
|
||||
|
||||
|
||||
def test_validate_timeframes_not_in_config(default_conf, mocker):
|
||||
del default_conf["ticker_interval"]
|
||||
api_mock = MagicMock()
|
||||
id_mock = PropertyMock(return_value='test_exchange')
|
||||
type(api_mock).id = id_mock
|
||||
timeframes = PropertyMock(return_value={'1m': '1m',
|
||||
'5m': '5m',
|
||||
'15m': '15m',
|
||||
'1h': '1h'})
|
||||
type(api_mock).timeframes = timeframes
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
|
||||
Exchange(default_conf)
|
||||
|
||||
|
||||
def test_exchangehas(default_conf, mocker):
|
||||
exchange = get_patched_exchange(mocker, default_conf)
|
||||
assert not exchange.exchange_has('ASDFASDF')
|
||||
|
Loading…
Reference in New Issue
Block a user