diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 41e9f5e66..c7d837471 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -2085,22 +2085,68 @@ class Exchange: upnl_ex_1=upnl_ex_1, ) - def liquidation_price_helper( - self, - open_rate: float, # Entry price of position - is_short: bool, - leverage: float, - mm_ratio: float, - position: float, # Absolute value of position size - trading_mode: TradingMode, - collateral: Collateral, - maintenance_amt: Optional[float] = None, # (Binance) - wallet_balance: Optional[float] = None, # (Binance and Gateio) - taker_fee_rate: Optional[float] = None, # (Gateio & Okex) - mm_ex_1: Optional[float] = 0.0, # (Binance) Cross only - upnl_ex_1: Optional[float] = 0.0, # (Binance) Cross only - ) -> Optional[float]: - raise OperationalException(f"liquidation_price is not implemented for {self.name}") + def liquidation_price_helper( + self, + open_rate: float, # Entry price of position + is_short: bool, + leverage: float, + mm_ratio: float, + position: float, # Absolute value of position size + wallet_balance: float, # Or margin balance + trading_mode: TradingMode, + collateral: Collateral, + taker_fee_rate: Optional[float] = None, # (Gateio & Okex) + maintenance_amt: Optional[float] = None, # (Binance) + mm_ex_1: Optional[float] = 0.0, # (Binance) Cross only + upnl_ex_1: Optional[float] = 0.0, # (Binance) Cross only + ) -> Optional[float]: + """ + PERPETUAL: + gateio: https://www.gate.io/help/futures/perpetual/22160/calculation-of-liquidation-price + okex: https://www.okex.com/support/hc/en-us/articles/ + 360053909592-VI-Introduction-to-the-isolated-mode-of-Single-Multi-currency-Portfolio-margin + + :param exchange_name: + :param open_rate: Entry price of position + :param is_short: True if the trade is a short, false otherwise + :param leverage: The amount of leverage on the trade + :param position: Absolute value of position size (in base currency) + :param mm_ratio: + :param trading_mode: SPOT, MARGIN, FUTURES, etc. + :param collateral: Either ISOLATED or CROSS + :param wallet_balance: Amount of collateral in the wallet being used to trade + Cross-Margin Mode: crossWalletBalance + Isolated-Margin Mode: isolatedWalletBalance + :param taker_fee_rate: + + # * Not required by Gateio or OKX + :param maintenance_amt: + :param mm_ex_1: + :param upnl_ex_1: + """ + if trading_mode == TradingMode.SPOT: + return None + + if (not taker_fee_rate): + raise OperationalException( + f"Parameter taker_fee_rate is required by {self.name}.liquidation_price" + ) + + if trading_mode == TradingMode.FUTURES and collateral == Collateral.ISOLATED: + # if is_inverse: + # raise OperationalException( + # "Freqtrade does not support inverse contracts at the moment") + + value = wallet_balance / position + + mm_ratio_taker = (mm_ratio + taker_fee_rate) + if is_short: + return (open_rate + value) / (1 + mm_ratio_taker) + else: + return (open_rate - value) / (1 - mm_ratio_taker) + else: + raise OperationalException( + f"{self.name} does not support {collateral.value} {trading_mode.value}") def is_exchange_known_ccxt(exchange_name: str, ccxt_module: CcxtModuleType = None) -> bool: diff --git a/freqtrade/exchange/gateio.py b/freqtrade/exchange/gateio.py index 3428fa1cf..c62b6222d 100644 --- a/freqtrade/exchange/gateio.py +++ b/freqtrade/exchange/gateio.py @@ -51,71 +51,3 @@ class Gateio(Exchange): """ info = self.markets[pair]['info'] return (float(info['maintenance_rate']), None) - - def liquidation_price_helper( - self, - open_rate: float, # Entry price of position - is_short: bool, - leverage: float, - mm_ratio: float, - position: float, # Absolute value of position size - trading_mode: TradingMode, - collateral: Collateral, - maintenance_amt: Optional[float] = None, # (Binance) - wallet_balance: Optional[float] = None, # (Binance and Gateio) - taker_fee_rate: Optional[float] = None, # (Gateio & Okex) - mm_ex_1: Optional[float] = 0.0, # (Binance) Cross only - upnl_ex_1: Optional[float] = 0.0, # (Binance) Cross only - ) -> Optional[float]: - """ - PERPETUAL: https://www.gate.io/help/futures/perpetual/22160/calculation-of-liquidation-price - - :param exchange_name: - :param open_rate: Entry price of position - :param is_short: True if the trade is a short, false otherwise - :param leverage: The amount of leverage on the trade - :param position: Absolute value of position size (in base currency) - :param mm_ratio: - :param trading_mode: SPOT, MARGIN, FUTURES, etc. - :param collateral: Either ISOLATED or CROSS - :param maintenance_amt: # * Not required by Gateio - :param wallet_balance: - Cross-Margin Mode: crossWalletBalance - Isolated-Margin Mode: isolatedWalletBalance - :param taker_fee_rate: - - # * Not required by Gateio - :param mm_ex_1: - :param upnl_ex_1: - """ - if trading_mode == TradingMode.SPOT: - return None - - if not collateral: - raise OperationalException( - "Parameter collateral is required by liquidation_price when trading_mode is " - f"{trading_mode}" - ) - - if (not wallet_balance or not position or not taker_fee_rate): - raise OperationalException( - "Parameters wallet_balance, position, taker_fee_rate" - "are required by Gateio.liquidation_price" - ) - - if trading_mode == TradingMode.FUTURES and collateral == Collateral.ISOLATED: - # if is_inverse: - # # ! Not implemented - # raise OperationalException( - # "Freqtrade does not support inverse contracts at the moment") - - value = wallet_balance / position - - mm_ratio_taker = (mm_ratio + taker_fee_rate) - if is_short: - return (open_rate + value) / (1 + mm_ratio_taker) - else: - return (open_rate - value) / (1 - mm_ratio_taker) - else: - raise OperationalException( - f"Gateio does not support {collateral.value} Mode {trading_mode.value} trading ") diff --git a/freqtrade/exchange/okex.py b/freqtrade/exchange/okex.py index b62d8fdf8..b15e686d3 100644 --- a/freqtrade/exchange/okex.py +++ b/freqtrade/exchange/okex.py @@ -27,54 +27,3 @@ class Okex(Exchange): # (TradingMode.FUTURES, Collateral.CROSS), # (TradingMode.FUTURES, Collateral.ISOLATED) ] - - def liquidation_price_helper( - self, - open_rate: float, # Entry price of position - is_short: bool, - leverage: float, - mm_ratio: float, - position: float, # Absolute value of position size - trading_mode: TradingMode, - collateral: Collateral, - maintenance_amt: Optional[float] = None, # (Binance) - wallet_balance: Optional[float] = None, # (Binance and Gateio) - taker_fee_rate: Optional[float] = None, # (Gateio & Okex) - mm_ex_1: Optional[float] = 0.0, # (Binance) Cross only - upnl_ex_1: Optional[float] = 0.0, # (Binance) Cross only - ) -> Optional[float]: - """ - PERPETUAL: https://www.okex.com/support/hc/en-us/articles/ - 360053909592-VI-Introduction-to-the-isolated-mode-of-Single-Multi-currency-Portfolio-margin - - :param exchange_name: - :param open_rate: (EP1) Entry price of position - :param is_short: True if the trade is a short, false otherwise - :param leverage: The amount of leverage on the trade - :param position: Absolute value of position size (in base currency) - :param mm_ratio: - Okex: [assets in the position - (liability +interest) * mark price] / - (maintenance margin + liquidation fee) - :param trading_mode: SPOT, MARGIN, FUTURES, etc. - :param collateral: Either ISOLATED or CROSS - :param maintenance_amt: # * Not required by Okex - :param wallet_balance: # * margin_balance? - :param taker_fee_rate: - :param mm_ex_1: # * Not required by Okex - :param upnl_ex_1: # * Not required by Okex - """ - - if (not taker_fee_rate): - raise OperationalException( - "Parameter taker_fee_rate is required by Okex.liquidation_price" - ) - - if trading_mode == TradingMode.FUTURES and collateral == Collateral.ISOLATED: - - if is_short: - return (margin_balance + (face_value * number_of_contracts * open_price)) / [face_value * number_of_contracts * (mm_ratio + taker_fee_rate + 1)] - else: - return (margin_balance - (face_value * number_of_contracts * open_price)) / [face_value * number_of_contracts * (mm_ratio + taker_fee_rate - 1)] - else: - raise OperationalException( - f"Okex does not support {collateral.value} Mode {trading_mode.value} trading")