From 386be2d889287674c0acd5d75a74ae2383bd58c9 Mon Sep 17 00:00:00 2001 From: Sam Germain Date: Tue, 1 Feb 2022 22:23:05 -0600 Subject: [PATCH] set reduceOnly for futures exit orders --- freqtrade/exchange/binance.py | 12 ++++++++++-- freqtrade/exchange/exchange.py | 29 ++++++++++++++++++++++++----- freqtrade/exchange/ftx.py | 2 ++ freqtrade/exchange/kraken.py | 12 ++++++++++-- freqtrade/freqtradebot.py | 2 ++ 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/freqtrade/exchange/binance.py b/freqtrade/exchange/binance.py index 7d50e2c57..c04947bdf 100644 --- a/freqtrade/exchange/binance.py +++ b/freqtrade/exchange/binance.py @@ -86,14 +86,22 @@ class Binance(Exchange): try: params = self._params.copy() params.update({'stopPrice': stop_price}) + if self.trading_mode == TradingMode.FUTURES: + params.update({'reduceOnly': True}) amount = self.amount_to_precision(pair, amount) rate = self.price_to_precision(pair, rate) self._lev_prep(pair, leverage) - order = self._api.create_order(symbol=pair, type=ordertype, side=side, - amount=amount, price=rate, params=params) + order = self._api.create_order( + symbol=pair, + type=ordertype, + side=side, + amount=amount, + price=rate, + params=params + ) logger.info('stoploss limit order added for %s. ' 'stop price: %s. limit: %s', pair, stop_price, rate) self._log_exchange_response('create_stoploss_order', order) diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 5d7a75a42..b28858ebd 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -882,21 +882,38 @@ class Exchange: self.set_margin_mode(pair, self.margin_mode) self._set_leverage(leverage, pair) - def _get_params(self, ordertype: str, leverage: float, time_in_force: str = 'gtc') -> Dict: + def _get_params( + self, + ordertype: str, + leverage: float, + reduceOnly: bool, + time_in_force: str = 'gtc', + ) -> Dict: params = self._params.copy() if time_in_force != 'gtc' and ordertype != 'market': param = self._ft_has.get('time_in_force_parameter', '') params.update({param: time_in_force}) + if reduceOnly: + params.update({'reduceOnly': True}) return params - def create_order(self, pair: str, ordertype: str, side: str, amount: float, - rate: float, leverage: float = 1.0, time_in_force: str = 'gtc') -> Dict: + def create_order( + self, + pair: str, + ordertype: str, + side: str, + amount: float, + rate: float, + reduceOnly: bool = False, + leverage: float = 1.0, + time_in_force: str = 'gtc', + ) -> Dict: # TODO-lev: remove default for leverage if self._config['dry_run']: dry_order = self.create_dry_run_order(pair, ordertype, side, amount, rate, leverage) return dry_order - params = self._get_params(ordertype, leverage, time_in_force) + params = self._get_params(ordertype, leverage, reduceOnly, time_in_force) try: # Set the precision for amount and price(rate) as accepted by the exchange @@ -905,7 +922,9 @@ class Exchange: or self._api.options.get("createMarketBuyOrderRequiresPrice", False)) rate_for_order = self.price_to_precision(pair, rate) if needs_price else None - self._lev_prep(pair, leverage) + if not reduceOnly: + self._lev_prep(pair, leverage) + order = self._api.create_order( pair, ordertype, diff --git a/freqtrade/exchange/ftx.py b/freqtrade/exchange/ftx.py index 88e906a56..143be73ac 100644 --- a/freqtrade/exchange/ftx.py +++ b/freqtrade/exchange/ftx.py @@ -70,6 +70,8 @@ class Ftx(Exchange): if order_types.get('stoploss', 'market') == 'limit': # set orderPrice to place limit order, otherwise it's a market order params['orderPrice'] = limit_rate + if self.trading_mode == TradingMode.FUTURES: + params.update({'reduceOnly': True}) params['stopPrice'] = stop_price amount = self.amount_to_precision(pair, amount) diff --git a/freqtrade/exchange/kraken.py b/freqtrade/exchange/kraken.py index 308a6feab..3516f41d5 100644 --- a/freqtrade/exchange/kraken.py +++ b/freqtrade/exchange/kraken.py @@ -101,6 +101,8 @@ class Kraken(Exchange): Stoploss market orders is the only stoploss type supported by kraken. """ params = self._params.copy() + if self.trading_mode == TradingMode.FUTURES: + params.update({'reduceOnly': True}) if order_types.get('stoploss', 'market') == 'limit': ordertype = "stop-loss-limit" @@ -159,8 +161,14 @@ class Kraken(Exchange): """ return - def _get_params(self, ordertype: str, leverage: float, time_in_force: str = 'gtc') -> Dict: - params = super()._get_params(ordertype, leverage, time_in_force) + def _get_params( + self, + ordertype: str, + leverage: float, + reduceOnly: bool, + time_in_force: str = 'gtc' + ) -> Dict: + params = super()._get_params(ordertype, leverage, reduceOnly, time_in_force) if leverage > 1.0: params['leverage'] = leverage return params diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 38d80ab7a..6f39c23f7 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -699,6 +699,7 @@ class FreqtradeBot(LoggingMixin): side=side, amount=amount, rate=enter_limit_requested, + reduceOnly=False, time_in_force=time_in_force, leverage=leverage ) @@ -1422,6 +1423,7 @@ class FreqtradeBot(LoggingMixin): side=trade.exit_side, amount=amount, rate=limit, + reduceOnly=self.trading_mode == TradingMode.FUTURES, time_in_force=time_in_force ) except InsufficientFundsError as e: