diff --git a/freqtrade/leverage/liquidation_price.py b/freqtrade/leverage/liquidation_price.py index 2eb660394..7bab2af37 100644 --- a/freqtrade/leverage/liquidation_price.py +++ b/freqtrade/leverage/liquidation_price.py @@ -14,10 +14,10 @@ def liquidation_price( wallet_balance: Optional[float], maintenance_margin_ex_1: Optional[float], unrealized_pnl_ex_1: Optional[float], - maintenance_amount_both: Optional[float], - position_1_both: Optional[float], - entry_price_1_both: Optional[float], - maintenance_margin_rate_both: Optional[float] + maintenance_amount: Optional[float], + position_1: Optional[float], + entry_price_1: Optional[float], + maintenance_margin_rate: Optional[float] ) -> Optional[float]: if trading_mode == TradingMode.SPOT: @@ -30,34 +30,16 @@ def liquidation_price( ) if exchange_name.lower() == "binance": - if ( - not wallet_balance or - not maintenance_margin_ex_1 or - not unrealized_pnl_ex_1 or - not maintenance_amount_both or - not position_1_both or - not entry_price_1_both or - not maintenance_margin_rate_both - ): + if not wallet_balance or not maintenance_margin_ex_1 or not unrealized_pnl_ex_1 or not maintenance_amount \ + or not position_1 or not entry_price_1 or not maintenance_margin_rate: raise OperationalException( - f"Parameters wallet_balance, maintenance_margin_ex_1, unrealized_pnl_ex_1, maintenance_amount_both, " - f"position_1_both, entry_price_1_both, maintenance_margin_rate_both is required by liquidation_price " + f"Parameters wallet_balance, maintenance_margin_ex_1, unrealized_pnl_ex_1, maintenance_amount, " + f"position_1, entry_price_1, maintenance_margin_rate is required by liquidation_price " f"when exchange is {exchange_name.lower()}") - return binance( - open_rate, - is_short, - leverage, - trading_mode, - collateral, - wallet_balance, - maintenance_margin_ex_1, - unrealized_pnl_ex_1, - maintenance_amount_both, - position_1_both, - entry_price_1_both, - maintenance_margin_rate_both - ) + return binance(open_rate, is_short, leverage, trading_mode, collateral, wallet_balance, maintenance_margin_ex_1, + unrealized_pnl_ex_1, maintenance_amount, position_1, entry_price_1, + maintenance_margin_rate) elif exchange_name.lower() == "kraken": return kraken(open_rate, is_short, leverage, trading_mode, collateral) elif exchange_name.lower() == "ftx": @@ -92,10 +74,10 @@ def binance( wallet_balance: float, maintenance_margin_ex_1: float, unrealized_pnl_ex_1: float, - maintenance_amount_both: float, - position_1_both: float, - entry_price_1_both: float, - maintenance_margin_rate_both: float, + maintenance_amount: float, + position_1: float, + entry_price_1: float, + maintenance_margin_rate: float, ): r""" Calculates the liquidation price on Binance @@ -114,24 +96,24 @@ def binance( :param unrealized_pnl_ex_1: Unrealized PNL of all other contracts, excluding Contract 1. If it is an isolated margin mode, then UPNL=0 - :param maintenance_amount_both: Maintenance Amount of BOTH position (one-way mode) + :param maintenance_amount: Maintenance Amount of position (one-way mode) - :param position_1_both: Absolute value of BOTH position size (one-way mode) + :param position_1: Absolute value of position size (one-way mode) - :param entry_price_1_both: Entry Price of BOTH position (one-way mode) + :param entry_price_1: Entry Price of position (one-way mode) - :param maintenance_margin_rate_both: Maintenance margin rate of BOTH position (one-way mode) + :param maintenance_margin_rate: Maintenance margin rate of position (one-way mode) """ # TODO-lev: Additional arguments, fill in formulas wb = wallet_balance tmm_1 = 0.0 if collateral == Collateral.ISOLATED else maintenance_margin_ex_1 upnl_1 = 0.0 if collateral == Collateral.ISOLATED else unrealized_pnl_ex_1 - cum_b = maintenance_amount_both - side_1_both = -1 if is_short else 1 - position_1_both = abs(position_1_both) - ep1_both = entry_price_1_both - mmr_b = maintenance_margin_rate_both + cum_b = maintenance_amount + side_1 = -1 if is_short else 1 + position_1 = abs(position_1) + ep1 = entry_price_1 + mmr_b = maintenance_margin_rate if trading_mode == TradingMode.MARGIN and collateral == Collateral.CROSS: # TODO-lev: perform a calculation based on this formula @@ -142,16 +124,16 @@ def binance( # Liquidation Price of USDⓈ-M Futures Contracts Isolated # Isolated margin mode, then TMM=0,UPNL=0 - return (wb + cum_b - (side_1_both * position_1_both * ep1_both)) / ( - position_1_both * mmr_b - side_1_both * position_1_both) + return (wb + cum_b - side_1 * position_1 * ep1) / ( + position_1 * mmr_b - side_1 * position_1) elif trading_mode == TradingMode.FUTURES and collateral == Collateral.CROSS: # https://www.binance.com/en/support/faq/b3c689c1f50a44cabb3a84e663b81d93 # Liquidation Price of USDⓈ-M Futures Contracts Cross # Isolated margin mode, then TMM=0,UPNL=0 - return (wb - tmm_1 + upnl_1 + cum_b - (side_1_both * position_1_both * ep1_both)) / ( - position_1_both * mmr_b - side_1_both * position_1_both) + return (wb - tmm_1 + upnl_1 + cum_b - side_1 * position_1 * ep1) / ( + position_1 * mmr_b - side_1 * position_1) # If nothing was returned exception("binance", trading_mode, collateral) diff --git a/tests/leverage/test_liquidation_price.py b/tests/leverage/test_liquidation_price.py index ade1d83ea..6a3351d41 100644 --- a/tests/leverage/test_liquidation_price.py +++ b/tests/leverage/test_liquidation_price.py @@ -1,4 +1,5 @@ import pytest +from math import isclose from freqtrade.enums import Collateral, TradingMode from freqtrade.leverage import liquidation_price @@ -87,44 +88,34 @@ def test_liquidation_price_exception_thrown( @pytest.mark.parametrize( - ('exchange_name,open_rate,is_short,leverage,trading_mode,collateral,wallet_balance,' - 'maintenance_margin_ex_1,unrealized_pnl_ex_1,maintenance_amount_both,' - 'position_1_both,entry_price_1_both,maintenance_margin_rate_both,liq_price'), [ - # Binance - ("binance", 0.0, False, 1, futures, cross, 1535443.01, - 71200.81144, -56354.57, 135365.00, 3683.979, 1456.84, 0.10, 1153.26) - # Kraken - # FTX - ] -) -def test_liquidation_price( - exchange_name, - open_rate, - is_short, - leverage, - trading_mode, - collateral, - wallet_balance, - maintenance_margin_ex_1, - unrealized_pnl_ex_1, - maintenance_amount_both, - position_1_both, - entry_price_1_both, - maintenance_margin_rate_both, - liq_price -): - assert liquidation_price( - exchange_name, - open_rate, - is_short, - leverage, - trading_mode, - collateral, - wallet_balance, - maintenance_margin_ex_1, - unrealized_pnl_ex_1, - maintenance_amount_both, - position_1_both, - entry_price_1_both, - maintenance_margin_rate_both - ) == liq_price + 'exchange_name, open_rate, is_short, leverage, trading_mode, collateral, wallet_balance, maintenance_margin_ex_1, ' + 'unrealized_pnl_ex_1, maintenance_amount, position_1, entry_price_1, maintenance_margin_rate, ' + 'expected', + [ + ("binance", 0.0, False, 1, TradingMode.FUTURES, Collateral.ISOLATED, 1535443.01, 71200.81144, -56354.57, + 135365.00, 3683.979, 1456.84, 0.10, 1114.78), + ("binance", 0.0, False, 1, TradingMode.FUTURES, Collateral.ISOLATED, 1535443.01, 356512.508, -448192.89, + 16300.000, 109.488, 32481.980, 0.025, 18778.73), + ("binance", 0.0, False, 1, TradingMode.FUTURES, Collateral.CROSS, 1535443.01, 71200.81144, -56354.57, 135365.00, + 3683.979, 1456.84, 0.10, 1153.26), + ("binance", 0.0, False, 1, TradingMode.FUTURES, Collateral.CROSS, 1535443.01, 356512.508, -448192.89, 16300.000, + 109.488, 32481.980, 0.025, 26316.89) + ]) +def test_liquidation_price(exchange_name, open_rate, is_short, leverage, trading_mode, collateral, wallet_balance, + maintenance_margin_ex_1, unrealized_pnl_ex_1, maintenance_amount, position_1, + entry_price_1, maintenance_margin_rate, expected): + assert isclose(round(liquidation_price( + exchange_name=exchange_name, + open_rate=open_rate, + is_short=is_short, + leverage=leverage, + trading_mode=trading_mode, + collateral=collateral, + wallet_balance=wallet_balance, + maintenance_margin_ex_1=maintenance_margin_ex_1, + unrealized_pnl_ex_1=unrealized_pnl_ex_1, + maintenance_amount=maintenance_amount, + position_1=position_1, + entry_price_1=entry_price_1, + maintenance_margin_rate=maintenance_margin_rate + ), 2), expected)