From 19b78fbc22856160d8f2d436ce6af7be8dbb61fd Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 28 Mar 2023 06:55:55 +0200 Subject: [PATCH] Override ccxt's marketOrderRequiresPrice settings for gate --- freqtrade/exchange/exchange.py | 12 ++++++++++-- freqtrade/exchange/gate.py | 3 ++- tests/exchange/test_exchange.py | 20 ++++++++++++++++---- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 92eb4b58a..bbe9585ae 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -80,6 +80,8 @@ class Exchange: "fee_cost_in_contracts": False, # Fee cost needs contract conversion "needs_trading_fees": False, # use fetch_trading_fees to cache fees "order_props_in_contracts": ['amount', 'cost', 'filled', 'remaining'], + # Override createMarketBuyOrderRequiresPrice where ccxt has it wrong + "marketOrderRequiresPrice": False, } _ft_has: Dict = {} _ft_has_futures: Dict = {} @@ -1040,6 +1042,13 @@ class Exchange: params.update({'reduceOnly': True}) return params + def _order_needs_price(self, ordertype: str) -> bool: + return ( + ordertype != 'market' + or self._api.options.get("createMarketBuyOrderRequiresPrice", False) + or self._ft_has.get('marketOrderRequiresPrice', False) + ) + def create_order( self, *, @@ -1062,8 +1071,7 @@ class Exchange: try: # Set the precision for amount and price(rate) as accepted by the exchange amount = self.amount_to_precision(pair, self._amount_to_contracts(pair, amount)) - needs_price = (ordertype != 'market' - or self._api.options.get("createMarketBuyOrderRequiresPrice", False)) + needs_price = self._order_needs_price(ordertype) rate_for_order = self.price_to_precision(pair, rate) if needs_price else None if not reduceOnly: diff --git a/freqtrade/exchange/gate.py b/freqtrade/exchange/gate.py index f0c1053a6..2ac135fc1 100644 --- a/freqtrade/exchange/gate.py +++ b/freqtrade/exchange/gate.py @@ -5,7 +5,6 @@ from typing import Any, Dict, List, Optional, Tuple from freqtrade.constants import BuySell from freqtrade.enums import MarginMode, PriceType, TradingMode -from freqtrade.exceptions import OperationalException from freqtrade.exchange import Exchange from freqtrade.misc import safe_value_fallback2 @@ -28,10 +27,12 @@ class Gate(Exchange): "order_time_in_force": ['GTC', 'IOC'], "stoploss_order_types": {"limit": "limit"}, "stoploss_on_exchange": True, + "marketOrderRequiresPrice": True, } _ft_has_futures: Dict = { "needs_trading_fees": True, + "marketOrderRequiresPrice": False, "tickers_have_bid_ask": False, "fee_cost_in_contracts": False, # Set explicitly to false for clarity "order_props_in_contracts": ['amount', 'filled', 'remaining'], diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 5350f4e3e..e08815e61 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1439,7 +1439,10 @@ def test_buy_prod(default_conf, mocker, exchange_name): assert api_mock.create_order.call_args[0][1] == order_type assert api_mock.create_order.call_args[0][2] == 'buy' assert api_mock.create_order.call_args[0][3] == 1 - assert api_mock.create_order.call_args[0][4] is None + if exchange._order_needs_price(order_type): + assert api_mock.create_order.call_args[0][4] == 200 + else: + assert api_mock.create_order.call_args[0][4] is None api_mock.create_order.reset_mock() order_type = 'limit' @@ -1544,7 +1547,10 @@ def test_buy_considers_time_in_force(default_conf, mocker, exchange_name): assert api_mock.create_order.call_args[0][1] == order_type assert api_mock.create_order.call_args[0][2] == 'buy' assert api_mock.create_order.call_args[0][3] == 1 - assert api_mock.create_order.call_args[0][4] is None + if exchange._order_needs_price(order_type): + assert api_mock.create_order.call_args[0][4] == 200 + else: + assert api_mock.create_order.call_args[0][4] is None # Market orders should not send timeInForce!! assert "timeInForce" not in api_mock.create_order.call_args[0][5] @@ -1588,7 +1594,10 @@ def test_sell_prod(default_conf, mocker, exchange_name): assert api_mock.create_order.call_args[0][1] == order_type assert api_mock.create_order.call_args[0][2] == 'sell' assert api_mock.create_order.call_args[0][3] == 1 - assert api_mock.create_order.call_args[0][4] is None + if exchange._order_needs_price(order_type): + assert api_mock.create_order.call_args[0][4] == 200 + else: + assert api_mock.create_order.call_args[0][4] is None api_mock.create_order.reset_mock() order_type = 'limit' @@ -1682,7 +1691,10 @@ def test_sell_considers_time_in_force(default_conf, mocker, exchange_name): assert api_mock.create_order.call_args[0][1] == order_type assert api_mock.create_order.call_args[0][2] == 'sell' assert api_mock.create_order.call_args[0][3] == 1 - assert api_mock.create_order.call_args[0][4] is None + if exchange._order_needs_price(order_type): + assert api_mock.create_order.call_args[0][4] == 200 + else: + assert api_mock.create_order.call_args[0][4] is None # Market orders should not send timeInForce!! assert "timeInForce" not in api_mock.create_order.call_args[0][5]