From f681ce9139896225c7ea50b8af6900eae81301b5 Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 31 Dec 2022 15:53:43 +0100 Subject: [PATCH] Allow margin and leverage setting failures (this is important when an exchange "fails" a request if the setting didn't change). --- freqtrade/exchange/bybit.py | 26 ++++++++++++++++++++++++++ freqtrade/exchange/exchange.py | 14 ++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/freqtrade/exchange/bybit.py b/freqtrade/exchange/bybit.py index cb8faa7a8..fc79abd6a 100644 --- a/freqtrade/exchange/bybit.py +++ b/freqtrade/exchange/bybit.py @@ -2,6 +2,7 @@ import logging from typing import Any, Dict, List, Optional, Tuple +from freqtrade.constants import BuySell from freqtrade.enums import MarginMode, TradingMode from freqtrade.exceptions import OperationalException from freqtrade.exchange import Exchange @@ -82,6 +83,31 @@ class Bybit(Exchange): data = [[x['timestamp'], x['fundingRate'], 0, 0, 0, 0] for x in data] return data + def _lev_prep(self, pair: str, leverage: float, side: BuySell): + if self.trading_mode != TradingMode.SPOT: + params = {'leverage': leverage} + self.set_margin_mode(pair, self.margin_mode, accept_fail=True, params=params) + self._set_leverage(leverage, pair, accept_fail=True) + + def _get_params( + self, + side: BuySell, + ordertype: str, + leverage: float, + reduceOnly: bool, + time_in_force: str = 'GTC', + ) -> Dict: + params = super()._get_params( + side=side, + ordertype=ordertype, + leverage=leverage, + reduceOnly=reduceOnly, + time_in_force=time_in_force, + ) + if self.trading_mode == TradingMode.FUTURES and self.margin_mode: + params['position_idx'] = 0 + return params + def dry_run_liquidation_price( self, pair: str, diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 2e172c652..9b0419cd6 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -2484,7 +2484,8 @@ class Exchange: self, leverage: float, pair: Optional[str] = None, - trading_mode: Optional[TradingMode] = None + trading_mode: Optional[TradingMode] = None, + accept_fail: bool = False, ): """ Set's the leverage before making a trade, in order to not @@ -2499,6 +2500,10 @@ class Exchange: self._log_exchange_response('set_leverage', res) except ccxt.DDoSProtection as e: raise DDosProtection(e) from e + except ccxt.BadRequest as e: + if not accept_fail: + raise TemporaryError( + f'Could not set leverage due to {e.__class__.__name__}. Message: {e}') from e except (ccxt.NetworkError, ccxt.ExchangeError) as e: raise TemporaryError( f'Could not set leverage due to {e.__class__.__name__}. Message: {e}') from e @@ -2520,7 +2525,8 @@ class Exchange: return open_date.minute > 0 or open_date.second > 0 @retrier - def set_margin_mode(self, pair: str, margin_mode: MarginMode, params: dict = {}): + def set_margin_mode(self, pair: str, margin_mode: MarginMode, accept_fail: bool = False, + params: dict = {}): """ Set's the margin mode on the exchange to cross or isolated for a specific pair :param pair: base/quote currency pair (e.g. "ADA/USDT") @@ -2534,6 +2540,10 @@ class Exchange: self._log_exchange_response('set_margin_mode', res) except ccxt.DDoSProtection as e: raise DDosProtection(e) from e + except ccxt.BadRequest as e: + if not accept_fail: + raise TemporaryError( + f'Could not set margin mode due to {e.__class__.__name__}. Message: {e}') from e except (ccxt.NetworkError, ccxt.ExchangeError) as e: raise TemporaryError( f'Could not set margin mode due to {e.__class__.__name__}. Message: {e}') from e