diff --git a/crypto_monitor_binance/templates/index.html b/crypto_monitor_binance/templates/index.html index f58102d..7f61139 100644 --- a/crypto_monitor_binance/templates/index.html +++ b/crypto_monitor_binance/templates/index.html @@ -321,114 +321,7 @@
{% if page == 'key_monitor' %} -
-
-
-

关键位监控

- {% if focus_key_id %} - 放大查看K线(默认200根) - {% else %} - 输入币种查看K线 - {% endif %} -
-
- - - - - - - - - - -
-
{{ key_gate_rule_text }}
-
- {% for k in key %} -
-
-
- {{ k.symbol }} - {% if k.direction == 'watch' %} - 双向 - {% else %} - {{ '做多' if k.direction == 'long' else '做空' }} - {% endif %} - {{ k.monitor_type }} -
- -
-
- 上沿: {{ k.upper }} - 下沿: {{ k.lower }} - {% if k.fib_entry_price %}挂E: {{ k.fib_entry_price }}{% endif %} - {% if k.monitor_type == '假突破' and k.fib_stop_loss %}SL: {{ k.fib_stop_loss }} / TP: {{ k.fib_take_profit }}{% endif %} - 已提醒: {{ k.notification_count or 0 }}/{{ k.max_notify or 3 }} - {% if k.monitor_type in ['箱体突破','收敛突破'] %} - 方案: {{ '标准突破' if (k.sl_tp_mode or 'standard') == 'standard' else ('箱体1R·止盈1.5H' if k.sl_tp_mode == 'box_1p5' else '趋势单') }} - {% endif %} - 保本: {{ '开' if k.breakeven_enabled else '关' }} -
-
-
现价-
-
距上沿-
-
距下沿-
-
门控-
-
-
-
- {% else %} -
暂无监控中的关键位
- {% endfor %} -
-
-
-

关键位历史

-
失效或已结案的关键位
-
- {% for h in key_history %} -
-
-
- {{ h.symbol }} - {{ '做多' if h.direction == 'long' else '做空' }} -
- -
-
- {{ h.monitor_type }} - {{ h.close_reason }} - {{ (h.closed_at or '-')[:16] }} -
-
- 上: {{ h.upper }} 下: {{ h.lower }} - 提醒: {{ h.notification_count }} -
- {% if h.last_alert_message %}
{{ h.last_alert_message[:180] }}{% if h.last_alert_message|length > 180 %}…{% endif %}
{% endif %} -
- {% else %} -
暂无历史
- {% endfor %} -
-
-
+ {% include 'key_monitor_panel.html' %} {% elif page == 'trade' %}
@@ -2235,6 +2128,7 @@ function refreshPriceSnapshotConditional(){ if(gateEl){ gateEl.innerText = k.gate_summary || "-"; gateEl.style.color = k.gate_ok ? "#4cd97f" : "#ff8f8f"; } const gateMetricEl = document.getElementById(`key-gate-metrics-${k.id}`); if(gateMetricEl) gateMetricEl.innerText = k.gate_metrics || ""; + if(typeof paintKeyMonitorSummary === "function") paintKeyMonitorSummary(k.id, k); }); } if(page === "trade"){ diff --git a/crypto_monitor_gate/templates/index.html b/crypto_monitor_gate/templates/index.html index b378fcf..a964163 100644 --- a/crypto_monitor_gate/templates/index.html +++ b/crypto_monitor_gate/templates/index.html @@ -322,114 +322,7 @@
{% if page == 'key_monitor' %} -
-
-
-

关键位监控

- {% if focus_key_id %} - 放大查看K线(默认200根) - {% else %} - 输入币种查看K线 - {% endif %} -
-
- - - - - - - - - - -
-
{{ key_gate_rule_text }}
-
- {% for k in key %} -
-
-
- {{ k.symbol }} - {% if k.direction == 'watch' %} - 双向 - {% else %} - {{ '做多' if k.direction == 'long' else '做空' }} - {% endif %} - {{ k.monitor_type }} -
- -
-
- 上沿: {{ k.upper }} - 下沿: {{ k.lower }} - {% if k.fib_entry_price %}挂E: {{ k.fib_entry_price }}{% endif %} - {% if k.monitor_type == '假突破' and k.fib_stop_loss %}SL: {{ k.fib_stop_loss }} / TP: {{ k.fib_take_profit }}{% endif %} - 已提醒: {{ k.notification_count or 0 }}/{{ k.max_notify or 3 }} - {% if k.monitor_type in ['箱体突破','收敛突破'] %} - 方案: {{ '标准突破' if (k.sl_tp_mode or 'standard') == 'standard' else ('箱体1R·止盈1.5H' if k.sl_tp_mode == 'box_1p5' else '趋势单') }} - {% endif %} - 保本: {{ '开' if k.breakeven_enabled else '关' }} -
-
-
现价-
-
距上沿-
-
距下沿-
-
门控-
-
-
-
- {% else %} -
暂无监控中的关键位
- {% endfor %} -
-
-
-

关键位历史

-
失效或已结案的关键位
-
- {% for h in key_history %} -
-
-
- {{ h.symbol }} - {{ '做多' if h.direction == 'long' else '做空' }} -
- -
-
- {{ h.monitor_type }} - {{ h.close_reason }} - {{ (h.closed_at or '-')[:16] }} -
-
- 上: {{ h.upper }} 下: {{ h.lower }} - 提醒: {{ h.notification_count }} -
- {% if h.last_alert_message %}
{{ h.last_alert_message[:180] }}{% if h.last_alert_message|length > 180 %}…{% endif %}
{% endif %} -
- {% else %} -
暂无历史
- {% endfor %} -
-
-
+ {% include 'key_monitor_panel.html' %} {% elif page == 'trade' %}
@@ -2219,6 +2112,7 @@ function refreshPriceSnapshotConditional(){ if(gateEl){ gateEl.innerText = k.gate_summary || "-"; gateEl.style.color = k.gate_ok ? "#4cd97f" : "#ff8f8f"; } const gateMetricEl = document.getElementById(`key-gate-metrics-${k.id}`); if(gateMetricEl) gateMetricEl.innerText = k.gate_metrics || ""; + if(typeof paintKeyMonitorSummary === "function") paintKeyMonitorSummary(k.id, k); }); } if(page === "trade"){ diff --git a/crypto_monitor_gate_bot/app.py b/crypto_monitor_gate_bot/app.py index 8f84b58..74e6e48 100644 --- a/crypto_monitor_gate_bot/app.py +++ b/crypto_monitor_gate_bot/app.py @@ -5431,6 +5431,12 @@ def render_main_page(page="trade"): orphan_positions = collect_orphan_exchange_positions(order_list, conn) except Exception as exc: print(f"[render_main_page] orphan positions: {exc}") + key_gate_rule_text = ( + f"【箱体/收敛】{KLINE_TIMEFRAME} 两根闭合K|突破越过关键位 0.03%~0.5%|" + f"确认K收于箱外|量能>前20均量×1.3|日成交前30|" + f"偏离关键位 > {KEY_BREAKOUT_LIMIT_PCT}% 不提醒|" + f"【阻力/支撑】收盘突破任一侧即提醒 {KEY_ALERT_MAX_TIMES} 次(间隔 {KEY_ALERT_INTERVAL_MINUTES} 分),不自动开仓" + ) conn.close() return render_template( "index.html", @@ -5502,6 +5508,7 @@ def render_main_page(page="trade"): journal_chart_default_limit=JOURNAL_CHART_DEFAULT_LIMIT, journal_chart_default_anchor=JOURNAL_CHART_DEFAULT_ANCHOR, exchange_display=EXCHANGE_DISPLAY_NAME, + key_gate_rule_text=key_gate_rule_text, **strategy_extra, ) @@ -5512,6 +5519,12 @@ def index(): return redirect("/trade") +@app.route("/key_monitor") +@login_required +def key_monitor_page(): + return render_main_page("key_monitor") + + @app.route("/trade") @login_required def trade_page(): @@ -6284,7 +6297,7 @@ def add_key(): conn.commit() conn.close() flash(f"添加成功({symbol} 日成交量排名 {rank}/{total})") - return redirect("/") + return redirect("/key_monitor") @app.route("/add_order", methods=["POST"]) @login_required diff --git a/crypto_monitor_gate_bot/templates/index.html b/crypto_monitor_gate_bot/templates/index.html index ac8aaac..e83fad5 100644 --- a/crypto_monitor_gate_bot/templates/index.html +++ b/crypto_monitor_gate_bot/templates/index.html @@ -322,6 +322,7 @@
+ 关键位监控 交易执行 策略交易 策略交易记录 @@ -354,6 +355,8 @@
数据导出(v{{ data_export_version }} CSV,UTF-8;交易记录含开仓类型列及交易所对齐字段): 交易记录 + 关键位(当前) + 关键位历史
交易所
{{ exchange_display }}
@@ -368,7 +371,9 @@ {% include 'gate_transfer_block.html' %}
- {% if page == 'trade' %} + {% if page == 'key_monitor' %} + {% include 'key_monitor_panel.html' %} + {% elif page == 'trade' %}
@@ -1577,6 +1582,62 @@ if(journalForm){ } } +function syncKeyMonitorFormFields(){ + const typeEl = document.querySelector('#key-form [name="type"]'); + const dirEl = document.getElementById("key-direction"); + const modeEl = document.getElementById("key-sl-tp-mode"); + const manualTp = document.getElementById("key-manual-tp"); + const beWrap = document.getElementById("key-breakeven-wrap"); + if(!typeEl) return; + const t = (typeEl.value || "").trim(); + const autoTypes = new Set(["箱体突破","收敛突破"]); + const fibTypes = new Set(["斐波回调0.618","斐波回调0.786"]); + const fbTypes = new Set(["假突破"]); + const rsTypes = new Set(["关键阻力位","关键支撑位"]); + const showAuto = autoTypes.has(t); + const showFb = fbTypes.has(t); + const showBe = showAuto || fibTypes.has(t) || showFb; + const showDir = !rsTypes.has(t); + const upperEl = document.getElementById("key-upper"); + const lowerEl = document.getElementById("key-lower"); + const fbPriceEl = document.getElementById("key-fb-price"); + if(dirEl){ + dirEl.style.display = showDir ? "" : "none"; + dirEl.required = showDir; + if(!showDir) dirEl.value = ""; + } + if(modeEl) modeEl.style.display = showAuto ? "" : "none"; + if(manualTp){ + const trend = showAuto && modeEl && modeEl.value === "trend_manual"; + manualTp.style.display = trend ? "" : "none"; + manualTp.required = !!trend; + } + if(beWrap) beWrap.style.display = showBe ? "inline-flex" : "none"; + if(upperEl){ + upperEl.style.display = showFb ? "none" : ""; + upperEl.required = !showFb; + if(showFb) upperEl.value = ""; + } + if(lowerEl){ + lowerEl.style.display = showFb ? "none" : ""; + lowerEl.required = !showFb; + if(showFb) lowerEl.value = ""; + } + if(fbPriceEl){ + fbPriceEl.style.display = showFb ? "" : "none"; + fbPriceEl.required = showFb; + if(!showFb) fbPriceEl.value = ""; + fbPriceEl.placeholder = (dirEl && dirEl.value === "short") ? "高点(阻力)" : ((dirEl && dirEl.value === "long") ? "低点(支撑)" : "做空填高点/做多填低点"); + } +} +const keyTypeSel = document.querySelector('#key-form [name="type"]'); +const keyModeSel = document.getElementById("key-sl-tp-mode"); +const keyDirSel = document.getElementById("key-direction"); +if(keyTypeSel) keyTypeSel.addEventListener("change", syncKeyMonitorFormFields); +if(keyModeSel) keyModeSel.addEventListener("change", syncKeyMonitorFormFields); +if(keyDirSel) keyDirSel.addEventListener("change", syncKeyMonitorFormFields); +syncKeyMonitorFormFields(); + const keyForm = document.getElementById("key-form"); if(keyForm){ keyForm.addEventListener("submit", (e)=>{ @@ -1874,7 +1935,7 @@ function refreshPriceSnapshotConditional(){ (data.key_prices || []).forEach(k=>{ const pEl = document.getElementById(`key-price-${k.id}`); if(pEl){ - pEl.innerText = Number(k.price).toFixed(6); + pEl.innerText = k.price_display || (Number.isFinite(Number(k.price)) ? Number(k.price).toFixed(6) : "-"); paintPriceTrend(pEl, `k-${k.id}`, Number(k.price)); } const upEl = document.getElementById(`key-up-diff-${k.id}`); @@ -1888,6 +1949,7 @@ function refreshPriceSnapshotConditional(){ } const gateMetricEl = document.getElementById(`key-gate-metrics-${k.id}`); if(gateMetricEl) gateMetricEl.innerText = k.gate_metrics || ""; + if(typeof paintKeyMonitorSummary === "function") paintKeyMonitorSummary(k.id, k); }); } if(page === "trade"){ diff --git a/crypto_monitor_okx/templates/index.html b/crypto_monitor_okx/templates/index.html index f6f81ab..aa64c3e 100644 --- a/crypto_monitor_okx/templates/index.html +++ b/crypto_monitor_okx/templates/index.html @@ -330,114 +330,7 @@
{% if page == 'key_monitor' %} -
-
-
-

关键位监控

- {% if focus_key_id %} - 放大查看K线(默认200根) - {% else %} - 输入币种查看K线 - {% endif %} -
-
- - - - - - - - - - -
-
{{ key_gate_rule_text }}
-
- {% for k in key %} -
-
-
- {{ k.symbol }} - {% if k.direction == 'watch' %} - 双向 - {% else %} - {{ '做多' if k.direction == 'long' else '做空' }} - {% endif %} - {{ k.monitor_type }} -
- -
-
- 上沿: {{ k.upper }} - 下沿: {{ k.lower }} - {% if k.fib_entry_price %}挂E: {{ k.fib_entry_price }}{% endif %} - {% if k.monitor_type == '假突破' and k.fib_stop_loss %}SL: {{ k.fib_stop_loss }} / TP: {{ k.fib_take_profit }}{% endif %} - 已提醒: {{ k.notification_count or 0 }}/{{ k.max_notify or 3 }} - {% if k.monitor_type in ['箱体突破','收敛突破'] %} - 方案: {{ '标准突破' if (k.sl_tp_mode or 'standard') == 'standard' else ('箱体1R·止盈1.5H' if k.sl_tp_mode == 'box_1p5' else '趋势单') }} - {% endif %} - 保本: {{ '开' if k.breakeven_enabled else '关' }} -
-
-
现价-
-
距上沿-
-
距下沿-
-
门控-
-
-
-
- {% else %} -
暂无监控中的关键位
- {% endfor %} -
-
-
-

关键位历史

-
失效或已结案的关键位
-
- {% for h in key_history %} -
-
-
- {{ h.symbol }} - {{ '做多' if h.direction == 'long' else '做空' }} -
- -
-
- {{ h.monitor_type }} - {{ h.close_reason }} - {{ (h.closed_at or '-')[:16] }} -
-
- 上: {{ h.upper }} 下: {{ h.lower }} - 提醒: {{ h.notification_count }} -
- {% if h.last_alert_message %}
{{ h.last_alert_message[:180] }}{% if h.last_alert_message|length > 180 %}…{% endif %}
{% endif %} -
- {% else %} -
暂无历史
- {% endfor %} -
-
-
+ {% include 'key_monitor_panel.html' %} {% elif page == 'trade' %}
@@ -2268,6 +2161,7 @@ function refreshPriceSnapshotConditional(){ if(gateEl){ gateEl.innerText = k.gate_summary || "-"; gateEl.style.color = k.gate_ok ? "#4cd97f" : "#ff8f8f"; } const gateMetricEl = document.getElementById(`key-gate-metrics-${k.id}`); if(gateMetricEl) gateMetricEl.innerText = k.gate_metrics || ""; + if(typeof paintKeyMonitorSummary === "function") paintKeyMonitorSummary(k.id, k); }); } if(page === "trade"){ diff --git a/strategy_templates/key_monitor_panel.html b/strategy_templates/key_monitor_panel.html new file mode 100644 index 0000000..0b204b1 --- /dev/null +++ b/strategy_templates/key_monitor_panel.html @@ -0,0 +1,173 @@ + + +{% macro key_direction_label(k) -%} +{% if k.direction == 'watch' %}双向{% elif k.direction == 'long' %}做多{% else %}做空{% endif %} +{%- endmacro %} + +{% macro key_sl_tp_mode_label(k) -%} +{% if (k.sl_tp_mode or 'standard') == 'standard' %}标准突破{% elif k.sl_tp_mode == 'box_1p5' %}箱体1R·止盈1.5H{% else %}趋势单{% endif %} +{%- endmacro %} + +{% macro key_monitor_brief(k) -%} +上{{ k.upper }} / 下{{ k.lower }} · 提醒 {{ k.notification_count or 0 }}/{{ k.max_notify or 3 }} +{%- if k.monitor_type in ['箱体突破','收敛突破'] %} · {{ key_sl_tp_mode_label(k) }}{% endif %} +{%- if k.breakeven_enabled %} · 保本开{% else %} · 保本关{% endif %} +{%- endmacro %} + +{% macro key_history_brief(h) -%} +{{ h.close_reason or '—' }} · {{ (h.closed_at or '-')[:16] }} · 上{{ h.upper }} / 下{{ h.lower }} · 提醒 {{ h.notification_count or 0 }} +{%- endmacro %} + +
+
+
+

关键位监控

+ {% if focus_key_id %} + 放大查看K线(默认200根) + {% else %} + 输入币种查看K线 + {% endif %} +
+
+ + + + + + + + + + +
+
{{ key_gate_rule_text }}
+
+ {% for k in key %} +
+ + + + {{ k.symbol }} + {% if k.direction == 'watch' %} + 双向 + {% else %} + {{ key_direction_label(k) }} + {% endif %} + {{ k.monitor_type }} + + {{ key_monitor_brief(k) }} + 现价 — · 门控 — + + + + + +
+
+ 上沿: {{ k.upper }} + 下沿: {{ k.lower }} + {% if k.fib_entry_price %}挂E: {{ k.fib_entry_price }}{% endif %} + {% if k.monitor_type == '假突破' and k.fib_stop_loss %}SL: {{ k.fib_stop_loss }} / TP: {{ k.fib_take_profit }}{% endif %} + 已提醒: {{ k.notification_count or 0 }}/{{ k.max_notify or 3 }} + {% if k.monitor_type in ['箱体突破','收敛突破'] %} + 方案: {{ key_sl_tp_mode_label(k) }} + {% endif %} + 保本: {{ '开' if k.breakeven_enabled else '关' }} +
+
+
现价-
+
距上沿-
+
距下沿-
+
门控-
+
+
+
+
+ {% else %} +
暂无监控中的关键位
+ {% endfor %} +
+
+
+

关键位历史

+
失效或已结案的关键位 · 点击展开详情
+
+ {% for h in key_history %} +
+ + + + {{ h.symbol }} + {{ key_direction_label(h) }} + {{ h.monitor_type }} + + {{ key_history_brief(h) }} + + + + + +
+
+ 类型: {{ h.monitor_type }} + 结案: {{ h.close_reason or '—' }} + 时间: {{ h.closed_at or '—' }} +
+
+ 上沿: {{ h.upper }} + 下沿: {{ h.lower }} + 提醒次数: {{ h.notification_count or 0 }} +
+ {% if h.last_alert_message %} +
{{ h.last_alert_message }}
+ {% endif %} +
+
+ {% else %} +
暂无历史
+ {% endfor %} +
+
+
+