From c11984d943af8a59a548ddbee7a78d49fcb8bdde Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 17 Nov 2018 19:54:55 +0100 Subject: [PATCH] Check if exchange supports all configured market types --- freqtrade/exchange/__init__.py | 11 ++++++++- freqtrade/tests/conftest.py | 1 + freqtrade/tests/exchange/test_exchange.py | 30 +++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/freqtrade/exchange/__init__.py b/freqtrade/exchange/__init__.py index 57db4a125..11836ed4e 100644 --- a/freqtrade/exchange/__init__.py +++ b/freqtrade/exchange/__init__.py @@ -102,7 +102,7 @@ class Exchange(object): self.markets = self._load_markets() # Check if all pairs are available self.validate_pairs(config['exchange']['pair_whitelist']) - + self.validate_ordertypes(config.get('order_types', {})) if config.get('ticker_interval'): # Check if timeframe is available self.validate_timeframes(config['ticker_interval']) @@ -218,6 +218,15 @@ class Exchange(object): raise OperationalException( f'Invalid ticker {timeframe}, this Exchange supports {timeframes}') + def validate_ordertypes(self, order_types: Dict) -> None: + """ + Checks if order-types configured in strategy/config are supported + """ + if any(v == 'market' for k, v in order_types.items()): + if not self.exchange_has('createMarketOrder'): + raise OperationalException( + f'Exchange {self.name} does not support market orders.') + def exchange_has(self, endpoint: str) -> bool: """ Checks if exchange implements a specific API endpoint. diff --git a/freqtrade/tests/conftest.py b/freqtrade/tests/conftest.py index 8a497725f..b6c022b45 100644 --- a/freqtrade/tests/conftest.py +++ b/freqtrade/tests/conftest.py @@ -30,6 +30,7 @@ def log_has(line, logs): def patch_exchange(mocker, api_mock=None) -> None: mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={})) mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock()) + mocker.patch('freqtrade.exchange.Exchange.validate_ordertypes', MagicMock()) mocker.patch('freqtrade.exchange.Exchange.name', PropertyMock(return_value="Bittrex")) mocker.patch('freqtrade.exchange.Exchange.id', PropertyMock(return_value="bittrex")) if api_mock: diff --git a/freqtrade/tests/exchange/test_exchange.py b/freqtrade/tests/exchange/test_exchange.py index fd4512bd2..10644a9be 100644 --- a/freqtrade/tests/exchange/test_exchange.py +++ b/freqtrade/tests/exchange/test_exchange.py @@ -355,6 +355,36 @@ def test_validate_timeframes_not_in_config(default_conf, mocker): Exchange(default_conf) +def test_validate_order_types(default_conf, mocker): + api_mock = MagicMock() + + type(api_mock).has = PropertyMock(return_value={'createMarketOrder': True}) + 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.validate_timeframes', MagicMock()) + default_conf['order_types'] = {'buy': 'limit', 'sell': 'limit', 'stoploss': 'market'} + Exchange(default_conf) + + type(api_mock).has = PropertyMock(return_value={'createMarketOrder': False}) + mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) + + default_conf['order_types'] = {'buy': 'limit', 'sell': 'limit', 'stoploss': 'market'} + + with pytest.raises(OperationalException, + match=r'Exchange .* does not support market orders.'): + Exchange(default_conf) + + +def test_validate_order_types_not_in_config(default_conf, mocker): + api_mock = MagicMock() + 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.validate_timeframes', MagicMock()) + + conf = copy.deepcopy(default_conf) + Exchange(conf) + + def test_exchange_has(default_conf, mocker): exchange = get_patched_exchange(mocker, default_conf) assert not exchange.exchange_has('ASDFASDF')