"""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「交易模式」切换为「单独期权」" )