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(
|
||||
exchange_name: str,
|
||||
open_rate: float,
|
||||
open_rate: float, # (b) Entry price of position
|
||||
is_short: bool,
|
||||
leverage: float,
|
||||
trading_mode: TradingMode,
|
||||
collateral: Optional[Collateral],
|
||||
wallet_balance: Optional[float],
|
||||
mm_ex_1: Optional[float],
|
||||
upnl_ex_1: Optional[float],
|
||||
maintenance_amt: Optional[float],
|
||||
position: Optional[float],
|
||||
mm_rate: Optional[float]
|
||||
# Binance
|
||||
collateral_amount: Optional[float] = None, # (bg)
|
||||
mm_ex_1: Optional[float] = None, # (b)
|
||||
upnl_ex_1: Optional[float] = None, # (b)
|
||||
maintenance_amt: Optional[float] = None, # (b) (cum_b)
|
||||
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]:
|
||||
'''
|
||||
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:
|
||||
return None
|
||||
|
||||
@ -29,7 +85,7 @@ def liquidation_price(
|
||||
|
||||
if exchange_name.lower() == "binance":
|
||||
if (
|
||||
wallet_balance is None or
|
||||
collateral_amount is None or
|
||||
mm_ex_1 is None or
|
||||
upnl_ex_1 is None or
|
||||
maintenance_amt is None or
|
||||
@ -48,7 +104,7 @@ def liquidation_price(
|
||||
leverage=leverage,
|
||||
trading_mode=trading_mode,
|
||||
collateral=collateral, # type: ignore
|
||||
wallet_balance=wallet_balance,
|
||||
wallet_balance=collateral_amount,
|
||||
mm_ex_1=mm_ex_1,
|
||||
upnl_ex_1=upnl_ex_1,
|
||||
maintenance_amt=maintenance_amt, # type: ignore
|
||||
@ -59,6 +115,51 @@ def liquidation_price(
|
||||
return kraken(open_rate, is_short, leverage, trading_mode, collateral)
|
||||
elif exchange_name.lower() == "ftx":
|
||||
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(
|
||||
f"liquidation_price is not implemented for {exchange_name}"
|
||||
)
|
||||
@ -94,29 +195,21 @@ def binance(
|
||||
mm_rate: float,
|
||||
):
|
||||
"""
|
||||
Calculates the liquidation price on Binance
|
||||
:param is_short: true or false
|
||||
:param leverage: leverage in float
|
||||
:param trading_mode: spot, margin, futures
|
||||
:param collateral: cross, isolated
|
||||
|
||||
:param wallet_balance: Wallet Balance is crossWalletBalance in Cross-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 upnl_ex_1: Unrealized PNL of all other contracts, excluding Contract 1.
|
||||
If it is an isolated margin mode, then UPNL=0
|
||||
|
||||
: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)
|
||||
|
||||
Calculates the liquidation price on Binance
|
||||
:param is_short: true or false
|
||||
:param leverage: leverage in float
|
||||
:param trading_mode: spot, margin, futures
|
||||
:param collateral: cross, isolated
|
||||
:param wallet_balance: Wallet Balance is crossWalletBalance in Cross-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 upnl_ex_1: Unrealized PNL of all other contracts, excluding Contract 1.
|
||||
If it is an isolated margin mode, then UPNL=0
|
||||
: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
|
||||
wb = wallet_balance
|
||||
@ -161,10 +254,9 @@ def kraken(
|
||||
collateral: Collateral
|
||||
):
|
||||
"""
|
||||
Calculates the liquidation price on Kraken
|
||||
:param name: Name of the exchange
|
||||
:param trading_mode: spot, margin, futures
|
||||
:param collateral: cross, isolated
|
||||
Calculates the liquidation price on Kraken
|
||||
:param trading_mode: spot, margin, futures
|
||||
:param collateral: cross, isolated
|
||||
"""
|
||||
# TODO-lev: Additional arguments, fill in formulas
|
||||
|
||||
@ -188,10 +280,9 @@ def ftx(
|
||||
collateral: Collateral
|
||||
):
|
||||
"""
|
||||
Calculates the liquidation price on FTX
|
||||
:param name: Name of the exchange
|
||||
:param trading_mode: spot, margin, futures
|
||||
:param collateral: cross, isolated
|
||||
Calculates the liquidation price on FTX
|
||||
:param trading_mode: spot, margin, futures
|
||||
:param collateral: cross, isolated
|
||||
"""
|
||||
if collateral == Collateral.CROSS:
|
||||
# TODO-lev: Additional arguments, fill in formulas
|
||||
@ -201,18 +292,99 @@ def ftx(
|
||||
exception("ftx", 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
|
||||
))
|
||||
def gateio(
|
||||
open_rate: float,
|
||||
is_short: bool,
|
||||
trading_mode: TradingMode,
|
||||
collateral: Collateral,
|
||||
collateral_amount: float,
|
||||
base_size: float,
|
||||
mm_ratio: float,
|
||||
taker_fee_rate: float,
|
||||
is_inverse: bool = False
|
||||
):
|
||||
"""
|
||||
Calculates the liquidation price on Gate.io
|
||||
: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.enums import Collateral, SellType, TradingMode
|
||||
from freqtrade.exceptions import DependencyException, OperationalException
|
||||
from freqtrade.leverage import interest
|
||||
from freqtrade.leverage import liquidation_price
|
||||
from freqtrade.leverage import interest, liquidation_price
|
||||
from freqtrade.misc import safe_value_fallback
|
||||
from freqtrade.persistence.migrations import check_migrate
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user