diff --git a/.env.example b/.env.example index de374b6..dba96c8 100644 --- a/.env.example +++ b/.env.example @@ -102,11 +102,11 @@ OKX_POSITION_INST_TYPE=SWAP EXCHANGE_DISPLAY_NAME=OKX # 企业微信推送里展示的账户备注 # OKX_ACCOUNT_LABEL= -# 顶栏是否显示 USDT 资金/交易账户(热更);false 时总资金仅计期权 USDC 侧 +# 顶栏是否显示 USDT 资金/交易账户(热更);币本位买币仍会显示交易账户可用额 OKX_SHOW_PERP_FUNDS=true # ============================================================================= -# 期权模块(与上方 OKX_API_* 同源;修改启用开关后须重启 PM2) +# 期权模块(币本位专用;与上方 OKX_API_* 同源;修改启用开关后须重启 PM2) # 详见 docs/期权方案.md 与 docs/期权用法.md # ============================================================================= OKX_OPTIONS_ENABLED=true @@ -116,7 +116,7 @@ OKX_OPTIONS_ENABLED=true # OKX_OPTIONS_API_PASSPHRASE= OKX_OPTIONS_ACCOUNT_LABEL=账户·期权 -# 单笔期权本位: coin(默认,币本位+USDT买币桥) | usdc(权利金USDC;对冲仍仅USDC) +# 固定币本位(USDT买币桥);历史 OKX_OPTIONS_MARGIN_MODE=usdc 会被忽略并视为 coin OKX_OPTIONS_MARGIN_MODE=coin OKX_OPTIONS_COIN_COMPOUND=true OKX_OPTIONS_COIN_BUDGET_USDT=10 @@ -125,18 +125,10 @@ OKX_OPTIONS_COIN_MAX_USDT=50 # 现货买入相对权利金缓冲:1.10=多买10%;也可写 0.10。按最大可开张数×权利金×缓冲买币,不全额兑换 OKX_OPTIONS_COIN_SPOT_BUY_BUFFER=1.10 -OKX_OPTIONS_TRADE_BUDGET_USDC=10 OKX_OPTIONS_BUDGET_BUFFER=0.95 -# 全仓复利:开启时隐藏单笔预算且不可用打满;关闭后恢复单笔预算 -OKX_OPTIONS_COMPOUND_FULL_ENABLED=true -OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED=false -OKX_OPTIONS_COMPOUND_FULL_CAP_USDC=300 -# 交易模式三选一(热更):options=单独期权 / perp_options=永期对冲 / options_options=期期对冲 -# 选单独期权时隐藏对冲导航与对冲配置;选对冲时不可单独开期权,仓位按「对冲组数上限」 +# 交易模式固定单独期权(历史 perp_options / options_options 读取时归一为 options) OKX_TRADE_MODE=options -# 永期对冲改为: OKX_TRADE_MODE=perp_options -# 期期对冲改为: OKX_TRADE_MODE=options_options -# 仅单独期权模式:期权同时持仓上限(笔);0=不限制;同合约加仓不占新笔数;热更 +# 期权同时持仓上限(笔);0=不限制;同合约加仓不占新笔数;热更 OKX_OPTIONS_MAX_ACTIVE_POSITIONS=0 OKX_OPTIONS_DEFAULT_UNDERLY=ETH # 期权链仅显示卖一深度≥1张的合约(估算卖一/无深度不显示);false 则显示全部 @@ -148,46 +140,15 @@ OKX_OPTIONS_PROFIT_ALERT_RATIO=1.0 OKX_OPTIONS_POLL_SECONDS=15 OKX_OPTIONS_TD_MODE=isolated OKX_OPTIONS_ALLOW_MARKET_CLOSE=false -# 对冲买期权等成交超时(秒);超时撤未成交部分,未完全成交则开仓失败 +# 开仓成交超时(秒);超时撤未成交部分,未完全成交则开仓失败 OKX_OPTIONS_OPEN_FILL_TIMEOUT_SEC=12 # 目标平仓门控(目标位触发后按买一平仓前需满足) OKX_OPTIONS_CLOSE_GATE_MODE=premium # premium:可回收≥权利金×倍数;net_pnl:净盈亏(买一可回收−权利金)折USDT≥下限 -OKX_OPTIONS_CLOSE_RECYCLE_MULT=2 OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN=1.05 OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT=0 OKX_OPTIONS_CLOSE_HOLD_SECONDS=120 -# ============================================================================= -# 对冲计划(仅 OKX;由 OKX_TRADE_MODE 控制是否启用;详见 docs/对冲计划开发方案.md) -# ============================================================================= -# 以下三项已由 OKX_TRADE_MODE 取代,保留兼容旧部署(未配置 TRADE_MODE 时仍可读) -HEDGE_PLAN_ENABLED=false -HEDGE_PLAN_SHOW_PERP_OPTIONS=false -HEDGE_PLAN_SHOW_OPTIONS_OPTIONS=false -HEDGE_PLAN_LIVE_ORDER=false -# 永期子模式:true=以期权为主;false=保险模式(页面标题前标识,不可页内切换) -HEDGE_PLAN_OPTION_PRIMARY=true -HEDGE_PLAN_OPEN_ORDER=options_first -HEDGE_PLAN_ON_PERP_SL_CLOSE_OPTIONS=true -HEDGE_PLAN_ON_PERP_TP_CLOSE_OPTIONS=false -HEDGE_PLAN_OO_CLOSE_WINNER_ONLY=true -# 方案C:期期页面显示「平仓模式」(到期平/全平);关则固定到期平.默认开启,页面默认选全平 -HEDGE_PLAN_OO_CLOSE_MODE_ENABLED=true -# 期期「做多/做空」拆分口径:budget=按权利金预算(默认);sheets=先算同张数总张数(2n)再按比例拆 -HEDGE_PLAN_OO_BIAS_SPLIT_BY=budget -# 期期「做多/做空」主腿占比(0~1,默认 0.7=7:3);做多主腿=Call,做空主腿=Put -HEDGE_PLAN_OO_BIAS_RATIO=0.7 -# 对冲与单独期权互斥(默认 true):有对冲计划不可单独开期权;有单独期权不可启动对冲;false=可同时开 -HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE=true -# 半腿失败改手动补开(默认 true):不自动平已成腿,计划挂 partial,页面补开;开启时下方自动平强制无效 -HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL=true -# 对冲组数上限(默认 1;opening/active/partial 计入);仅永期/期期模式生效;热更 -MAX_ACTIVE_HEDGE_PLANS=1 -HEDGE_PLAN_MONITOR_POLL_SECONDS=15 -# 半腿失败自动平期权;若 MANUAL_COMPLETE_ON_PARTIAL=true 则运行时强制无效(建议一并写成 false) -HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION=false - # ============================================================================= # ============================================================================= # diff --git a/lib/env/env_schema.py b/lib/env/env_schema.py index 2693d96..52b666f 100644 --- a/lib/env/env_schema.py +++ b/lib/env/env_schema.py @@ -88,18 +88,11 @@ HOT_RELOAD_EXACT = frozenset({ "APP_AUTH_DISABLED", "APP_SESSION_DAYS", "WECHAT_WEBHOOK", - "HEDGE_PLAN_ENABLED", - "HEDGE_PLAN_SHOW_PERP_OPTIONS", - "HEDGE_PLAN_SHOW_OPTIONS_OPTIONS", "OKX_SHOW_PERP_FUNDS", "OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED", "OKX_OPTIONS_CHAIN_MAX_DTE_DAYS", "OKX_OPTIONS_MAX_DTE_DAYS", "OKX_OPTIONS_MAX_ACTIVE_POSITIONS", - "OKX_OPTIONS_COMPOUND_FULL_ENABLED", - "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED", - "OKX_OPTIONS_COMPOUND_FULL_CAP_USDC", - "OKX_OPTIONS_TRADE_BUDGET_USDC", "OKX_OPTIONS_BUDGET_BUFFER", "OKX_OPTIONS_COIN_COMPOUND", "OKX_OPTIONS_COIN_BUDGET_USDT", @@ -107,27 +100,10 @@ HOT_RELOAD_EXACT = frozenset({ "OKX_OPTIONS_COIN_MAX_USDT", "OKX_OPTIONS_COIN_SPOT_BUY_BUFFER", "OKX_OPTIONS_CLOSE_GATE_MODE", - "OKX_OPTIONS_CLOSE_RECYCLE_MULT", "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN", "OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT", "OKX_OPTIONS_CLOSE_HOLD_SECONDS", "OKX_TRADE_MODE", - "MAX_ACTIVE_HEDGE_PLANS", - "HEDGE_PLAN_LIVE_ORDER", - "HEDGE_PLAN_OPTION_PRIMARY", - "HEDGE_PLAN_OPEN_ORDER", - "HEDGE_PLAN_ON_PERP_SL_CLOSE_OPTIONS", - "HEDGE_PLAN_ON_PERP_TP_CLOSE_OPTIONS", - "HEDGE_PLAN_OO_CLOSE_WINNER_ONLY", - "HEDGE_PLAN_OO_CLOSE_MODE_ENABLED", - "HEDGE_PLAN_OO_BIAS_SPLIT_BY", - "HEDGE_PLAN_OO_BIAS_RATIO", - "HEDGE_PLAN_BUDGET_BUFFER", - "HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE", - "HEDGE_PLAN_MANUAL_COMPLETE_ON_PARTIAL", - "MAX_ACTIVE_HEDGE_PLANS", - "HEDGE_PLAN_MONITOR_POLL_SECONDS", - "HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION", }) SENSITIVE_EXACT = frozenset({ @@ -164,17 +140,9 @@ SELECT_OPTIONS: dict[str, tuple[tuple[str, str], ...]] = { ("spot", "spot 现货"), ), "TRANSFER_CCY": (("USDT", "USDT"),), - "HEDGE_PLAN_OO_BIAS_SPLIT_BY": ( - ("budget", "预算金额"), - ("sheets", "张数"), - ), "OKX_TRADE_MODE": ( ("options", "单独期权"), ), - "OKX_OPTIONS_MARGIN_MODE": ( - ("coin", "币本位(USDT买币桥)"), - ("usdc", "USDC(USDⓈ权利金)"), - ), "OKX_OPTIONS_CLOSE_GATE_MODE": ( ("premium", "权利金倍数"), ("net_pnl", "净盈亏(USDT)"), @@ -243,8 +211,6 @@ def _field_type(key: str, value: str) -> str: return "bool" if key.endswith("_ENABLED") or key.startswith("RISK_MOOD_") or key in ( "OKX_SHOW_PERP_FUNDS", - "HEDGE_PLAN_SHOW_PERP_OPTIONS", - "HEDGE_PLAN_SHOW_OPTIONS_OPTIONS", ): return "bool" try: diff --git a/lib/env/env_ui_manifest.py b/lib/env/env_ui_manifest.py index 58e6696..e2c1b24 100644 --- a/lib/env/env_ui_manifest.py +++ b/lib/env/env_ui_manifest.py @@ -27,8 +27,8 @@ _EXCHANGE_LIVE_FIELDS: dict[str, list[tuple[str, str, str]]] = { ("OKX_ACCOUNT_LABEL", "账户备注", "企业微信推送中显示"), ( "OKX_SHOW_PERP_FUNDS", - "显示永续资金", - "默认关闭;开启后顶栏显示 USDT 资金/交易账户。币本位期权仍会显示交易账户以便买币", + "显示USDT资金/交易账户", + "默认关闭;开启后顶栏显示 USDT 资金与交易账户。币本位期权买币仍会显示交易账户可用额", ), ], "binance": [ @@ -64,59 +64,34 @@ _OPTIONS_SECTION: dict[str, Any] = { "title": "期权账户", "exchanges": frozenset({"okx"}), "fields": [ - ("OKX_OPTIONS_ENABLED", "启用期权模块", "与永续共用上方 OKX_API_*;不再单独配置期权密钥"), + ("OKX_OPTIONS_ENABLED", "启用期权模块", "与上方 OKX_API_* 同源;不再单独配置期权密钥"), ("OKX_OPTIONS_ACCOUNT_LABEL", "期权账户备注", ""), - ( - "OKX_OPTIONS_MARGIN_MODE", - "单笔期权本位", - "usdc=USDⓈ权利金;coin=币本位+USDT买币桥(默认)。有持仓/半成品桥时勿切换;改后需重启", - ), - ( - "OKX_OPTIONS_TRADE_BUDGET_USDC", - "单笔预算(USDC)", - "仅 USDC 模式且全仓复利关闭时显示/生效;用于「按可用余额打满」及张数/币数上限", - ), - ("OKX_OPTIONS_BUDGET_BUFFER", "预算缓冲比例", "如 0.95;USDC 打满/全仓复利与币本位复利共用"), + ("OKX_OPTIONS_BUDGET_BUFFER", "预算缓冲比例", "如 0.95;币本位复利/固定预算共用"), ( "OKX_OPTIONS_COIN_COMPOUND", - "币本位按交易户USDT复利", + "按交易户USDT复利", "默认 true;预算=交易账户USDT×缓冲;关闭则用下方固定 USDT 预算×缓冲", ), ( "OKX_OPTIONS_COIN_BUDGET_USDT", - "币本位固定预算(USDT)", - "仅币本位且复利关闭时生效", + "固定预算(USDT)", + "仅复利关闭时生效", ), ( "OKX_OPTIONS_COIN_MAX_USDT_ENABLED", - "币本位单笔上限开关", + "单笔上限开关", "默认 false=靠人工转走控规模;true 时预算不超过下方 N U", ), ( "OKX_OPTIONS_COIN_MAX_USDT", - "币本位单笔上限(USDT)", + "单笔上限(USDT)", "仅上限开关开启时生效", ), ( "OKX_OPTIONS_COIN_SPOT_BUY_BUFFER", - "币本位现货买入缓冲", + "现货买入缓冲", "相对权利金倍数,默认 1.10(=多买10%);也可写 0.10 表示+10%。按最大可开张数×卖一权利金×本缓冲买币,不全额兑换", ), - ( - "OKX_OPTIONS_COMPOUND_FULL_ENABLED", - "全仓复利开关", - "默认 true;仅 USDC 模式。开启时隐藏单笔预算且不可用打满预算,下单以全仓复利为主;关闭则恢复单笔预算并隐藏全仓复利", - ), - ( - "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED", - "全仓复利上限开关", - "仅全仓复利开启时有意义;默认 false=不设上限用期权户全部可用;true 时按下方上限封顶", - ), - ( - "OKX_OPTIONS_COMPOUND_FULL_CAP_USDC", - "全仓复利上限(USDC)", - "仅「全仓复利」且「上限开关」都开启时生效;例如 300", - ), ( "OKX_OPTIONS_MAX_ACTIVE_POSITIONS", "期权持仓上限(笔)", @@ -131,7 +106,7 @@ _OPTIONS_SECTION: dict[str, Any] = { ( "OKX_OPTIONS_MAX_DTE_DAYS", "开仓最大剩余天数", - "默认 2;单独开期权时拒绝更远到期(与链展示天数独立)", + "默认 2;开仓时拒绝更远到期(与链展示天数独立)", ), ( "OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED", @@ -141,17 +116,12 @@ _OPTIONS_SECTION: dict[str, Any] = { ( "OKX_OPTIONS_CLOSE_GATE_MODE", "目标平仓门控模式", - "premium=可回收≥权利金×倍数(币本位默认×1.05);net_pnl=净盈亏折USDT≥阈值", - ), - ( - "OKX_OPTIONS_CLOSE_RECYCLE_MULT", - "门控权利金倍数(USDC)", - "仅 premium 模式;USDC 权利金仓默认 2", + "premium=可回收≥权利金×倍数(默认×1.05);net_pnl=净盈亏折USDT≥阈值", ), ( "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN", - "门控权利金倍数(币本位)", - "仅 premium 模式;ETH/BTC 权利金仓默认 1.05", + "门控权利金倍数", + "仅 premium 模式;默认 1.05", ), ( "OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT", @@ -182,9 +152,7 @@ _RUNTIME_ENV_DEFAULTS: dict[str, str] = { "OKX_OPTIONS_CHAIN_MAX_DTE_DAYS": "14", "OKX_OPTIONS_MAX_DTE_DAYS": "2", "OKX_OPTIONS_MAX_ACTIVE_POSITIONS": "0", - "OKX_OPTIONS_MARGIN_MODE": "coin", "OKX_OPTIONS_CLOSE_GATE_MODE": "premium", - "OKX_OPTIONS_CLOSE_RECYCLE_MULT": "2", "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN": "1.05", "OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT": "0", "OKX_OPTIONS_CLOSE_HOLD_SECONDS": "120", @@ -194,13 +162,14 @@ _RUNTIME_ENV_DEFAULTS: dict[str, str] = { def _effective_env_value(key: str, file_values: dict[str, str], schema_default: str = "") -> str: if key == "OKX_TRADE_MODE": - # 展示值必须与运行时 get_okx_trade_mode() 一致(始终单独期权) try: from lib.options.okx_trade_mode_lib import get_okx_trade_mode return get_okx_trade_mode() except Exception: return "options" + if key == "OKX_OPTIONS_MARGIN_MODE": + return "coin" if key in file_values: file_val = str(file_values.get(key) or "").strip() if file_val: @@ -313,24 +282,7 @@ def build_env_ui_payload( return groups -# 币本位专属 / USDC 专属(配置页互斥隐藏) -_COIN_ONLY_ENV_KEYS = frozenset({ - "OKX_OPTIONS_COIN_COMPOUND", - "OKX_OPTIONS_COIN_BUDGET_USDT", - "OKX_OPTIONS_COIN_MAX_USDT_ENABLED", - "OKX_OPTIONS_COIN_MAX_USDT", - "OKX_OPTIONS_COIN_SPOT_BUY_BUFFER", - "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN", -}) -_USDC_ONLY_ENV_KEYS = frozenset({ - "OKX_OPTIONS_TRADE_BUDGET_USDC", - "OKX_OPTIONS_COMPOUND_FULL_ENABLED", - "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED", - "OKX_OPTIONS_COMPOUND_FULL_CAP_USDC", - "OKX_OPTIONS_CLOSE_RECYCLE_MULT", -}) - - +# 币本位专用:按复利/上限/门控模式标记 hidden def _field_current(fields: list[dict[str, Any]], key: str, default: str = "") -> str: for f in fields: if f.get("key") == key: @@ -339,37 +291,19 @@ def _field_current(fields: list[dict[str, Any]], key: str, default: str = "") -> def _mark_options_section_hidden(fields: list[dict[str, Any]]) -> list[dict[str, Any]]: - """按本位/门控模式/全仓复利标记 hidden(供 SSR/前端;切换开关仍可再显示).""" - margin = (_field_current(fields, "OKX_OPTIONS_MARGIN_MODE", "coin") or "coin").lower() - is_coin = margin != "usdc" + """按门控模式/复利/单笔上限标记 hidden.""" gate_mode = (_field_current(fields, "OKX_OPTIONS_CLOSE_GATE_MODE", "premium") or "premium").lower() - compound_on = _env_truthy(_field_current(fields, "OKX_OPTIONS_COMPOUND_FULL_ENABLED", "true")) coin_compound_on = _env_truthy(_field_current(fields, "OKX_OPTIONS_COIN_COMPOUND", "true")) coin_max_on = _env_truthy(_field_current(fields, "OKX_OPTIONS_COIN_MAX_USDT_ENABLED", "false")) - compound_cap_on = _env_truthy( - _field_current(fields, "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED", "false") - ) out: list[dict[str, Any]] = [] for f in fields: key = str(f.get("key") or "") hide = False - if is_coin and key in _USDC_ONLY_ENV_KEYS: - hide = True - elif (not is_coin) and key in _COIN_ONLY_ENV_KEYS: - hide = True - elif key == "OKX_OPTIONS_CLOSE_RECYCLE_MULT" and gate_mode != "premium": - hide = True - elif key == "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN" and gate_mode != "premium": + if key == "OKX_OPTIONS_CLOSE_RECYCLE_MULT_COIN" and gate_mode != "premium": hide = True elif key == "OKX_OPTIONS_CLOSE_NET_PNL_MIN_USDT" and gate_mode != "net_pnl": hide = True - elif key == "OKX_OPTIONS_TRADE_BUDGET_USDC" and compound_on: - hide = True - elif key == "OKX_OPTIONS_COMPOUND_FULL_CAP_ENABLED" and not compound_on: - hide = True - elif key == "OKX_OPTIONS_COMPOUND_FULL_CAP_USDC" and not (compound_on and compound_cap_on): - hide = True elif key == "OKX_OPTIONS_COIN_BUDGET_USDT" and coin_compound_on: hide = True elif key == "OKX_OPTIONS_COIN_MAX_USDT" and not coin_max_on: diff --git a/lib/instance/instance_settings_register.py b/lib/instance/instance_settings_register.py index 3bf6f07..9a9299a 100644 --- a/lib/instance/instance_settings_register.py +++ b/lib/instance/instance_settings_register.py @@ -118,23 +118,8 @@ def register_instance_settings_routes( if not clean: return jsonify({"ok": True, "changed_keys": [], "restart_required": False}) if "OKX_OPTIONS_MARGIN_MODE" in clean: - try: - from lib.options.options_margin_mode_lib import normalize_options_margin_mode - from lib.options.options_spot_bridge_lib import mode_switch_block_msg - - lines = read_env_lines(env_path) - old_mode = normalize_options_margin_mode(env_get(lines, "OKX_OPTIONS_MARGIN_MODE") or "coin") - new_mode = normalize_options_margin_mode(clean.get("OKX_OPTIONS_MARGIN_MODE")) - if old_mode != new_mode: - conn_m = get_db() - try: - block = mode_switch_block_msg(conn_m, None) - if block: - return jsonify({"ok": False, "msg": block}), 400 - finally: - conn_m.close() - except Exception as e: - return jsonify({"ok": False, "msg": f"本位切换校验失败: {e}"}), 400 + # 币本位专用机:忽略任何写入,强制 coin + clean["OKX_OPTIONS_MARGIN_MODE"] = "coin" changed = apply_env_updates(env_path, clean) groups = parse_env_example_schema(example_path) reload_info = apply_env_reload(env_path, get_db, changed, groups) diff --git a/lib/options/options_margin_mode_lib.py b/lib/options/options_margin_mode_lib.py index 246bebb..6c6705d 100644 --- a/lib/options/options_margin_mode_lib.py +++ b/lib/options/options_margin_mode_lib.py @@ -24,22 +24,14 @@ def _env_float(name: str, default: float) -> float: def normalize_options_margin_mode(raw: Any = None) -> str: - """返回 usdc | coin;未配置时默认币本位.""" - if raw is None: - raw = os.getenv("OKX_OPTIONS_MARGIN_MODE") - v = str(raw or MODE_COIN).strip().lower() - if v in ("usdc", "usdc_margin", "usd_margin", "u本位", "u"): - return MODE_USDC - if v in ("coin", "coin_margin", "crypto", "crypto_margin", "币本位"): - return MODE_COIN - # 空串或未知值:默认币本位 - if not v: - return MODE_COIN + """币本位专用机:始终 coin;历史 usdc 配置读取时亦归一为 coin.""" + del raw return MODE_COIN def is_coin_margin_mode(raw: Any = None) -> bool: - return normalize_options_margin_mode(raw) == MODE_COIN + del raw + return True def inst_family_for_underlying(underlying: str, *, margin_mode: str | None = None) -> str: diff --git a/tests/test_remove_hedge_smoke.py b/tests/test_remove_hedge_smoke.py index ee12937..78edd42 100644 --- a/tests/test_remove_hedge_smoke.py +++ b/tests/test_remove_hedge_smoke.py @@ -72,16 +72,30 @@ class RemoveHedgeSmokeTests(unittest.TestCase): from lib.env.env_schema import select_options_for titles = [s["title"] for s in ui_sections_for_exchange("okx")] - self.assertNotIn("期权/对冲模式", titles) - self.assertTrue(any("对冲" not in t for t in titles)) for t in titles: self.assertNotIn("对冲", t) labels = [f[1] for s in ui_sections_for_exchange("okx") for f in s["fields"]] for lab in labels: self.assertNotIn("对冲", lab) + keys = [f[0] for s in ui_sections_for_exchange("okx") for f in s["fields"]] + self.assertNotIn("OKX_OPTIONS_MARGIN_MODE", keys) + self.assertNotIn("OKX_OPTIONS_TRADE_BUDGET_USDC", keys) + self.assertNotIn("OKX_OPTIONS_COMPOUND_FULL_ENABLED", keys) + self.assertNotIn("OKX_OPTIONS_CLOSE_RECYCLE_MULT", keys) + self.assertIn("OKX_OPTIONS_COIN_COMPOUND", keys) mode_opts = [o["value"] for o in select_options_for("OKX_TRADE_MODE")] self.assertEqual(mode_opts, ["options"]) + def test_margin_mode_locked_coin(self): + from lib.options.options_margin_mode_lib import ( + is_coin_margin_mode, + normalize_options_margin_mode, + ) + + self.assertEqual(normalize_options_margin_mode("usdc"), "coin") + self.assertEqual(normalize_options_margin_mode("coin"), "coin") + self.assertTrue(is_coin_margin_mode("usdc")) + if __name__ == "__main__": unittest.main()