From 16bba2eb1a053a7ff8aa82d6f8d51c6aeeeeaab3 Mon Sep 17 00:00:00 2001 From: dekun Date: Wed, 14 Oct 2026 18:43:02 +0800 Subject: [PATCH] Enable hedge review with dual-timeframe K-line charts. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always install the review module in hedge-only mode, expose 对冲复盘 in nav, and allow auto charts for closed hedge plans. Co-authored-by: Cursor --- README.md | 2 +- app.py | 12 +++---- lib/common/static/instance_embed.js | 2 +- lib/common/static/options_review.js | 14 +++++++- lib/instance/instance_display_prefs_lib.py | 2 +- lib/instance/instance_embed_lib.py | 1 + lib/instance/templates/embed_shell.html | 6 ++++ lib/instance/templates/index.html | 3 ++ lib/options/options_review_register.py | 32 +++++++++++++++---- .../templates/options_review_panel.html | 6 ++-- 10 files changed, 60 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 516d6c4..213f5bd 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ OKX **币本位期权** + **U 本位永续对冲** 独立实例。 ## 产品范围 -本仓**仅对冲**。单独期权(含中控)请用专用期权仓库;此处默认不装期权页/复盘/独立盯盘。 +本仓**仅对冲**。单独期权(含中控)请用专用期权仓库;此处默认不装单独期权交易页/独立盯盘,但装载**对冲复盘**(已结束计划 + 标的永续双周期 K 线)。 | 保留 | 说明 | |------|------| diff --git a/app.py b/app.py index 6af91ff..fc60e3d 100644 --- a/app.py +++ b/app.py @@ -9941,7 +9941,7 @@ from lib.sim.register import install_sim_trading install_sim_trading(app, _REPO_ROOT, app_module=sys.modules[__name__]) -# 本仓默认仅对冲:不装单独期权页/复盘/独立盯盘(执行层由 hedge 共用 okx_options_lib). +# 本仓默认仅对冲:不装单独期权交易页/独立盯盘;复盘始终安装(对冲复盘+双周期K线). # 紧急需要单独期权 UI 时设 STANDALONE_OPTIONS_UI=true(不推荐;专用期权仓更完整). from lib.hedge_plan.okx_trade_mode_lib import standalone_options_ui_enabled as _standalone_opt_ui @@ -9949,16 +9949,16 @@ if _standalone_opt_ui(): from lib.options.options_register import install_options_trading install_options_trading(app, _REPO_ROOT, app_module=sys.modules[__name__]) - - from lib.options.options_review_register import install_options_review - - install_options_review(app, _REPO_ROOT, app_module=sys.modules[__name__]) else: print( - "[boot] STANDALONE_OPTIONS_UI=false → skip options/review UI (hedge-only)", + "[boot] STANDALONE_OPTIONS_UI=false → skip standalone options trading UI", flush=True, ) +from lib.options.options_review_register import install_options_review + +install_options_review(app, _REPO_ROOT, app_module=sys.modules[__name__]) + from lib.hedge_plan.hedge_plan_register import install_hedge_plan install_hedge_plan(app, _REPO_ROOT, app_module=sys.modules[__name__]) diff --git a/lib/common/static/instance_embed.js b/lib/common/static/instance_embed.js index be8b93b..705a364 100644 --- a/lib/common/static/instance_embed.js +++ b/lib/common/static/instance_embed.js @@ -11,7 +11,7 @@ strategy: "/strategy", strategy_records: "/strategy/records", options: "/options", - options_review: "/options/review", + options_review: "/hedge-plan/review", hedge_plan: "/hedge-plan", records: "/records", stats: "/stats", diff --git a/lib/common/static/options_review.js b/lib/common/static/options_review.js index c7cf7f3..2abad1e 100644 --- a/lib/common/static/options_review.js +++ b/lib/common/static/options_review.js @@ -1161,7 +1161,19 @@ ($("or-f-note") || {}).value = e.note || ""; setMoodTags(e.mistake_tags); resetChartOptions(); - setChartOptionsVisible(t.source_type === "option_spot"); + // 纯期权与对冲均可生成标的永续双周期 K 线;对冲默认勾选 + var chartOk = + t.source_type === "option_spot" || + t.source_type === "perp_options" || + t.source_type === "options_options"; + setChartOptionsVisible(chartOk); + if ( + chartOk && + (t.source_type === "perp_options" || t.source_type === "options_options") + ) { + var cb = $("or-exchange-chart"); + if (cb) cb.checked = true; + } var summary = $("or-journal-summary"); if (summary) { diff --git a/lib/instance/instance_display_prefs_lib.py b/lib/instance/instance_display_prefs_lib.py index 420d9a6..2dd3ef2 100644 --- a/lib/instance/instance_display_prefs_lib.py +++ b/lib/instance/instance_display_prefs_lib.py @@ -43,7 +43,7 @@ DISPLAY_LABELS: dict[str, str] = { "show_nav_system_guide": "系统说明", "show_nav_env_config": "env配置", "show_nav_options": "期权", - "show_nav_options_review": "期权复盘", + "show_nav_options_review": "对冲复盘", "show_nav_hedge_plan": "永期/期期对冲", "show_settings_transfer": "资金划转", "show_settings_export": "数据导出", diff --git a/lib/instance/instance_embed_lib.py b/lib/instance/instance_embed_lib.py index 3610962..37f1842 100644 --- a/lib/instance/instance_embed_lib.py +++ b/lib/instance/instance_embed_lib.py @@ -40,6 +40,7 @@ PATH_TO_EMBED_TAB: dict[str, str] = { "/strategy/records": "strategy_records", "/options": "options", "/options/review": "options_review", + "/hedge-plan/review": "options_review", "/hedge-plan": "hedge_plan", "/records": "records", "/stats": "stats", diff --git a/lib/instance/templates/embed_shell.html b/lib/instance/templates/embed_shell.html index 41d5688..9b6f1e2 100644 --- a/lib/instance/templates/embed_shell.html +++ b/lib/instance/templates/embed_shell.html @@ -37,6 +37,9 @@ {% if options_nav_visible and display.show_nav_options_review %} 期权复盘 {% endif %} + {% if hedge_plan_nav_visible and display.show_nav_options_review %} + 对冲复盘 + {% endif %} {% if hedge_plan_nav_visible and display.show_nav_hedge_plan %} {% if hedge_plan_show_options_options %}期期对冲{% else %}永期对冲{% endif %} {% endif %} @@ -98,6 +101,9 @@ {% if options_nav_visible and display.show_nav_options_review %} 期权复盘 {% endif %} + {% if hedge_plan_nav_visible and display.show_nav_options_review %} + 对冲复盘 + {% endif %} {% if display.show_nav_risk_policy %} 风控说明 {% endif %} diff --git a/lib/instance/templates/index.html b/lib/instance/templates/index.html index f37a513..05208c6 100644 --- a/lib/instance/templates/index.html +++ b/lib/instance/templates/index.html @@ -160,6 +160,9 @@ {% if options_nav_visible and display.show_nav_options_review %} 期权复盘 {% endif %} + {% if hedge_plan_nav_visible and display.show_nav_options_review %} + 对冲复盘 + {% endif %} {% if hedge_plan_nav_visible and display.show_nav_hedge_plan %} {% if hedge_plan_show_options_options %}期期对冲{% else %}永期对冲{% endif %} {% endif %} diff --git a/lib/options/options_review_register.py b/lib/options/options_review_register.py index 1e6b673..194ef81 100644 --- a/lib/options/options_review_register.py +++ b/lib/options/options_review_register.py @@ -139,8 +139,12 @@ def _maybe_schedule_options_review_chart( trade: dict[str, Any], data: dict[str, Any], ) -> bool: - """纯期权 + 无手动截图 + 勾选自动K线 → 后台生成标的永续双周期拼图(只钉进/出场).""" - if str(trade.get("source_type") or "").strip() != "option_spot": + """无手动截图 + 勾选自动K线 → 后台生成标的永续双周期拼图(只钉进/出场). + + 纯期权与永期/期期对冲均可;对冲按计划开平时间钉在标的永续 K 线上. + """ + src = str(trade.get("source_type") or "").strip() + if src not in ("option_spot", "perp_options", "options_options"): return False images = data.get("images") if isinstance(data.get("images"), list) else [] has_manual = any(str((x or {}).get("file") or "").strip() for x in images) @@ -205,12 +209,17 @@ def _maybe_schedule_options_review_chart( except Exception: now_ms = None - inst = str(trade.get("inst_id") or underlying or f"#{trade.get('id') or ''}").strip() + plan_id = trade.get("hedge_plan_id") + if plan_id: + title_prefix = f"{underlying or 'HEDGE'} plan#{plan_id} review" + else: + inst = str(trade.get("inst_id") or underlying or f"#{trade.get('id') or ''}").strip() + title_prefix = f"{underlying or 'OPT'} {inst} review" upload_folder = options_review_upload_dir(cfg["upload_folder"]) schedule_options_review_exchange_chart( trade_id=int(trade["id"]), exchange_symbol=exchange_symbol, - title_prefix=f"{underlying or 'OPT'} {inst} review", + title_prefix=title_prefix, journal_tfs=journal_tfs, journal_limit=journal_limit, marker_payload={ @@ -231,9 +240,7 @@ def _maybe_schedule_options_review_chart( def register_options_review_routes(app: Flask, cfg: dict[str, Any], repo_root: str) -> None: lr = cfg["login_required"] - @app.route("/options/review") - @lr - def options_review_page(): + def _review_page(): from lib.instance.instance_embed_lib import redirect_to_embed_shell_if_enabled redir = redirect_to_embed_shell_if_enabled("options_review") @@ -241,6 +248,17 @@ def register_options_review_routes(app: Flask, cfg: dict[str, Any], repo_root: s return redir return cfg["render_main_page"]("options_review") + @app.route("/options/review") + @lr + def options_review_page(): + return _review_page() + + @app.route("/hedge-plan/review") + @lr + def hedge_plan_review_page(): + """对冲复盘入口(与 /options/review 同页;本仓主入口).""" + return _review_page() + @app.route("/static/options_review.js") @lr def static_options_review_js(): diff --git a/lib/options/templates/options_review_panel.html b/lib/options/templates/options_review_panel.html index 54aeeaf..5a5e8f4 100644 --- a/lib/options/templates/options_review_panel.html +++ b/lib/options/templates/options_review_panel.html @@ -178,7 +178,7 @@
-

期权复盘

+

{% if okx_trade_mode|default('') in ('perp_options', 'options_options') %}对冲复盘{% else %}期权复盘{% endif %}

@@ -356,7 +356,7 @@ - +
@@ -447,4 +447,4 @@
- +