diff --git a/crypto_monitor_binance/app.py b/crypto_monitor_binance/app.py index 56d5c95..961f7ed 100644 --- a/crypto_monitor_binance/app.py +++ b/crypto_monitor_binance/app.py @@ -6008,12 +6008,12 @@ def render_main_page(page="trade"): f"【阻力/支撑】填上/下沿,5m 收盘突破任一侧即提醒 {KEY_ALERT_MAX_TIMES} 次(间隔 {KEY_ALERT_INTERVAL_MINUTES} 分),不选方向、不自动开仓" ) strategy_extra = {} - if page in ("strategy", "strategy_trend", "strategy_roll"): - from strategy_ui import strategy_page_template_vars + if page in ("strategy", "strategy_trend", "strategy_roll", "strategy_records"): + from strategy_ui import strategy_render_extras - strategy_extra = strategy_page_template_vars( + strategy_extra = strategy_render_extras( conn, - "strategy", + page, default_risk_percent=float(RISK_PERCENT), request_obj=request, trend_cfg=app.extensions.get("strategy_trend_cfg"), diff --git a/crypto_monitor_binance/templates/index.html b/crypto_monitor_binance/templates/index.html index 26f6b41..e2dac27 100644 --- a/crypto_monitor_binance/templates/index.html +++ b/crypto_monitor_binance/templates/index.html @@ -259,6 +259,7 @@ 关键位监控 实盘下单 策略交易 + 策略交易记录 交易记录与复盘 统计分析 @@ -594,6 +595,8 @@ {% elif page in ('strategy', 'strategy_trend', 'strategy_roll') %} {% include 'strategy_trading_page.html' %} + {% elif page == 'strategy_records' %} + {% include 'strategy_records_page.html' %} {% endif %} diff --git a/crypto_monitor_gate/app.py b/crypto_monitor_gate/app.py index 0599e12..135b425 100644 --- a/crypto_monitor_gate/app.py +++ b/crypto_monitor_gate/app.py @@ -5964,12 +5964,12 @@ def render_main_page(page="trade"): f"【阻力/支撑】填上/下沿,5m 收盘突破任一侧即提醒 {KEY_ALERT_MAX_TIMES} 次(间隔 {KEY_ALERT_INTERVAL_MINUTES} 分),不选方向、不自动开仓" ) strategy_extra = {} - if page in ("strategy", "strategy_trend", "strategy_roll"): - from strategy_ui import strategy_page_template_vars + if page in ("strategy", "strategy_trend", "strategy_roll", "strategy_records"): + from strategy_ui import strategy_render_extras - strategy_extra = strategy_page_template_vars( + strategy_extra = strategy_render_extras( conn, - "strategy", + page, default_risk_percent=float(RISK_PERCENT), request_obj=request, trend_cfg=app.extensions.get("strategy_trend_cfg"), diff --git a/crypto_monitor_gate/templates/index.html b/crypto_monitor_gate/templates/index.html index 26f6b41..e2dac27 100644 --- a/crypto_monitor_gate/templates/index.html +++ b/crypto_monitor_gate/templates/index.html @@ -259,6 +259,7 @@ 关键位监控 实盘下单 策略交易 + 策略交易记录 交易记录与复盘 统计分析 @@ -594,6 +595,8 @@ {% elif page in ('strategy', 'strategy_trend', 'strategy_roll') %} {% include 'strategy_trading_page.html' %} + {% elif page == 'strategy_records' %} + {% include 'strategy_records_page.html' %} {% endif %} diff --git a/crypto_monitor_gate_bot/app.py b/crypto_monitor_gate_bot/app.py index 7e97f7c..382b44f 100644 --- a/crypto_monitor_gate_bot/app.py +++ b/crypto_monitor_gate_bot/app.py @@ -3824,7 +3824,9 @@ def enrich_active_trend_plan_row(row): d["floating_mark"] = float(m["mark_price"]) else: d["floating_mark"] = None - return d + from strategy_snapshot_lib import attach_trend_dca_levels + + return attach_trend_dca_levels(d) def opened_at_str_to_ms(opened_at_str): @@ -4602,6 +4604,25 @@ def _trend_finalize_plan(conn, row, result_label, exit_price, closed_at=None): if not getattr(cur, "rowcount", 0): return conn.commit() + try: + cfg = app.extensions.get("strategy_trend_cfg") or {} + closed = conn.execute( + "SELECT * FROM trend_pullback_plans WHERE id=?", (plan_id,) + ).fetchone() + if closed and cfg: + from strategy_snapshot_lib import save_trend_plan_snapshot + + save_trend_plan_snapshot( + cfg, + conn, + closed, + result_label=result_label, + exit_price=float(exit_price), + pnl_amount=float(pnl_amount) if pnl_amount is not None else None, + ) + conn.commit() + except Exception: + pass if _trend_plan_trade_exists(conn, plan_id): return session_date = row["session_date"] or get_trading_day() @@ -5457,7 +5478,11 @@ def render_main_page(page="trade"): elif pr: trend_preview_expired = True strategy_extra = {} - if page in ("strategy", "strategy_trend", "strategy_roll"): + if page == "strategy_records": + from strategy_ui import strategy_render_extras + + strategy_extra = strategy_render_extras(conn, page) + elif page in ("strategy", "strategy_trend", "strategy_roll"): from strategy_ui import fetch_roll_page_data strategy_extra = fetch_roll_page_data( diff --git a/crypto_monitor_gate_bot/templates/index.html b/crypto_monitor_gate_bot/templates/index.html index d43837a..f914392 100644 --- a/crypto_monitor_gate_bot/templates/index.html +++ b/crypto_monitor_gate_bot/templates/index.html @@ -248,6 +248,7 @@
@@ -422,6 +423,8 @@ {% elif page in ('strategy', 'strategy_trend', 'strategy_roll') %} {% set can_trade_trend = can_trade %} {% include 'strategy_trading_page.html' %} + {% elif page == 'strategy_records' %} + {% include 'strategy_records_page.html' %} {% endif %} {% if page == 'records' %} diff --git a/crypto_monitor_okx/app.py b/crypto_monitor_okx/app.py index 3def956..282521a 100644 --- a/crypto_monitor_okx/app.py +++ b/crypto_monitor_okx/app.py @@ -5608,12 +5608,12 @@ def render_main_page(page="trade"): f"【阻力/支撑】填上/下沿,5m 收盘突破任一侧即提醒 {KEY_ALERT_MAX_TIMES} 次(间隔 {KEY_ALERT_INTERVAL_MINUTES} 分),不选方向、不自动开仓" ) strategy_extra = {} - if page in ("strategy", "strategy_trend", "strategy_roll"): - from strategy_ui import strategy_page_template_vars + if page in ("strategy", "strategy_trend", "strategy_roll", "strategy_records"): + from strategy_ui import strategy_render_extras - strategy_extra = strategy_page_template_vars( + strategy_extra = strategy_render_extras( conn, - "strategy", + page, default_risk_percent=float(RISK_PERCENT), request_obj=request, trend_cfg=app.extensions.get("strategy_trend_cfg"), diff --git a/crypto_monitor_okx/templates/index.html b/crypto_monitor_okx/templates/index.html index a818e88..a8b442b 100644 --- a/crypto_monitor_okx/templates/index.html +++ b/crypto_monitor_okx/templates/index.html @@ -259,6 +259,7 @@ 关键位监控 实盘下单 策略交易 + 策略交易记录 交易记录与复盘 统计分析 @@ -603,6 +604,8 @@ {% elif page in ('strategy', 'strategy_trend', 'strategy_roll') %} {% include 'strategy_trading_page.html' %} + {% elif page == 'strategy_records' %} + {% include 'strategy_records_page.html' %} {% endif %} diff --git a/manual_trading_hub/static/app.css b/manual_trading_hub/static/app.css index 87ddd6e..1fdcdf1 100644 --- a/manual_trading_hub/static/app.css +++ b/manual_trading_hub/static/app.css @@ -1375,15 +1375,84 @@ body.market-chart-fs-open { color: #8fc8ff; } -.exchange-fullscreen .hub-trend-plan-list { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); - gap: 14px; - align-items: stretch; +.hub-trend-plan-card--horizontal { + display: flex; + flex-wrap: wrap; + gap: 14px 18px; + align-items: flex-start; + background: linear-gradient(145deg, rgba(12, 18, 32, 0.92), rgba(8, 12, 22, 0.88)); + border-color: rgba(0, 212, 255, 0.22); + box-shadow: 0 4px 18px rgba(0, 0, 0, 0.35); } -.exchange-fullscreen .hub-trend-plan-card { - height: 100%; +.hub-trend-plan-body { + flex: 1 1 320px; + min-width: 0; +} + +.hub-trend-plan-side { + flex: 1 1 220px; + min-width: 200px; + max-width: 100%; +} + +.hub-trend-dca-block { + padding: 8px 10px; + background: rgba(0, 0, 0, 0.22); + border: 1px solid var(--border-soft); + border-radius: 8px; +} + +.hub-trend-dca-title { + font-size: 11px; + color: var(--muted); + margin-bottom: 6px; +} + +.hub-trend-dca-table { + width: 100%; + border-collapse: collapse; + font-size: 11px; +} + +.hub-trend-dca-table th, +.hub-trend-dca-table td { + padding: 4px 6px; + border-bottom: 1px solid rgba(255, 255, 255, 0.06); + text-align: left; +} + +.hub-trend-dca-table th { + color: var(--muted); + font-weight: 600; +} + +.hub-trend-dca-table .dca-done { + color: var(--green); +} + +.hub-trend-dca-table .dca-pending { + color: var(--muted); +} + +.exchange-fullscreen .hub-trend-plan-list { + display: block; + max-width: 100%; +} + +.exchange-fullscreen .hub-trend-plan-card--horizontal { + width: 100%; +} + +.exchange-fullscreen .hub-trend-plan-metrics-row { + display: flex; + flex-wrap: wrap; + align-items: flex-end; + gap: 10px 16px; +} + +.exchange-fullscreen .hub-trend-plan-grid { + flex: 1 1 280px; } /* 顺势加仓 */ diff --git a/manual_trading_hub/static/app.js b/manual_trading_hub/static/app.js index a26339c..f95e033 100644 --- a/manual_trading_hub/static/app.js +++ b/manual_trading_hub/static/app.js @@ -1513,6 +1513,37 @@ return html; } + function renderTrendDcaTable(t, tickMap) { + const levels = Array.isArray(t.dca_levels) ? t.dca_levels : []; + if (!levels.length) return ""; + const sym = t.exchange_symbol || t.symbol || ""; + const rows = levels + .map((lv) => { + const price = + lv.price != null && lv.price !== "" + ? fmtSymbolPrice(lv.price, sym, tickMap) + : "—"; + const amt = + lv.contracts != null && lv.contracts !== "" ? esc(String(lv.contracts)) : "—"; + const stCls = lv.status === "done" ? "dca-done" : "dca-pending"; + const label = lv.status_label || (lv.status === "done" ? "已补仓" : "待补仓"); + return `| 档位 | 触发价 | 张数 | 状态 |
|---|