Files
CoinOX/lib/hedge_plan/okx_trade_mode_lib.py
T
dekun 6607d09526 Make this repo hedge-only: skip standalone options UI by default.
Nav/env only expose 永期/期期; set STANDALONE_OPTIONS_UI=true for emergency opt-in.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 18:37:46 +08:00

114 lines
3.4 KiB
Python

"""OKX 对冲交易模式(env: OKX_TRADE_MODE).
本仓定位:仅对冲(永期/期期).单独期权产品面已迁出,默认不安装其 UI/复盘/独立盯盘.
期权执行层(报价/下单/买币桥)仍由对冲腿共用.
perp_options → 永期对冲
options_options → 期期对冲
options → 遗留值;未开 STANDALONE_OPTIONS_UI 时回退为永期
"""
from __future__ import annotations
import os
from typing import Optional
MODE_OPTIONS = "options"
MODE_PERP = "perp_options"
MODE_OO = "options_options"
VALID_MODES = frozenset({MODE_OPTIONS, MODE_PERP, MODE_OO})
# env 可选值(本仓默认只暴露对冲两种)
HEDGE_MODES = frozenset({MODE_PERP, MODE_OO})
_ALIASES = {
"option": MODE_OPTIONS,
"standalone": MODE_OPTIONS,
"期权": MODE_OPTIONS,
"单独期权": MODE_OPTIONS,
"po": MODE_PERP,
"perp": MODE_PERP,
"永期": MODE_PERP,
"永期对冲": MODE_PERP,
"oo": MODE_OO,
"期期": MODE_OO,
"期期对冲": MODE_OO,
}
def _env_bool(name: str, default: bool = False) -> bool:
raw = os.getenv(name)
if raw is None or str(raw).strip() == "":
return default
return str(raw).strip().lower() in ("1", "true", "yes", "on")
def standalone_options_ui_enabled() -> bool:
"""是否安装单独期权页/复盘/独立盯盘.本仓默认 false."""
return _env_bool("STANDALONE_OPTIONS_UI", False)
def normalize_okx_trade_mode(raw: Optional[str]) -> str:
s = str(raw or "").strip().lower()
if s in VALID_MODES:
return s
if s in _ALIASES:
return _ALIASES[s]
return ""
def legacy_infer_okx_trade_mode() -> str:
"""未配置 OKX_TRADE_MODE 时推断;本仓默认永期对冲."""
if not _env_bool("HEDGE_PLAN_ENABLED", True):
# 旧开关关对冲时,本仓仍回退永期(不再默认单独期权)
return MODE_PERP
show_po = _env_bool("HEDGE_PLAN_SHOW_PERP_OPTIONS", True)
show_oo = _env_bool("HEDGE_PLAN_SHOW_OPTIONS_OPTIONS", True)
if show_oo and not show_po:
return MODE_OO
return MODE_PERP
def get_okx_trade_mode() -> str:
m = normalize_okx_trade_mode(os.getenv("OKX_TRADE_MODE"))
if not m:
m = legacy_infer_okx_trade_mode()
# 未显式打开单独期权 UI 时,options 模式回退永期,避免空导航
if m == MODE_OPTIONS and not standalone_options_ui_enabled():
return MODE_PERP
return m
def hedge_module_enabled() -> bool:
return get_okx_trade_mode() in (MODE_PERP, MODE_OO)
def show_perp_options() -> bool:
return get_okx_trade_mode() == MODE_PERP
def show_options_options() -> bool:
return get_okx_trade_mode() == MODE_OO
def standalone_options_open_allowed() -> bool:
return standalone_options_ui_enabled() and get_okx_trade_mode() == MODE_OPTIONS
def mode_label(mode: Optional[str] = None) -> str:
m = mode or get_okx_trade_mode()
return {
MODE_OPTIONS: "单独期权",
MODE_PERP: "永期对冲",
MODE_OO: "期期对冲",
}.get(m, m or "—")
def block_standalone_open_by_mode_msg() -> Optional[str]:
if standalone_options_open_allowed():
return None
if not standalone_options_ui_enabled():
return "本实例仅对冲;单独期权请使用专用期权仓库"
return (
f"当前交易模式为「{mode_label()}」,不可单独开期权;"
"请在 env「交易模式」切换为「单独期权」(并开启 STANDALONE_OPTIONS_UI)"
)