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
|
# Check if all pairs are available
|
||||||
self.validate_pairs(config['exchange']['pair_whitelist'])
|
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:
|
def _init_ccxt(self, exchange_config: dict) -> ccxt.Exchange:
|
||||||
"""
|
"""
|
||||||
Initialize ccxt with given config and return valid
|
Initialize ccxt with given config and return valid
|
||||||
@ -128,6 +132,15 @@ class Exchange(object):
|
|||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
f'Pair {pair} is not available at {self.name}')
|
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:
|
def exchange_has(self, endpoint: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Checks if exchange implements a specific API endpoint.
|
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:
|
def patch_exchange(mocker, api_mock=None) -> None:
|
||||||
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
|
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||||
if api_mock:
|
if api_mock:
|
||||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||||
else:
|
else:
|
||||||
|
@ -61,6 +61,7 @@ def test_validate_pairs(default_conf, mocker):
|
|||||||
type(api_mock).id = id_mock
|
type(api_mock).id = id_mock
|
||||||
|
|
||||||
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())
|
||||||
Exchange(default_conf)
|
Exchange(default_conf)
|
||||||
|
|
||||||
|
|
||||||
@ -68,6 +69,7 @@ def test_validate_pairs_not_available(default_conf, mocker):
|
|||||||
api_mock = MagicMock()
|
api_mock = MagicMock()
|
||||||
api_mock.load_markets = MagicMock(return_value={})
|
api_mock.load_markets = MagicMock(return_value={})
|
||||||
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())
|
||||||
|
|
||||||
with pytest.raises(OperationalException, match=r'not available'):
|
with pytest.raises(OperationalException, match=r'not available'):
|
||||||
Exchange(default_conf)
|
Exchange(default_conf)
|
||||||
@ -81,7 +83,7 @@ def test_validate_pairs_not_compatible(default_conf, mocker):
|
|||||||
conf = deepcopy(default_conf)
|
conf = deepcopy(default_conf)
|
||||||
conf['stake_currency'] = 'ETH'
|
conf['stake_currency'] = 'ETH'
|
||||||
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())
|
||||||
with pytest.raises(OperationalException, match=r'not compatible'):
|
with pytest.raises(OperationalException, match=r'not compatible'):
|
||||||
Exchange(conf)
|
Exchange(conf)
|
||||||
|
|
||||||
@ -93,6 +95,7 @@ def test_validate_pairs_exception(default_conf, mocker, caplog):
|
|||||||
|
|
||||||
api_mock.load_markets = MagicMock(return_value={})
|
api_mock.load_markets = MagicMock(return_value={})
|
||||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', api_mock)
|
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'):
|
with pytest.raises(OperationalException, match=r'Pair ETH/BTC is not available at Binance'):
|
||||||
Exchange(default_conf)
|
Exchange(default_conf)
|
||||||
@ -112,6 +115,7 @@ def test_validate_pairs_stake_exception(default_conf, mocker, caplog):
|
|||||||
api_mock = MagicMock()
|
api_mock = MagicMock()
|
||||||
api_mock.name = MagicMock(return_value='binance')
|
api_mock.name = MagicMock(return_value='binance')
|
||||||
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', api_mock)
|
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', api_mock)
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||||
|
|
||||||
with pytest.raises(
|
with pytest.raises(
|
||||||
OperationalException,
|
OperationalException,
|
||||||
@ -120,6 +124,55 @@ def test_validate_pairs_stake_exception(default_conf, mocker, caplog):
|
|||||||
Exchange(conf)
|
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):
|
def test_exchangehas(default_conf, mocker):
|
||||||
exchange = get_patched_exchange(mocker, default_conf)
|
exchange = get_patched_exchange(mocker, default_conf)
|
||||||
assert not exchange.exchange_has('ASDFASDF')
|
assert not exchange.exchange_has('ASDFASDF')
|
||||||
|
Loading…
Reference in New Issue
Block a user