diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 5d6786476..fd4fd627f 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -182,6 +182,8 @@ class Exchange: self.required_candle_call_count = self.validate_required_startup_candles( config.get('startup_candle_count', 0), config.get('timeframe', '')) self.validate_trading_mode_and_margin_mode(self.trading_mode, self.margin_mode) + self.validate_pricing(config['ask_strategy']) + self.validate_pricing(config['bid_strategy']) # Converts the interval provided in minutes in config to seconds self.markets_refresh_interval: int = exchange_config.get( @@ -575,6 +577,14 @@ class Exchange: f'On exchange stoploss is not supported for {self.name}.' ) + def validate_pricing(self, pricing: Dict) -> None: + if pricing.get('use_order_book', False) and not self.exchange_has('fetchL2OrderBook'): + raise OperationalException(f'Orderbook not available for {self.name}.') + if (not pricing.get('use_order_book', False) and not ( + self.exchange_has('fetchTicker') and self._ft_has['tickers_have_price'] + )): + raise OperationalException(f'Ticker pricing not available for {self.name}.') + def validate_order_time_in_force(self, order_time_in_force: Dict) -> None: """ Checks if order time in force configured in strategy/config are supported diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 7438d900d..c375f37fe 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -939,7 +939,45 @@ def test_validate_timeframes_not_in_config(default_conf, mocker): Exchange(default_conf) -def test_validate_order_types(default_conf, mocker): +def test_validate_pricing(default_conf, mocker): + api_mock = MagicMock() + has = { + 'fetchL2OrderBook': True, + 'fetchTicker': True, + } + type(api_mock).has = PropertyMock(return_value=has) + mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) + mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={})) + mocker.patch('freqtrade.exchange.exchange.Exchange.validate_trading_mode_and_margin_mode') + mocker.patch('freqtrade.exchange.Exchange.validate_pairs') + mocker.patch('freqtrade.exchange.Exchange.validate_timeframes') + mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency') + mocker.patch('freqtrade.exchange.Exchange.name', 'Binance') + ExchangeResolver.load_exchange('binance', default_conf) + has.update({'fetchTicker': False}) + with pytest.raises(OperationalException, match="Ticker pricing not available for .*"): + ExchangeResolver.load_exchange('binance', default_conf) + + has.update({'fetchTicker': True}) + + default_conf['ask_strategy']['use_order_book'] = True + ExchangeResolver.load_exchange('binance', default_conf) + has.update({'fetchL2OrderBook': False}) + + with pytest.raises(OperationalException, match="Orderbook not available for .*"): + ExchangeResolver.load_exchange('binance', default_conf) + + has.update({'fetchL2OrderBook': True}) + + # Binance has no tickers on futures + default_conf['trading_mode'] = TradingMode.FUTURES + default_conf['margin_mode'] = MarginMode.ISOLATED + + with pytest.raises(OperationalException, match="Ticker pricing not available for .*"): + ExchangeResolver.load_exchange('binance', default_conf) + + +def test_validate_ordertypes(default_conf, mocker): api_mock = MagicMock() type(api_mock).has = PropertyMock(return_value={'createMarketOrder': True})