2021-11-02 18:49:53 +00:00
|
|
|
|
import logging
|
2022-01-23 02:03:38 +00:00
|
|
|
|
from typing import Dict, List, Optional, Tuple
|
2021-11-02 18:49:53 +00:00
|
|
|
|
|
2021-11-05 05:26:13 +00:00
|
|
|
|
from freqtrade.enums import Collateral, TradingMode
|
2022-01-23 02:03:38 +00:00
|
|
|
|
from freqtrade.exceptions import OperationalException
|
2021-11-02 18:49:53 +00:00
|
|
|
|
from freqtrade.exchange import Exchange
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Okex(Exchange):
|
2021-11-09 10:31:54 +00:00
|
|
|
|
"""Okex exchange class.
|
|
|
|
|
|
|
|
|
|
Contains adjustments needed for Freqtrade to work with this exchange.
|
2021-11-02 18:49:53 +00:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
_ft_has: Dict = {
|
2022-01-06 13:31:23 +00:00
|
|
|
|
"ohlcv_candle_limit": 300,
|
2021-12-19 13:48:59 +00:00
|
|
|
|
"mark_ohlcv_timeframe": "4h",
|
|
|
|
|
"funding_fee_timeframe": "8h",
|
2021-11-02 18:49:53 +00:00
|
|
|
|
}
|
2021-11-05 05:26:13 +00:00
|
|
|
|
|
|
|
|
|
_supported_trading_mode_collateral_pairs: List[Tuple[TradingMode, Collateral]] = [
|
|
|
|
|
# TradingMode.SPOT always supported and not required in this list
|
2021-11-14 01:45:41 +00:00
|
|
|
|
# (TradingMode.MARGIN, Collateral.CROSS),
|
|
|
|
|
# (TradingMode.FUTURES, Collateral.CROSS),
|
|
|
|
|
# (TradingMode.FUTURES, Collateral.ISOLATED)
|
2021-11-05 05:26:13 +00:00
|
|
|
|
]
|
2022-01-23 02:03:38 +00:00
|
|
|
|
|
|
|
|
|
def liquidation_price_helper(
|
|
|
|
|
self,
|
|
|
|
|
open_rate: float, # Entry price of position
|
|
|
|
|
is_short: bool,
|
|
|
|
|
leverage: float,
|
|
|
|
|
trading_mode: TradingMode,
|
|
|
|
|
mm_ratio: float,
|
|
|
|
|
collateral: Collateral,
|
|
|
|
|
maintenance_amt: Optional[float] = None, # Not required
|
|
|
|
|
position: Optional[float] = None, # Not required
|
|
|
|
|
wallet_balance: Optional[float] = None, # Not required
|
|
|
|
|
taker_fee_rate: Optional[float] = None, # * required
|
|
|
|
|
liability: Optional[float] = None, # * required
|
|
|
|
|
interest: Optional[float] = None, # * required
|
|
|
|
|
position_assets: Optional[float] = None, # * required (Might be same as position)
|
|
|
|
|
mm_ex_1: Optional[float] = 0.0, # Not required
|
|
|
|
|
upnl_ex_1: Optional[float] = 0.0, # Not required
|
|
|
|
|
) -> Optional[float]:
|
|
|
|
|
"""
|
|
|
|
|
PERPETUAL: https://www.okex.com/support/hc/en-us/articles/
|
|
|
|
|
360053909592-VI-Introduction-to-the-isolated-mode-of-Single-Multi-currency-Portfolio-margin
|
|
|
|
|
|
|
|
|
|
:param exchange_name:
|
|
|
|
|
:param open_rate: (EP1) Entry price of position
|
|
|
|
|
:param is_short: True if the trade is a short, false otherwise
|
|
|
|
|
:param leverage: The amount of leverage on the trade
|
|
|
|
|
:param trading_mode: SPOT, MARGIN, FUTURES, etc.
|
|
|
|
|
:param position: Absolute value of position size (in base currency)
|
|
|
|
|
:param mm_ratio:
|
|
|
|
|
Okex: [assets in the position - (liability +interest) * mark price] /
|
|
|
|
|
(maintenance margin + liquidation fee)
|
|
|
|
|
:param collateral: Either ISOLATED or CROSS
|
|
|
|
|
:param maintenance_amt: # * Not required by Okex
|
|
|
|
|
:param wallet_balance: # * Not required by Okex
|
|
|
|
|
:param position: # * Not required by Okex
|
|
|
|
|
:param taker_fee_rate:
|
|
|
|
|
:param liability:
|
|
|
|
|
Initial liabilities + deducted interest
|
|
|
|
|
• Long positions: Liability is calculated in quote currency.
|
|
|
|
|
• Short positions: Liability is calculated in trading currency.
|
|
|
|
|
:param interest: Interest that has not been deducted yet.
|
|
|
|
|
:param position_assets: Total position assets – on-hold by pending order
|
|
|
|
|
:param mm_ex_1: # * Not required by Okex
|
|
|
|
|
:param upnl_ex_1: # * Not required by Okex
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if (not liability or not interest or not taker_fee_rate or not position_assets):
|
|
|
|
|
raise OperationalException(
|
|
|
|
|
"Parameters liability, interest, taker_fee_rate, position_assets"
|
|
|
|
|
"are required by Okex.liquidation_price"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
raise OperationalException(
|
|
|
|
|
f"Okex does not support {collateral.value} Mode {trading_mode.value} trading")
|