6215d0975d
Reject blank float/int/select on save and parse env with safe helpers so options config edits cannot crash into 502; default OKX_TRADE_MODE=options and OKX_OPTIONS_MARGIN_MODE=coin. Co-authored-by: Cursor <cursoragent@cursor.com>
97 lines
2.5 KiB
Python
97 lines
2.5 KiB
Python
"""OKX 期权/对冲模式(env: OKX_TRADE_MODE).
|
|
|
|
options → 仅单独期权(隐藏对冲导航与对冲 env 配置)
|
|
options_options → 仅期期对冲(不可单独开期权)
|
|
perp_options → 永期对冲(含合约腿);产品 UI 已隐藏,仅兼容旧 .env / 历史计划
|
|
"""
|
|
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})
|
|
# 配置页可选模式(不含永期)
|
|
UI_MODES = frozenset({MODE_OPTIONS, 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 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 时默认单独期权(对冲关闭).
|
|
|
|
旧 HEDGE_PLAN_* 开关不再自动打开对冲,避免误开;需显式设 OKX_TRADE_MODE=options_options.
|
|
"""
|
|
return MODE_OPTIONS
|
|
|
|
|
|
def get_okx_trade_mode() -> str:
|
|
m = normalize_okx_trade_mode(os.getenv("OKX_TRADE_MODE"))
|
|
if m:
|
|
return m
|
|
return legacy_infer_okx_trade_mode()
|
|
|
|
|
|
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 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
|
|
return (
|
|
f"当前交易模式为「{mode_label()}」,不可单独开期权;"
|
|
"请在 env「交易模式」切换为「单独期权」"
|
|
)
|