Added gateio and okex isolated liquidation formulas
This commit is contained in:
parent
ba02605d77
commit
5796d95a95
@ -6,18 +6,74 @@ from freqtrade.exceptions import OperationalException
|
|||||||
|
|
||||||
def liquidation_price(
|
def liquidation_price(
|
||||||
exchange_name: str,
|
exchange_name: str,
|
||||||
open_rate: float,
|
open_rate: float, # (b) Entry price of position
|
||||||
is_short: bool,
|
is_short: bool,
|
||||||
leverage: float,
|
leverage: float,
|
||||||
trading_mode: TradingMode,
|
trading_mode: TradingMode,
|
||||||
collateral: Optional[Collateral],
|
collateral: Optional[Collateral],
|
||||||
wallet_balance: Optional[float],
|
# Binance
|
||||||
mm_ex_1: Optional[float],
|
collateral_amount: Optional[float] = None, # (bg)
|
||||||
upnl_ex_1: Optional[float],
|
mm_ex_1: Optional[float] = None, # (b)
|
||||||
maintenance_amt: Optional[float],
|
upnl_ex_1: Optional[float] = None, # (b)
|
||||||
position: Optional[float],
|
maintenance_amt: Optional[float] = None, # (b) (cum_b)
|
||||||
mm_rate: Optional[float]
|
position: Optional[float] = None, # (b) Absolute value of position size
|
||||||
|
mm_rate: Optional[float] = None, # (b)
|
||||||
|
# Gateio & Okex
|
||||||
|
mm_ratio: Optional[float] = None, # (go)
|
||||||
|
taker_fee_rate: Optional[float] = None, # (go)
|
||||||
|
# Gateio
|
||||||
|
base_size: Optional[float] = None, # (g)
|
||||||
|
# Okex
|
||||||
|
liability: Optional[float] = None, # (o)
|
||||||
|
interest: Optional[float] = None, # (o)
|
||||||
|
position_assets: Optional[float] = None, # (o)
|
||||||
) -> Optional[float]:
|
) -> Optional[float]:
|
||||||
|
'''
|
||||||
|
exchange_name
|
||||||
|
is_short
|
||||||
|
leverage
|
||||||
|
trading_mode
|
||||||
|
collateral
|
||||||
|
#
|
||||||
|
open_rate - b
|
||||||
|
collateral_amount - bg
|
||||||
|
In Cross margin mode, WB is crossWalletBalance
|
||||||
|
In Isolated margin mode, WB is isolatedWalletBalance of the isolated position,
|
||||||
|
TMM=0, UPNL=0, substitute the position quantity, MMR, cum into the formula to calculate.
|
||||||
|
Under the cross margin mode, the same ticker/symbol,
|
||||||
|
both long and short position share the same liquidation price except in the isolated mode.
|
||||||
|
Under the isolated mode, each isolated position will have different liquidation prices depending
|
||||||
|
on the margin allocated to the positions.
|
||||||
|
mm_ex_1 - b
|
||||||
|
Maintenance Margin of all other contracts, excluding Contract 1
|
||||||
|
If it is an isolated margin mode, then TMM=0,UPNL=0
|
||||||
|
upnl_ex_1 - b
|
||||||
|
Unrealized PNL of all other contracts, excluding Contract 1
|
||||||
|
If it is an isolated margin mode, then UPNL=0
|
||||||
|
maintenance_amt (cumb) - b
|
||||||
|
Maintenance Amount of position
|
||||||
|
position - b
|
||||||
|
Absolute value of position size
|
||||||
|
mm_rate - b
|
||||||
|
Maintenance margin rate of position
|
||||||
|
# Gateio & okex
|
||||||
|
mm_ratio - go
|
||||||
|
- [assets in the position - (liability +interest) * mark price] / (maintenance margin + liquidation fee) (okex)
|
||||||
|
taker_fee_rate - go
|
||||||
|
# Gateio
|
||||||
|
base_size - g
|
||||||
|
The size of the position in base currency
|
||||||
|
# Okex
|
||||||
|
liability - o
|
||||||
|
Initial liabilities + deducted interest
|
||||||
|
• Long positions: Liability is calculated in quote currency.
|
||||||
|
• Short positions: Liability is calculated in trading currency.
|
||||||
|
interest - o
|
||||||
|
Interest that has not been deducted yet.
|
||||||
|
position_assets - o
|
||||||
|
# * I think this is the same as collateral_amount
|
||||||
|
Total position assets – on-hold by pending order
|
||||||
|
'''
|
||||||
if trading_mode == TradingMode.SPOT:
|
if trading_mode == TradingMode.SPOT:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -29,7 +85,7 @@ def liquidation_price(
|
|||||||
|
|
||||||
if exchange_name.lower() == "binance":
|
if exchange_name.lower() == "binance":
|
||||||
if (
|
if (
|
||||||
wallet_balance is None or
|
collateral_amount is None or
|
||||||
mm_ex_1 is None or
|
mm_ex_1 is None or
|
||||||
upnl_ex_1 is None or
|
upnl_ex_1 is None or
|
||||||
maintenance_amt is None or
|
maintenance_amt is None or
|
||||||
@ -48,7 +104,7 @@ def liquidation_price(
|
|||||||
leverage=leverage,
|
leverage=leverage,
|
||||||
trading_mode=trading_mode,
|
trading_mode=trading_mode,
|
||||||
collateral=collateral, # type: ignore
|
collateral=collateral, # type: ignore
|
||||||
wallet_balance=wallet_balance,
|
wallet_balance=collateral_amount,
|
||||||
mm_ex_1=mm_ex_1,
|
mm_ex_1=mm_ex_1,
|
||||||
upnl_ex_1=upnl_ex_1,
|
upnl_ex_1=upnl_ex_1,
|
||||||
maintenance_amt=maintenance_amt, # type: ignore
|
maintenance_amt=maintenance_amt, # type: ignore
|
||||||
@ -59,6 +115,51 @@ def liquidation_price(
|
|||||||
return kraken(open_rate, is_short, leverage, trading_mode, collateral)
|
return kraken(open_rate, is_short, leverage, trading_mode, collateral)
|
||||||
elif exchange_name.lower() == "ftx":
|
elif exchange_name.lower() == "ftx":
|
||||||
return ftx(open_rate, is_short, leverage, trading_mode, collateral)
|
return ftx(open_rate, is_short, leverage, trading_mode, collateral)
|
||||||
|
elif exchange_name.lower() == "gateio":
|
||||||
|
if (
|
||||||
|
not collateral_amount or
|
||||||
|
not base_size or
|
||||||
|
not mm_ratio or
|
||||||
|
not taker_fee_rate
|
||||||
|
):
|
||||||
|
raise OperationalException(
|
||||||
|
f"{exchange_name} {collateral} {trading_mode} requires parameters "
|
||||||
|
f"collateral_amount, contract_size, num_contracts, mm_ratio and taker_fee"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return gateio(
|
||||||
|
open_rate=open_rate,
|
||||||
|
is_short=is_short,
|
||||||
|
trading_mode=trading_mode,
|
||||||
|
collateral=collateral,
|
||||||
|
collateral_amount=collateral_amount,
|
||||||
|
base_size=base_size,
|
||||||
|
mm_ratio=mm_ratio,
|
||||||
|
taker_fee_rate=taker_fee_rate
|
||||||
|
)
|
||||||
|
elif exchange_name.lower() == "okex":
|
||||||
|
if (
|
||||||
|
not mm_ratio or
|
||||||
|
not liability or
|
||||||
|
not interest or
|
||||||
|
not taker_fee_rate or
|
||||||
|
not position_assets
|
||||||
|
):
|
||||||
|
raise OperationalException(
|
||||||
|
f"{exchange_name} {collateral} {trading_mode} requires parameters "
|
||||||
|
f"mm_ratio, liability, interest, taker_fee_rate, position_assets"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return okex(
|
||||||
|
is_short=is_short,
|
||||||
|
trading_mode=trading_mode,
|
||||||
|
collateral=collateral,
|
||||||
|
mm_ratio=mm_ratio,
|
||||||
|
liability=liability,
|
||||||
|
interest=interest,
|
||||||
|
taker_fee_rate=taker_fee_rate,
|
||||||
|
position_assets=position_assets,
|
||||||
|
)
|
||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
f"liquidation_price is not implemented for {exchange_name}"
|
f"liquidation_price is not implemented for {exchange_name}"
|
||||||
)
|
)
|
||||||
@ -94,29 +195,21 @@ def binance(
|
|||||||
mm_rate: float,
|
mm_rate: float,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Calculates the liquidation price on Binance
|
Calculates the liquidation price on Binance
|
||||||
:param is_short: true or false
|
:param is_short: true or false
|
||||||
:param leverage: leverage in float
|
:param leverage: leverage in float
|
||||||
:param trading_mode: spot, margin, futures
|
:param trading_mode: spot, margin, futures
|
||||||
:param collateral: cross, isolated
|
:param collateral: cross, isolated
|
||||||
|
:param wallet_balance: Wallet Balance is crossWalletBalance in Cross-Margin Mode.
|
||||||
: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 mm_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,
|
:param upnl_ex_1: Unrealized PNL of all other contracts, excluding Contract 1.
|
||||||
excluding Contract 1. If it is an isolated margin mode, then TMM=0
|
If it is an isolated margin mode, then UPNL=0
|
||||||
|
:param maintenance_amt: Maintenance Amount of position (one-way mode)
|
||||||
:param upnl_ex_1: Unrealized PNL of all other contracts, excluding Contract 1.
|
:param position: Absolute value of position size (one-way mode)
|
||||||
If it is an isolated margin mode, then UPNL=0
|
:param open_rate: Entry Price of position (one-way mode)
|
||||||
|
:param mm_rate: Maintenance margin rate of position (one-way mode)
|
||||||
:param maintenance_amt: Maintenance Amount of position (one-way mode)
|
|
||||||
|
|
||||||
:param position: Absolute value of position size (one-way mode)
|
|
||||||
|
|
||||||
:param open_rate: Entry Price of position (one-way mode)
|
|
||||||
|
|
||||||
:param mm_rate: Maintenance margin rate of position (one-way mode)
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Additional arguments, fill in formulas
|
# TODO-lev: Additional arguments, fill in formulas
|
||||||
wb = wallet_balance
|
wb = wallet_balance
|
||||||
@ -161,10 +254,9 @@ def kraken(
|
|||||||
collateral: Collateral
|
collateral: Collateral
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Calculates the liquidation price on Kraken
|
Calculates the liquidation price on Kraken
|
||||||
:param name: Name of the exchange
|
:param trading_mode: spot, margin, futures
|
||||||
:param trading_mode: spot, margin, futures
|
:param collateral: cross, isolated
|
||||||
:param collateral: cross, isolated
|
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Additional arguments, fill in formulas
|
# TODO-lev: Additional arguments, fill in formulas
|
||||||
|
|
||||||
@ -188,10 +280,9 @@ def ftx(
|
|||||||
collateral: Collateral
|
collateral: Collateral
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Calculates the liquidation price on FTX
|
Calculates the liquidation price on FTX
|
||||||
:param name: Name of the exchange
|
:param trading_mode: spot, margin, futures
|
||||||
:param trading_mode: spot, margin, futures
|
:param collateral: cross, isolated
|
||||||
:param collateral: cross, isolated
|
|
||||||
"""
|
"""
|
||||||
if collateral == Collateral.CROSS:
|
if collateral == Collateral.CROSS:
|
||||||
# TODO-lev: Additional arguments, fill in formulas
|
# TODO-lev: Additional arguments, fill in formulas
|
||||||
@ -201,18 +292,99 @@ def ftx(
|
|||||||
exception("ftx", trading_mode, collateral)
|
exception("ftx", trading_mode, collateral)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
def gateio(
|
||||||
print(liquidation_price(
|
open_rate: float,
|
||||||
"binance",
|
is_short: bool,
|
||||||
32481.980,
|
trading_mode: TradingMode,
|
||||||
False,
|
collateral: Collateral,
|
||||||
1,
|
collateral_amount: float,
|
||||||
TradingMode.FUTURES,
|
base_size: float,
|
||||||
Collateral.ISOLATED,
|
mm_ratio: float,
|
||||||
1535443.01,
|
taker_fee_rate: float,
|
||||||
356512.508,
|
is_inverse: bool = False
|
||||||
0.0,
|
):
|
||||||
16300.000,
|
"""
|
||||||
109.488,
|
Calculates the liquidation price on Gate.io
|
||||||
0.025
|
:param open_rate: Entry Price of position
|
||||||
))
|
:param is_short: True for short trades
|
||||||
|
:param trading_mode: spot, margin, futures
|
||||||
|
:param collateral: cross, isolated
|
||||||
|
:param collateral_amount: Also called margin
|
||||||
|
:param base_size: size of position in base currency
|
||||||
|
contract_size / num_contracts
|
||||||
|
contract_size: How much one contract is worth
|
||||||
|
num_contracts: Also called position
|
||||||
|
:param mm_ratio: Viewed in contract details
|
||||||
|
:param taker_fee_rate:
|
||||||
|
:param is_inverse: True if settle currency matches base currency
|
||||||
|
|
||||||
|
( Opening Price ± Margin/Contract Multiplier/Position ) / [ 1 ± ( MMR + Taker Fee)]
|
||||||
|
'±' in the formula refers to the direction of the contract,
|
||||||
|
go long refers to '-'
|
||||||
|
go short refers to '+'
|
||||||
|
Position refers to the number of contracts.
|
||||||
|
Maintenance Margin Ratio and Contract Multiplier can be viewed in the Contract Details.
|
||||||
|
|
||||||
|
https://www.gate.io/help/futures/perpetual/22160/calculation-of-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 = collateral_amount / base_size
|
||||||
|
|
||||||
|
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:
|
||||||
|
exception("gatio", trading_mode, collateral)
|
||||||
|
|
||||||
|
|
||||||
|
def okex(
|
||||||
|
is_short: bool,
|
||||||
|
trading_mode: TradingMode,
|
||||||
|
collateral: Collateral,
|
||||||
|
liability: float,
|
||||||
|
interest: float,
|
||||||
|
mm_ratio: float,
|
||||||
|
taker_fee_rate: float,
|
||||||
|
position_assets: float
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
https://www.okex.com/support/hc/en-us/articles/
|
||||||
|
360053909592-VI-Introduction-to-the-isolated-mode-of-Single-Multi-currency-Portfolio-margin
|
||||||
|
|
||||||
|
Initial liabilities + deducted interest
|
||||||
|
Long positions: Liability is calculated in quote currency.
|
||||||
|
Short positions: Liability is calculated in trading currency.
|
||||||
|
interest: Interest that has not been deducted yet.
|
||||||
|
Margin ratio
|
||||||
|
Long: [position_assets - (liability + interest) / mark_price] / (maintenance_margin + fees)
|
||||||
|
Short: [position_assets - (liability + interest) * mark_price] / (maintenance_margin + fees)
|
||||||
|
'''
|
||||||
|
if trading_mode == TradingMode.FUTURES and collateral == Collateral.ISOLATED:
|
||||||
|
if is_short:
|
||||||
|
return (liability + interest) * (1 + mm_ratio) * (1 + taker_fee_rate)
|
||||||
|
else:
|
||||||
|
return (liability + interest) * (1 + mm_ratio) * (1 + taker_fee_rate) / position_assets
|
||||||
|
else:
|
||||||
|
exception("okex", trading_mode, collateral)
|
||||||
|
|
||||||
|
# if __name__ == '__main__':
|
||||||
|
# print(liquidation_price(
|
||||||
|
# "binance",
|
||||||
|
# 32481.980,
|
||||||
|
# False,
|
||||||
|
# 1,
|
||||||
|
# TradingMode.FUTURES,
|
||||||
|
# Collateral.ISOLATED,
|
||||||
|
# 1535443.01,
|
||||||
|
# 356512.508,
|
||||||
|
# 0.0,
|
||||||
|
# 16300.000,
|
||||||
|
# 109.488,
|
||||||
|
# 0.025
|
||||||
|
# ))
|
||||||
|
@ -16,8 +16,7 @@ from sqlalchemy.sql.schema import UniqueConstraint
|
|||||||
from freqtrade.constants import DATETIME_PRINT_FORMAT, NON_OPEN_EXCHANGE_STATES
|
from freqtrade.constants import DATETIME_PRINT_FORMAT, NON_OPEN_EXCHANGE_STATES
|
||||||
from freqtrade.enums import Collateral, SellType, TradingMode
|
from freqtrade.enums import Collateral, SellType, TradingMode
|
||||||
from freqtrade.exceptions import DependencyException, OperationalException
|
from freqtrade.exceptions import DependencyException, OperationalException
|
||||||
from freqtrade.leverage import interest
|
from freqtrade.leverage import interest, liquidation_price
|
||||||
from freqtrade.leverage import liquidation_price
|
|
||||||
from freqtrade.misc import safe_value_fallback
|
from freqtrade.misc import safe_value_fallback
|
||||||
from freqtrade.persistence.migrations import check_migrate
|
from freqtrade.persistence.migrations import check_migrate
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user