diff --git a/crypto_monitor_gate_bot/app.py b/crypto_monitor_gate_bot/app.py
index b5a713c..7d34b73 100644
--- a/crypto_monitor_gate_bot/app.py
+++ b/crypto_monitor_gate_bot/app.py
@@ -5270,11 +5270,27 @@ def background_task():
check_roll_monitors(_roll_cfg)
check_order_monitors()
- except:
- pass
+ except Exception as e:
+ print(f"[background_task] error: {e}", flush=True)
time.sleep(MONITOR_POLL_SECONDS)
+_BG_MONITORS_LOCK = threading.Lock()
+_BG_MONITORS_STARTED = False
+
+
+def _ensure_background_monitors_started():
+ global _BG_MONITORS_STARTED
+ with _BG_MONITORS_LOCK:
+ if _BG_MONITORS_STARTED:
+ return
+ _BG_MONITORS_STARTED = True
+ threading.Thread(
+ target=background_task, daemon=True, name="gate-bot-monitors"
+ ).start()
+ print("[startup] background monitor thread started", flush=True)
+
+
# ====================== 登录路由 ======================
@app.route("/login", methods=["GET", "POST"])
def login():
@@ -5400,12 +5416,26 @@ def render_main_page(page="trade"):
"SELECT * FROM trend_pullback_plans WHERE status='active' ORDER BY id DESC"
).fetchall()
trend_plans = []
+ trend_dca_probes = []
+ _trend_cfg = app.extensions.get("strategy_trend_cfg")
for r in trend_plans_raw:
try:
- trend_plans.append(enrich_active_trend_plan_row(r))
+ enriched = enrich_active_trend_plan_row(r)
+ trend_plans.append(enriched)
except Exception as e:
print(f"[render_main_page] enrich trend plan: {e}")
- trend_plans.append(row_to_dict(r))
+ enriched = row_to_dict(r)
+ trend_plans.append(enriched)
+ if _trend_cfg and page in ("strategy", "strategy_trend", "strategy_roll"):
+ try:
+ from strategy_trend_register import summarize_trend_dca_probe
+
+ probe = summarize_trend_dca_probe(_trend_cfg, r)
+ trend_dca_probes.append(probe)
+ if isinstance(enriched, dict):
+ enriched["dca_probe"] = probe
+ except Exception as e:
+ print(f"[render_main_page] trend dca probe: {e}")
preview_snapshots = []
if page == "records":
try:
@@ -5511,6 +5541,8 @@ def render_main_page(page="trade"):
manual_min_planned_rr=MANUAL_MIN_PLANNED_RR,
can_trade=can_trade,
trend_plans=trend_plans,
+ trend_dca_probes=trend_dca_probes,
+ live_trading_enabled=LIVE_TRADING_ENABLED,
preview_snapshots=preview_snapshots,
exchange_sync_from_label=(EXCHANGE_POSITION_SYNC_FROM_BJ or "最近90天"),
trend_pullback_dca_legs=TREND_PULLBACK_DCA_LEGS,
@@ -8017,6 +8049,35 @@ def strategy_trend_page():
return redirect(f"/strategy?{qs}" if qs else "/strategy")
+@app.route("/api/trend_poll_status")
+@login_required
+def api_trend_poll_status():
+ from strategy_trend_register import (
+ build_trend_config,
+ get_trend_poll_state,
+ summarize_trend_dca_probe,
+ )
+
+ cfg = app.extensions.get("strategy_trend_cfg") or build_trend_config(
+ sys.modules[__name__]
+ )
+ conn = get_db()
+ probes = []
+ for r in conn.execute(
+ "SELECT * FROM trend_pullback_plans WHERE status='active' ORDER BY id DESC"
+ ).fetchall():
+ probes.append(summarize_trend_dca_probe(cfg, r))
+ conn.close()
+ return jsonify(
+ {
+ "poll": get_trend_poll_state(),
+ "probes": probes,
+ "live_trading_enabled": LIVE_TRADING_ENABLED,
+ "monitor_poll_seconds": MONITOR_POLL_SECONDS,
+ }
+ )
+
+
@app.route("/strategy/roll")
@login_required
def strategy_roll_page():
@@ -8035,9 +8096,9 @@ install_strategy_trading(
app.extensions["strategy_trend_cfg"] = build_trend_config(sys.modules[__name__])
_purge_key_monitors_if_full_margin()
+_ensure_background_monitors_started()
# 启动
if __name__ == "__main__":
- threading.Thread(target=background_task, daemon=True).start()
app.run(host=HOST, port=PORT, debug=DEBUG)
diff --git a/strategy_templates/strategy_trend_panel.html b/strategy_templates/strategy_trend_panel.html
index 9964036..6c54c8f 100644
--- a/strategy_templates/strategy_trend_panel.html
+++ b/strategy_templates/strategy_trend_panel.html
@@ -7,6 +7,19 @@
② 确认执行:市价首仓 50% + 挂交易所止损;首仓后可手动保本(默认均价+{{ trend_manual_breakeven_offset_pct }}%);剩余 50% 在止损与补仓区间之间共 {{ trend_pullback_dca_legs }} 档(做多为上沿、做空为下沿;程序可能因最小张数自动减档)市价补仓;止盈由程序监控。
确认执行时若当前可用余额与预览快照相对偏差 > {{ trend_preview_max_drift_pct }}% 会拒绝并要求重新预览。
+ {% if trend_dca_probes %}
+ {% for p in trend_dca_probes %}
+ {% if p.trigger_reached and p.block_reason %}
+
crypto_monitor_gate_bot/.env 设置 LIVE_TRADING_ENABLED=true 后重启 PM2 进程 crypto_gate_bot(不是 manual-agent-gate-bot)。
+ {% endif %}
+