diff --git a/docs/strategy/README.md b/docs/strategy/README.md index 236c059..9ec66a2 100644 --- a/docs/strategy/README.md +++ b/docs/strategy/README.md @@ -12,8 +12,7 @@ - **不写盈亏比(趋势户)**:币安/OKX 止盈/止损随行情人工设定,趋势 MD 不量化 RR。 - **日内例外**:Gate 日内 **最低 1:1** 才开仓,持仓目标可动态调整(见 [gate-intraday.md](./gate-intraday.md))。 -- **界面短标签(趋势户 · 现状 v0.2)**:`大分歧A` / `大分歧B` / `小分歧`。 -- **界面规划(趋势户 · v0.4 讨论稿)**:两级 — **反转**(启动 A/B)| **顺势**(大分歧 A/B)| **波段**(小分歧)。做多反转细则见 [binance-alt-trend-long.md §3](./binance-alt-trend-long.md);OKX 做空见 [okx-trend-both.md §3.2](./okx-trend-both.md)。 +- **界面(趋势户 · v0.4)**:两级 — **反转**(启动 A/B)| **顺势**(大分歧 A/B)| **波段**(小分歧);`lib/trade/entry_model_lib.py` 三所共用。 - **界面短标签(日内户)**:`假破` / `结构突破`。 - **多空共用三字**:方向由「做多/做空」表达,不复用为「大分歧A多」等。 - **自动联动**:大分歧 A/B → 趋势单;**小分歧 → 波段单**;平仓写入交易记录 `entry_reason`;复盘「填入」自动带入。 diff --git a/docs/strategy/binance-alt-trend-long.md b/docs/strategy/binance-alt-trend-long.md index 52168b2..bd3072d 100644 --- a/docs/strategy/binance-alt-trend-long.md +++ b/docs/strategy/binance-alt-trend-long.md @@ -1,6 +1,6 @@ # 币安山寨·多头趋势账户 -> **状态**:v0.4(讨论稿:反转·启动 A/B 策略正文;**UI 仍为 v0.2 三档**,两级下拉待实现) +> **状态**:v0.4(反转·启动 A/B 两级 UI 已实现;策略正文 + `entry_model_lib`) --- @@ -16,33 +16,19 @@ --- -## 2. 开仓类型(规划与现状) +## 2. 开仓类型(两级 UI · 三所共用) -### 2.1 规划:两级选择(讨论定稿,待实现) +### 2.1 趋势户:反转 / 顺势 / 波段 -| 第一级 | 第二级 | 性质 | 计划 code | -|--------|--------|------|-----------| -| **反转** | 启动 A / 启动 B | 跌后筑底 → 赌新主升 | `launch_a` / `launch_b` | -| **顺势** | 大分歧 A / 大分歧 B | 主升已确立 → 回踩/中继 | `big_div_a` / `big_div_b` | -| **波段** | 小分歧 | 主升途中短打 | `small_div` | +| 第一级 | 第二级 | code | 联动 | +|--------|--------|------|------| +| **反转** | 启动 A / 启动 B | `launch_a` / `launch_b` | 趋势单 | +| **顺势** | 大分歧 A / 大分歧 B | `big_div_a` / `big_div_b` | 趋势单 | +| **波段** | 小分歧 | `small_div` | 波段单 | -- 第一级表达 **交易性质**;第二级表达 **突破前 / 实体突破**(小分歧无 A/B)。 -- **启动 A** 含两条实操路径(界面仍一个选项,复盘可备注 A1/A2): - - **A1**:第二次摸高前的小收敛企稳; - - **A2**:启动 B 实体突破失败回箱后,箱子上半区 + 5m 不创新低 + 5m N 字试仓(**不单列类型**)。 -- **小分歧** 前提:主升**已确立**;反转链进行中**不做**小分歧。 +实现:`lib/trade/entry_model_lib.py` + `order_entry_model_fields.html` + `order_entry_model.js`(币安 / OKX / Gate 趋势户共用)。 -### 2.2 现状:下单监控 UI(v0.2 已实现) - -| 界面标签 | 存储 code | 联动 | -|----------|-----------|------| -| 大分歧A | `big_div_a` | 趋势单 | -| 大分歧B | `big_div_b` | 趋势单 | -| 小分歧 | `small_div` | 波段单 | - -实现反转·启动前,顺势单仍选大分歧 A/B;反转单复盘可先在「其他」或备注中写 **启动 A/B**,待 UI 上线后写入 `entry_model`。 - -### 2.3 杠杆(与开仓类型无关) +### 2.2 杠杆(与开仓类型无关) | 币种 | 默认杠杆 | |------|----------| @@ -193,8 +179,7 @@ MACD 背离(严格筛选)→ 标「参考高点」 | 操作 | 字段 | |------|------| -| 下单(现状) | `order_monitors.entry_model`:`big_div_a` / `big_div_b` / `small_div` | -| 下单(规划) | 增加 `launch_a` / `launch_b`;两级 UI | +| 下单 | `order_monitors.entry_model`:`launch_a` / `launch_b` / `big_div_a` / `big_div_b` / `small_div` | | 平仓 | `trade_records.entry_reason` = 界面标签 | | 复盘 | 与开仓类型一致 + 策略项 +「其他」 | @@ -204,6 +189,6 @@ MACD 背离(严格筛选)→ 标「参考高点」 | 版本 | 日期 | 说明 | |------|------|------| -| v0.4 | 2026-07-06 | 讨论稿:反转·启动 A/B(含 A1 收敛、A2 突破失败后 5m N);两级 UI 规划 | +| v0.4 | 2026-07-06 | 反转·启动 A/B 两级 UI 上线(共用 entry_model_lib) | | v0.2 | 2026-07-06 | 定稿 UI 短标签(大分歧/小分歧);实现代码联动 | | v0.1 | 2026-07-06 | 讨论稿 | diff --git a/docs/strategy/checklists/binance.json b/docs/strategy/checklists/binance.json index 79770f1..f3c6683 100644 --- a/docs/strategy/checklists/binance.json +++ b/docs/strategy/checklists/binance.json @@ -8,7 +8,7 @@ "items": [ "本账户仅做多,不做空", "计仓模式为以损定仓(risk),关键位自动单已关闭", - "已明确第一级:反转 / 顺势 / 波段(UI 待上线时复盘可先备注)" + "已明确第一级:反转 / 顺势 / 波段(两级下拉已上线)" ] }, { @@ -63,6 +63,6 @@ } ], "footnotes": [ - "v0.4:反转·启动为讨论定稿;下单 UI 仍为 v0.2 三档时,反转单请在复盘备注启动 A/B。" + "v0.4:两级 UI 已实现;启动 A 含 A1 收敛与 A2(B 失败后 5m N 字)。" ] } diff --git a/docs/strategy/checklists/okx.json b/docs/strategy/checklists/okx.json index b6d58ba..9058001 100644 --- a/docs/strategy/checklists/okx.json +++ b/docs/strategy/checklists/okx.json @@ -10,7 +10,7 @@ "趋势户 profile(非 Gate 日内 BTC/ETH 白名单)", "计仓模式为以损定仓(risk),关键位自动单已关闭", "同一币种无未计划的对冲叠仓", - "已明确第一级:反转 / 顺势 / 波段(UI 待上线时复盘可先备注)" + "已明确第一级:反转 / 顺势 / 波段(两级下拉已上线)" ] }, { @@ -67,6 +67,6 @@ } ], "footnotes": [ - "v0.4:反转·启动为讨论定稿;做多细则见 binance-alt-trend-long.md §3。UI 仍为 v0.2 三档时,反转单请在复盘备注启动 A/B。" + "v0.4:两级 UI 反转/顺势/波段;做多细则见 binance-alt-trend-long.md §3。" ] } diff --git a/docs/strategy/okx-trend-both.md b/docs/strategy/okx-trend-both.md index a5476eb..c1579c1 100644 --- a/docs/strategy/okx-trend-both.md +++ b/docs/strategy/okx-trend-both.md @@ -22,26 +22,19 @@ ## 2. 开仓类型(规划与现状) -### 2.1 规划:两级选择(讨论定稿,待实现) +### 2.1 规划:两级选择(与币安共用实现) | 第一级 | 第二级 | 做多 | 做空 | |--------|--------|------|------| -| **反转** | 启动 A / 启动 B | 跌后筑底 → 新主升 | 涨后筑顶 → 新主跌 | -| **顺势** | 大分歧 A / B | 主升已确立 | 主跌已确立 | -| **波段** | 小分歧 | 主升途中短打 | 主跌途中短打 | +| **反转** | 启动 A / 启动 B | `launch_a` / `launch_b` | 同 code,方向在表单 | +| **顺势** | 大分歧 A / B | `big_div_a` / `big_div_b` | 同左 | +| **波段** | 小分歧 | `small_div` | 同左 | -计划 code:`launch_a` / `launch_b` / `big_div_a` / `big_div_b` / `small_div`(与币安一致)。 +`lib/trade/entry_model_lib.py` + 共用模板/JS,三所趋势户一致。 -- **启动 A**:含 **A1**(第二次摸参考极值前小收敛)与 **A2**(启动 B 实体突破失败回箱后的 5m N 字试仓);**5m 试仓不单列**,统一记启动 A。 -- **小分歧**:仅在大级别趋势**已确立**后;反转链进行中**不做**小分歧。 +### 2.2 现状:下单监控 UI -### 2.2 现状:下单监控 UI(v0.2 已实现) - -| 界面标签 | code | 联动 | -|----------|------|------| -| 大分歧A / B、小分歧 | `big_div_a` 等 | 趋势单 / 波段单 | - -**方向**由表单「做多/做空」决定;**单型**由下拉决定。反转单在 UI 上线前,复盘可备注 **启动 A/B**。 +两级下拉:**性质** → **类型**;提交 `entry_model` code。 ### 2.3 杠杆 diff --git a/lib/common/static/instance_page.css b/lib/common/static/instance_page.css index 28a7859..384540d 100644 --- a/lib/common/static/instance_page.css +++ b/lib/common/static/instance_page.css @@ -1,4 +1,7 @@ .order-trade-style-hint{font-size:.78rem;color:#8fc8ff;margin-left:4px;white-space:nowrap} +.order-entry-model-row{display:flex;flex-wrap:wrap;align-items:center;gap:6px} +.order-entry-model-row select.order-entry-category{min-width:4.8em;max-width:6.5em} +.order-entry-model-row select.order-entry-model-sub{min-width:7em;max-width:10rem} .order-leverage-hint{font-size:.78rem;color:#cfd3ef;white-space:nowrap;align-self:center} body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;background:#0b0d14;color:#eaeaea;padding:14px 20px} .container{width:100%;max-width:min(1440px,94vw);margin:0 auto;padding:0 clamp(8px,1.5vw,20px)} diff --git a/lib/common/static/order_entry_model.js b/lib/common/static/order_entry_model.js index 4e66ec1..6bfe2d3 100644 --- a/lib/common/static/order_entry_model.js +++ b/lib/common/static/order_entry_model.js @@ -1,38 +1,125 @@ (function (global) { - function tradeStyleForSelect(sel) { - if (!sel || !sel.value) return "trend"; - var opt = sel.options[sel.selectedIndex]; - if (opt && opt.getAttribute) { - var ds = opt.getAttribute("data-trade-style"); - if (ds === "swing" || ds === "trend") return ds; - } + function categoriesData() { + return global.ORDER_ENTRY_MODEL_CATEGORIES || []; + } + + function codeToCategoryMap() { + return global.ORDER_ENTRY_MODEL_CODE_TO_CATEGORY || {}; + } + + function tradeStyleForCode(code) { var map = global.ORDER_ENTRY_MODEL_TRADE_STYLE || {}; - return map[sel.value] || "trend"; + return map[code] || "trend"; + } + + function findOption(catKey, code) { + var cats = categoriesData(); + for (var i = 0; i < cats.length; i++) { + if (cats[i].key !== catKey) continue; + var opts = cats[i].options || []; + for (var j = 0; j < opts.length; j++) { + if (opts[j].code === code) return opts[j]; + } + } + return null; + } + + function rebuildEntryModelSubSelect(preserveCode) { + var catSel = document.getElementById("order-entry-category"); + var modelSel = document.getElementById("order-entry-model"); + if (!catSel || !modelSel) return; + + var catKey = catSel.value; + var cats = categoriesData(); + var cat = null; + for (var i = 0; i < cats.length; i++) { + if (cats[i].key === catKey) { + cat = cats[i]; + break; + } + } + + modelSel.innerHTML = ""; + var placeholder = document.createElement("option"); + placeholder.value = ""; + placeholder.textContent = "类型"; + modelSel.appendChild(placeholder); + + if (!cat || !cat.options || !cat.options.length) { + modelSel.disabled = true; + modelSel.value = ""; + syncOrderEntryModelTradeStyle(); + return; + } + + modelSel.disabled = false; + var pick = preserveCode || ""; + for (var k = 0; k < cat.options.length; k++) { + var o = cat.options[k]; + var opt = document.createElement("option"); + opt.value = o.code; + opt.textContent = o.label; + if (o.trade_style) opt.setAttribute("data-trade-style", o.trade_style); + if (o.help) opt.title = o.help; + modelSel.appendChild(opt); + } + + if (pick && findOption(catKey, pick)) { + modelSel.value = pick; + } else if (cat.options.length === 1) { + modelSel.value = cat.options[0].code; + } else { + modelSel.value = ""; + } + syncOrderEntryModelTradeStyle(); } function syncOrderEntryModelTradeStyle() { - var sel = document.getElementById("order-entry-model"); + var modelSel = document.getElementById("order-entry-model"); var hidden = document.getElementById("order-trade-style-hidden"); var hint = document.getElementById("order-trade-style-hint"); - if (!sel || !hidden) return; + if (!modelSel || !hidden) return; var labels = { trend: "趋势单", swing: "波段单" }; - var ts = tradeStyleForSelect(sel); + var code = modelSel.value || ""; + var ts = tradeStyleForCode(code); hidden.value = ts; if (hint) hint.textContent = labels[ts] || ts; } function initOrderEntryModelSelect(root) { var scope = root && root.querySelector ? root : document; - var sel = + var catSel = + scope === document + ? document.getElementById("order-entry-category") + : scope.querySelector("#order-entry-category"); + var modelSel = scope === document ? document.getElementById("order-entry-model") : scope.querySelector("#order-entry-model"); - if (!sel) return; - if (sel.dataset.entryModelWired !== "1") { - sel.dataset.entryModelWired = "1"; - sel.addEventListener("change", syncOrderEntryModelTradeStyle); + if (!catSel || !modelSel) return; + + if (catSel.dataset.entryModelWired !== "1") { + catSel.dataset.entryModelWired = "1"; + catSel.addEventListener("change", function () { + rebuildEntryModelSubSelect(""); + }); } - syncOrderEntryModelTradeStyle(); + if (modelSel.dataset.entryModelWired !== "1") { + modelSel.dataset.entryModelWired = "1"; + modelSel.addEventListener("change", syncOrderEntryModelTradeStyle); + } + + var presetCode = modelSel.getAttribute("data-preset-code") || modelSel.value || ""; + if (presetCode) { + var catMap = codeToCategoryMap(); + var catKey = catMap[presetCode]; + if (catKey) { + catSel.value = catKey; + rebuildEntryModelSubSelect(presetCode); + return; + } + } + rebuildEntryModelSubSelect(""); } global.paintOrderLeverageHint = function (leverage) { @@ -51,12 +138,9 @@ global.initOrderEntryModelSelect = initOrderEntryModelSelect; global.syncOrderEntryModelTradeStyle = syncOrderEntryModelTradeStyle; + global.rebuildEntryModelSubSelect = rebuildEntryModelSubSelect; - if (document.readyState === "loading") { - document.addEventListener("DOMContentLoaded", function () { - initOrderEntryModelSelect(); - }); - } else { + document.addEventListener("DOMContentLoaded", function () { initOrderEntryModelSelect(); - } + }); })(typeof window !== "undefined" ? window : globalThis); diff --git a/lib/instance/templates/embed_boot_scripts.html b/lib/instance/templates/embed_boot_scripts.html index 94e9576..bf6e31f 100644 --- a/lib/instance/templates/embed_boot_scripts.html +++ b/lib/instance/templates/embed_boot_scripts.html @@ -1,52 +1,5 @@ - + + diff --git a/lib/instance/templates/index.html b/lib/instance/templates/index.html index d98dc4a..265f997 100644 --- a/lib/instance/templates/index.html +++ b/lib/instance/templates/index.html @@ -554,13 +554,17 @@ - + +