diff --git a/freqtrade/configuration/config_validation.py b/freqtrade/configuration/config_validation.py index 87a309f12..c7f44c643 100644 --- a/freqtrade/configuration/config_validation.py +++ b/freqtrade/configuration/config_validation.py @@ -6,6 +6,7 @@ from jsonschema import Draft4Validator, validators from jsonschema.exceptions import ValidationError, best_match from freqtrade import constants +from freqtrade.configuration.deprecated_settings import process_deprecated_setting from freqtrade.enums import RunMode, TradingMode from freqtrade.exceptions import OperationalException @@ -102,11 +103,12 @@ def _validate_price_config(conf: Dict[str, Any]) -> None: """ When using market orders, price sides must be using the "other" side of the price """ - if (conf.get('order_types', {}).get('buy') == 'market' + # TODO-lev: check this again when determining how to migrate pricing strategies! + if (conf.get('order_types', {}).get('entry') == 'market' and conf.get('bid_strategy', {}).get('price_side') != 'ask'): raise OperationalException('Market buy orders require bid_strategy.price_side = "ask".') - if (conf.get('order_types', {}).get('sell') == 'market' + if (conf.get('order_types', {}).get('exit') == 'market' and conf.get('ask_strategy', {}).get('price_side') != 'bid'): raise OperationalException('Market sell orders require ask_strategy.price_side = "bid".') @@ -213,6 +215,7 @@ def _validate_ask_orderbook(conf: Dict[str, Any]) -> None: def validate_migrated_strategy_settings(conf: Dict[str, Any]) -> None: _validate_time_in_force(conf) + _validate_order_types(conf) def _validate_time_in_force(conf: Dict[str, Any]) -> None: @@ -229,3 +232,31 @@ def _validate_time_in_force(conf: Dict[str, Any]) -> None: ) time_in_force['entry'] = time_in_force.pop('buy') time_in_force['exit'] = time_in_force.pop('sell') + + +def _validate_order_types(conf: Dict[str, Any]) -> None: + + order_types = conf.get('order_types', {}) + if any(x in order_types for x in ['buy', 'sell', 'emergencysell', 'forcebuy', 'forcesell']): + if conf.get('trading_mode', TradingMode.SPOT) != TradingMode.SPOT: + raise OperationalException( + "Please migrate your order_types settings to use the new wording.") + else: + logger.warning( + "DEPRECATED: Using 'buy' and 'sell' for order_types is deprecated." + "Please migrate your time_in_force settings to use 'entry' and 'exit' wording." + ) + for o, n in [ + ('buy', 'entry'), + ('sell', 'exit'), + ('emergencysell', 'emergencyexit'), + ('forcesell', 'forceexit'), + ('forcebuy', 'forceentry'), + ]: + + process_deprecated_setting(conf, 'order_types', o, 'order_types', n) + # order_types['entry'] = order_types.pop('buy') + # order_types['exit'] = order_types.pop('sell') + # order_types['emergencyexit'] = order_types.pop('emergencysell') + # order_types['forceexit'] = order_types.pop('forceexit') + # order_types['forceentry'] = order_types.pop('forceentry') diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 1f6be2860..bb2408b5c 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -951,8 +951,8 @@ def test_validate_order_types(default_conf, mocker): mocker.patch('freqtrade.exchange.Exchange.name', 'Bittrex') default_conf['order_types'] = { - 'buy': 'limit', - 'sell': 'limit', + 'entry': 'limit', + 'exit': 'limit', 'stoploss': 'market', 'stoploss_on_exchange': False } @@ -962,8 +962,8 @@ def test_validate_order_types(default_conf, mocker): mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) default_conf['order_types'] = { - 'buy': 'limit', - 'sell': 'limit', + 'entry': 'limit', + 'exit': 'limit', 'stoploss': 'market', 'stoploss_on_exchange': False } @@ -972,8 +972,8 @@ def test_validate_order_types(default_conf, mocker): Exchange(default_conf) default_conf['order_types'] = { - 'buy': 'limit', - 'sell': 'limit', + 'entry': 'limit', + 'exit': 'limit', 'stoploss': 'limit', 'stoploss_on_exchange': True } diff --git a/tests/strategy/strats/hyperoptable_strategy.py b/tests/strategy/strats/hyperoptable_strategy.py index e843f6b58..33734f241 100644 --- a/tests/strategy/strats/hyperoptable_strategy.py +++ b/tests/strategy/strats/hyperoptable_strategy.py @@ -34,8 +34,8 @@ class HyperoptableStrategy(IStrategy): # Optional order type mapping order_types = { - 'buy': 'limit', - 'sell': 'limit', + 'entry': 'limit', + 'exit': 'limit', 'stoploss': 'limit', 'stoploss_on_exchange': False } diff --git a/tests/strategy/strats/strategy_test_v2.py b/tests/strategy/strats/strategy_test_v2.py index fd70cf346..a9ca7d9e2 100644 --- a/tests/strategy/strats/strategy_test_v2.py +++ b/tests/strategy/strats/strategy_test_v2.py @@ -36,8 +36,8 @@ class StrategyTestV2(IStrategy): # Optional order type mapping order_types = { - 'buy': 'limit', - 'sell': 'limit', + 'entry': 'limit', + 'exit': 'limit', 'stoploss': 'limit', 'stoploss_on_exchange': False } diff --git a/tests/strategy/strats/strategy_test_v3.py b/tests/strategy/strats/strategy_test_v3.py index 962fd02e9..347d707bb 100644 --- a/tests/strategy/strats/strategy_test_v3.py +++ b/tests/strategy/strats/strategy_test_v3.py @@ -37,8 +37,8 @@ class StrategyTestV3(IStrategy): # Optional order type mapping order_types = { - 'buy': 'limit', - 'sell': 'limit', + 'entry': 'limit', + 'exit': 'limit', 'stoploss': 'limit', 'stoploss_on_exchange': False } diff --git a/tests/strategy/test_strategy_loading.py b/tests/strategy/test_strategy_loading.py index 8f407396c..6129272f1 100644 --- a/tests/strategy/test_strategy_loading.py +++ b/tests/strategy/test_strategy_loading.py @@ -223,8 +223,8 @@ def test_strategy_override_order_types(caplog, default_conf): caplog.set_level(logging.INFO) order_types = { - 'buy': 'market', - 'sell': 'limit', + 'entry': 'market', + 'exit': 'limit', 'stoploss': 'limit', 'stoploss_on_exchange': True, } @@ -235,16 +235,16 @@ def test_strategy_override_order_types(caplog, default_conf): strategy = StrategyResolver.load_strategy(default_conf) assert strategy.order_types - for method in ['buy', 'sell', 'stoploss', 'stoploss_on_exchange']: + for method in ['entry', 'exit', 'stoploss', 'stoploss_on_exchange']: assert strategy.order_types[method] == order_types[method] assert log_has("Override strategy 'order_types' with value in config file:" - " {'buy': 'market', 'sell': 'limit', 'stoploss': 'limit'," + " {'entry': 'market', 'exit': 'limit', 'stoploss': 'limit'," " 'stoploss_on_exchange': True}.", caplog) default_conf.update({ 'strategy': CURRENT_TEST_STRATEGY, - 'order_types': {'buy': 'market'} + 'order_types': {'exit': 'market'} }) # Raise error for invalid configuration with pytest.raises(ImportError, diff --git a/tests/test_configuration.py b/tests/test_configuration.py index e2ab3c9b5..dde879f05 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -798,8 +798,8 @@ def test_validate_max_open_trades(default_conf): def test_validate_price_side(default_conf): default_conf['order_types'] = { - "buy": "limit", - "sell": "limit", + "entry": "limit", + "exit": "limit", "stoploss": "limit", "stoploss_on_exchange": False, } @@ -807,21 +807,21 @@ def test_validate_price_side(default_conf): validate_config_consistency(default_conf) conf = deepcopy(default_conf) - conf['order_types']['buy'] = 'market' + conf['order_types']['entry'] = 'market' with pytest.raises(OperationalException, match='Market buy orders require bid_strategy.price_side = "ask".'): validate_config_consistency(conf) conf = deepcopy(default_conf) - conf['order_types']['sell'] = 'market' + conf['order_types']['exit'] = 'market' with pytest.raises(OperationalException, match='Market sell orders require ask_strategy.price_side = "bid".'): validate_config_consistency(conf) # Validate inversed case conf = deepcopy(default_conf) - conf['order_types']['sell'] = 'market' - conf['order_types']['buy'] = 'market' + conf['order_types']['exit'] = 'market' + conf['order_types']['entry'] = 'market' conf['ask_strategy']['price_side'] = 'bid' conf['bid_strategy']['price_side'] = 'ask' diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index b51637143..03a5b83be 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -91,8 +91,8 @@ def test_order_dict(default_conf_usdt, mocker, runmode, caplog) -> None: conf = default_conf_usdt.copy() conf['runmode'] = runmode conf['order_types'] = { - 'buy': 'market', - 'sell': 'limit', + 'entry': 'market', + 'exit': 'limit', 'stoploss': 'limit', 'stoploss_on_exchange': True, } @@ -108,8 +108,8 @@ def test_order_dict(default_conf_usdt, mocker, runmode, caplog) -> None: conf = default_conf_usdt.copy() conf['runmode'] = runmode conf['order_types'] = { - 'buy': 'market', - 'sell': 'limit', + 'entry': 'market', + 'exit': 'limit', 'stoploss': 'limit', 'stoploss_on_exchange': False, } @@ -3490,7 +3490,7 @@ def test_execute_trade_exit_market_order( 'freqtrade.exchange.Exchange', fetch_ticker=ticker_usdt_sell_up ) - freqtrade.config['order_types']['sell'] = 'market' + freqtrade.config['order_types']['exit'] = 'market' freqtrade.execute_trade_exit( trade=trade, diff --git a/tests/test_integration.py b/tests/test_integration.py index 70ee1c52c..9115b431b 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -80,7 +80,7 @@ def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee, freqtrade = get_patched_freqtradebot(mocker, default_conf) freqtrade.strategy.order_types['stoploss_on_exchange'] = True # Switch ordertype to market to close trade immediately - freqtrade.strategy.order_types['sell'] = 'market' + freqtrade.strategy.order_types['exit'] = 'market' freqtrade.strategy.confirm_trade_entry = MagicMock(return_value=True) freqtrade.strategy.confirm_trade_exit = MagicMock(return_value=True) patch_get_signal(freqtrade) @@ -173,7 +173,7 @@ def test_forcebuy_last_unlimited(default_conf, ticker, fee, mocker, balance_rati rpc = RPC(freqtrade) freqtrade.strategy.order_types['stoploss_on_exchange'] = True # Switch ordertype to market to close trade immediately - freqtrade.strategy.order_types['sell'] = 'market' + freqtrade.strategy.order_types['exit'] = 'market' patch_get_signal(freqtrade) # Create 4 trades