From 98d2d2f485f9605b5aa8eb7dd674b3bb3150f588 Mon Sep 17 00:00:00 2001 From: Arunavo Ray Date: Sun, 19 Sep 2021 11:16:41 +0530 Subject: [PATCH 1/2] Added Tests for Binance Liquidation price --- freqtrade/leverage/__init__.py | 1 + freqtrade/leverage/liquidation_price.py | 4 +-- tests/leverage/test_liquidation_price.py | 40 ++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 tests/leverage/test_liquidation_price.py diff --git a/freqtrade/leverage/__init__.py b/freqtrade/leverage/__init__.py index ae78f4722..0bb2dd0be 100644 --- a/freqtrade/leverage/__init__.py +++ b/freqtrade/leverage/__init__.py @@ -1,2 +1,3 @@ # flake8: noqa: F401 from freqtrade.leverage.interest import interest +from freqtrade.leverage.liquidation_price import liquidation_price diff --git a/freqtrade/leverage/liquidation_price.py b/freqtrade/leverage/liquidation_price.py index 8a9063a81..24b016ac9 100644 --- a/freqtrade/leverage/liquidation_price.py +++ b/freqtrade/leverage/liquidation_price.py @@ -123,7 +123,7 @@ 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)) / ( + return (wb + cum_b - side_1_both * position_1_both * ep1_both) / ( position_1_both * mmr_b - side_1_both * position_1_both) elif trading_mode == TradingMode.FUTURES and collateral == Collateral.CROSS: @@ -131,7 +131,7 @@ 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)) / ( + 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) # If nothing was returned diff --git a/tests/leverage/test_liquidation_price.py b/tests/leverage/test_liquidation_price.py new file mode 100644 index 000000000..f3fd54644 --- /dev/null +++ b/tests/leverage/test_liquidation_price.py @@ -0,0 +1,40 @@ +from math import isclose + +import pytest + +from freqtrade.enums import TradingMode, Collateral +from freqtrade.leverage import liquidation_price + + +@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, ' + '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_both, position_1_both, + entry_price_1_both, maintenance_margin_rate_both, 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_both=maintenance_amount_both, + position_1_both=position_1_both, + entry_price_1_both=entry_price_1_both, + maintenance_margin_rate_both=maintenance_margin_rate_both + ), 2), expected) From e5a9e118990609b925524d640c2a288921c8a17f Mon Sep 17 00:00:00 2001 From: Arunavo Ray Date: Sun, 19 Sep 2021 11:22:22 +0530 Subject: [PATCH 2/2] Removed `both` from parameters in liquidation price --- freqtrade/leverage/liquidation_price.py | 54 +++++++++---------- .../{test_leverage.py => test_interest.py} | 0 tests/leverage/test_liquidation_price.py | 14 ++--- 3 files changed, 34 insertions(+), 34 deletions(-) rename tests/leverage/{test_leverage.py => test_interest.py} (100%) diff --git a/freqtrade/leverage/liquidation_price.py b/freqtrade/leverage/liquidation_price.py index 24b016ac9..025a64846 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: return None @@ -29,16 +29,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) + 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": @@ -73,10 +73,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 @@ -95,24 +95,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 @@ -123,16 +123,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_leverage.py b/tests/leverage/test_interest.py similarity index 100% rename from tests/leverage/test_leverage.py rename to tests/leverage/test_interest.py diff --git a/tests/leverage/test_liquidation_price.py b/tests/leverage/test_liquidation_price.py index f3fd54644..216d0609a 100644 --- a/tests/leverage/test_liquidation_price.py +++ b/tests/leverage/test_liquidation_price.py @@ -8,7 +8,7 @@ from freqtrade.leverage import liquidation_price @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, ' + '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, @@ -21,8 +21,8 @@ from freqtrade.leverage import liquidation_price 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_both, position_1_both, - entry_price_1_both, maintenance_margin_rate_both, expected): + 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, @@ -33,8 +33,8 @@ def test_liquidation_price(exchange_name, open_rate, is_short, leverage, trading wallet_balance=wallet_balance, maintenance_margin_ex_1=maintenance_margin_ex_1, unrealized_pnl_ex_1=unrealized_pnl_ex_1, - maintenance_amount_both=maintenance_amount_both, - position_1_both=position_1_both, - entry_price_1_both=entry_price_1_both, - maintenance_margin_rate_both=maintenance_margin_rate_both + maintenance_amount=maintenance_amount, + position_1=position_1, + entry_price_1=entry_price_1, + maintenance_margin_rate=maintenance_margin_rate ), 2), expected)