From 3709130eb791901f64c165e6f0ab64bb57b28af4 Mon Sep 17 00:00:00 2001 From: Arunavo Ray Date: Sun, 19 Sep 2021 11:16:41 +0530 Subject: [PATCH] Added Tests for Binance Liquidation price, shortened liquidation param names --- freqtrade/leverage/liquidation_price.py | 81 ++++++++++++------------ tests/leverage/test_liquidation_price.py | 74 ++++++++++++---------- 2 files changed, 83 insertions(+), 72 deletions(-) diff --git a/freqtrade/leverage/liquidation_price.py b/freqtrade/leverage/liquidation_price.py index 12a2f0300..a18649812 100644 --- a/freqtrade/leverage/liquidation_price.py +++ b/freqtrade/leverage/liquidation_price.py @@ -12,12 +12,12 @@ def liquidation_price( trading_mode: TradingMode, collateral: Optional[Collateral], 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] + mm_ex_1: Optional[float], + upnl_ex_1: Optional[float], + maintenance_amt: Optional[float], + position: Optional[float], + entry_price: Optional[float], + mm_rate: Optional[float] ) -> Optional[float]: if trading_mode == TradingMode.SPOT: @@ -30,16 +30,17 @@ 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 mm_ex_1 or not upnl_ex_1 \ + or not maintenance_amt or not position or not entry_price \ + or not mm_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"when exchange is {exchange_name.lower()}") + f"Parameters wallet_balance, mm_ex_1, upnl_ex_1, " + f"maintenance_amt, position, entry_price, mm_rate " + f"is required by liquidation_price 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, + mm_ex_1, upnl_ex_1, maintenance_amt, + position, entry_price, mm_rate) elif exchange_name.lower() == "kraken": return kraken(open_rate, is_short, leverage, trading_mode, collateral) elif exchange_name.lower() == "ftx": @@ -72,12 +73,12 @@ def binance( trading_mode: TradingMode, collateral: Collateral, 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, + mm_ex_1: float, + upnl_ex_1: float, + maintenance_amt: float, + position: float, + entry_price: float, + mm_rate: float, ): """ Calculates the liquidation price on Binance @@ -88,32 +89,32 @@ def binance( :param collateral: cross, isolated :param wallet_balance: Wallet Balance is crossWalletBalance in Cross-Margin Mode. - Wallet Balance is isolatedWalletBalance in Isolated Margin Mode + Wallet Balance is isolatedWalletBalance in Isolated Margin Mode - :param maintenance_margin_ex_1: Maintenance Margin of all other contracts, excluding Contract 1. - If it is an isolated margin mode, then TMM=0 + :param mm_ex_1: Maintenance Margin of all other contracts, + excluding Contract 1. If it is an isolated margin mode, then TMM=0 - :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 upnl_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_amt: Maintenance Amount of position (one-way mode) - :param position_1_both: Absolute value of BOTH position size (one-way mode) + :param position: Absolute value of position size (one-way mode) - :param entry_price_1_both: Entry Price of BOTH position (one-way mode) + :param entry_price: Entry Price of position (one-way mode) - :param maintenance_margin_rate_both: Maintenance margin rate of BOTH position (one-way mode) + :param mm_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 + tmm_1 = 0.0 if collateral == Collateral.ISOLATED else mm_ex_1 + upnl_1 = 0.0 if collateral == Collateral.ISOLATED else upnl_ex_1 + cum_b = maintenance_amt + side_1 = -1 if is_short else 1 + position = abs(position) + ep1 = entry_price + mmr_b = mm_rate if trading_mode == TradingMode.MARGIN and collateral == Collateral.CROSS: # TODO-lev: perform a calculation based on this formula @@ -124,8 +125,8 @@ 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 * ep1) / ( + position * mmr_b - side_1 * position) elif trading_mode == TradingMode.FUTURES and collateral == Collateral.CROSS: # TODO-lev: perform a calculation based on this formula @@ -133,8 +134,8 @@ def binance( # 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 * ep1) / ( + position * mmr_b - side_1 * position) # 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 687dd57f4..a3f014bb4 100644 --- a/tests/leverage/test_liquidation_price.py +++ b/tests/leverage/test_liquidation_price.py @@ -1,3 +1,5 @@ +from math import isclose + import pytest from freqtrade.enums import Collateral, TradingMode @@ -46,7 +48,14 @@ def test_liquidation_price_is_none( is_short, leverage, trading_mode, - collateral + collateral, + 1535443.01, + 71200.81144, + -56354.57, + 135365.00, + 3683.979, + 1456.84, + 0.10, ) is None @@ -80,34 +89,35 @@ def test_liquidation_price_exception_thrown( @pytest.mark.parametrize( - 'exchange_name,open_rate,is_short,leverage,trading_mode,collateral,result', [ - # Binance - ('binance', "2.0", False, "1.0", margin, cross, 1.0), - ('binance', "2.0", False, "1.0", futures, cross, 1.0), - ('binance', "2.0", False, "1.0", futures, isolated, 1.0), - # Kraken - ('kraken', "2.0", True, "3.0", margin, cross, 1.0), - ('kraken', "2.0", True, "3.0", futures, cross, 1.0), - # FTX - ('ftx', "2.0", False, "3.0", margin, cross, 1.0), - ('ftx', "2.0", False, "3.0", futures, cross, 1.0), - ] -) -def test_liquidation_price( - exchange_name, - open_rate, - is_short, - leverage, - trading_mode, - collateral, - result -): - # assert liquidation_price( - # exchange_name, - # open_rate, - # is_short, - # leverage, - # trading_mode, - # collateral - # ) == result - return # Here to avoid indent error + 'exchange_name, open_rate, is_short, leverage, trading_mode, collateral, wallet_balance, ' + 'mm_ex_1, upnl_ex_1, maintenance_amt, position, entry_price, ' + 'mm_rate, expected', + [ + ("binance", 0.0, False, 1, TradingMode.FUTURES, Collateral.ISOLATED, 1535443.01, 71200.8114, + -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, mm_ex_1, upnl_ex_1, + maintenance_amt, position, entry_price, mm_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, + mm_ex_1=mm_ex_1, + upnl_ex_1=upnl_ex_1, + maintenance_amt=maintenance_amt, + position=position, + entry_price=entry_price, + mm_rate=mm_rate + ), 2), expected)