From 90f07b4eba2d64b7186c0c02a19fd1247cb3dea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=A5=E5=BE=AE?= Date: Mon, 20 Jul 2026 22:05:03 +0800 Subject: [PATCH] chore: sync --- deploy/profile-scripts/stale_detector.py | 22 +- deploy/profile-scripts/strategy_lifecycle.py | 8 + scripts/strategy_lifecycle.py | 8 + static/mofin_health.json | 287 ++++++++++--------- strategy_lifecycle.py | 8 + 5 files changed, 187 insertions(+), 146 deletions(-) diff --git a/deploy/profile-scripts/stale_detector.py b/deploy/profile-scripts/stale_detector.py index 93412551..dd86e9b2 100644 --- a/deploy/profile-scripts/stale_detector.py +++ b/deploy/profile-scripts/stale_detector.py @@ -142,7 +142,7 @@ def main(): reassess_scripts.append(code) print(f"[AUTO_REASSESS] {name}({code}) 价{cur_price:.2f}偏离买入区中心{center:.2f} {drift:+.0f}% → 触发重评") if reassess_scripts: - # 调用 per_stock_reassess + # 调用 per_stock_reassess(每轮最多5只,防LLM慢导致整批超时;其余下轮继续) reassess_path = None for p in ['/home/hmo/MoFin/scripts/per_stock_reassess.py', '/home/hmo/.hermes/profiles/position-analyst/scripts/per_stock_reassess.py']: @@ -150,12 +150,20 @@ def main(): reassess_path = p break if reassess_path: - for code in reassess_scripts: - r = subprocess.run(['python3', reassess_path, code], - capture_output=True, text=True, timeout=60) - out = r.stdout.strip()[:200] if r.stdout else "" - err = r.stderr.strip()[:200] if r.stderr else "" - print(f" → {code}: exited={r.returncode} {out}") + MAX_PER_RUN = 5 + batch = reassess_scripts[:MAX_PER_RUN] + if len(reassess_scripts) > MAX_PER_RUN: + print(f"[AUTO_REASSESS] 本轮限{MAX_PER_RUN}只,剩余{len(reassess_scripts)-MAX_PER_RUN}只下轮继续") + for code in batch: + try: + # LLM 重评冷启动 20-100s,60s 必死(37只全灭那次的根因)→ 240s + r = subprocess.run(['python3', reassess_path, code], + capture_output=True, text=True, timeout=240) + out = r.stdout.strip()[:200] if r.stdout else "" + err = r.stderr.strip()[:200] if r.stderr else "" + print(f" → {code}: exited={r.returncode} {out}") + except subprocess.TimeoutExpired: + print(f" → {code}: 超时240s(LLM仍慢),下轮重试") except Exception as e: print(f"[AUTO_REASSESS FAIL] {e}") # ----- 结束 自选股重评 ----- diff --git a/deploy/profile-scripts/strategy_lifecycle.py b/deploy/profile-scripts/strategy_lifecycle.py index 12dce8e9..b0f0867e 100644 --- a/deploy/profile-scripts/strategy_lifecycle.py +++ b/deploy/profile-scripts/strategy_lifecycle.py @@ -90,6 +90,14 @@ STRATEGY_QUALITY_GATES = [ "severity": "HIGH", "fix": "设置 d['currency']='HKD'" }, + { + "id": "GATE_ZONE_SANITY", + "desc": "买入区中心不得偏离现价超过3倍(防坏行情/LLM幻觉注入异常值,如15只股被统一写成97的教训)", + "check": lambda d: (lambda p, c: p <= 0 or c <= 0 or (p >= c * 0.3 and p <= c * 3.0))( + d.get("price") or 0, ((d.get("entry_low") or 0) + (d.get("entry_high") or 0)) / 2), + "severity": "CRITICAL", + "fix": "买入区与现价偏离超3倍,疑似坏数据。用 technical_analysis 重算支撑阻力或人工修正" + }, # --- 第4条 CRITICAL 红线:9维交叉验证 (2026-07-02 Dad要求) --- # 策略不能只有价格数字,必须有证据经过了多维分析: # 横切面: 大盘+行业+个股 | 纵切面: 基本面+消息面+技术面+资金流 diff --git a/scripts/strategy_lifecycle.py b/scripts/strategy_lifecycle.py index 12dce8e9..b0f0867e 100644 --- a/scripts/strategy_lifecycle.py +++ b/scripts/strategy_lifecycle.py @@ -90,6 +90,14 @@ STRATEGY_QUALITY_GATES = [ "severity": "HIGH", "fix": "设置 d['currency']='HKD'" }, + { + "id": "GATE_ZONE_SANITY", + "desc": "买入区中心不得偏离现价超过3倍(防坏行情/LLM幻觉注入异常值,如15只股被统一写成97的教训)", + "check": lambda d: (lambda p, c: p <= 0 or c <= 0 or (p >= c * 0.3 and p <= c * 3.0))( + d.get("price") or 0, ((d.get("entry_low") or 0) + (d.get("entry_high") or 0)) / 2), + "severity": "CRITICAL", + "fix": "买入区与现价偏离超3倍,疑似坏数据。用 technical_analysis 重算支撑阻力或人工修正" + }, # --- 第4条 CRITICAL 红线:9维交叉验证 (2026-07-02 Dad要求) --- # 策略不能只有价格数字,必须有证据经过了多维分析: # 横切面: 大盘+行业+个股 | 纵切面: 基本面+消息面+技术面+资金流 diff --git a/static/mofin_health.json b/static/mofin_health.json index 37959b04..46ce2f4d 100644 --- a/static/mofin_health.json +++ b/static/mofin_health.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-07-20 21:30:05", + "generated_at": "2026-07-20 22:00:13", "feature_tree": { "label": "MoFin 系统", "status": "ok", @@ -537,7 +537,7 @@ "script": "mofin_health.py", "schedule": "*/15 9-16,20-22 * * 1-5", "status": "ok", - "last_run": "2026-07-20T21:16", + "last_run": "2026-07-20T21:45", "type": "no_agent", "profile": "position-analyst" } @@ -624,7 +624,7 @@ "script": "self_todo_executor.py", "schedule": "*/10 8-22 * * 1-5", "status": "ok", - "last_run": "2026-07-20T21:20", + "last_run": "2026-07-20T21:50", "type": "no_agent", "profile": "position-analyst" } @@ -885,7 +885,7 @@ "script": "fix_gateway_port.py", "schedule": "every 10m", "status": "ok", - "last_run": "2026-07-20T21:24", + "last_run": "2026-07-20T21:55", "type": "no_agent", "profile": "position-analyst" } @@ -917,7 +917,7 @@ "script": "functional_health_check.py", "schedule": "*/15 9-16,20-22 * * 1-5", "status": "ok", - "last_run": "2026-07-20T21:15", + "last_run": "2026-07-20T21:45", "type": "no_agent", "profile": "position-analyst" } @@ -933,7 +933,7 @@ "script": "self_repair.py", "schedule": "*/30 9-16,20-22 * * 1-5", "status": "ok", - "last_run": "2026-07-20T21:00", + "last_run": "2026-07-20T21:30", "type": "no_agent", "profile": "position-analyst" } @@ -1080,16 +1080,16 @@ "desc": "潜力股候选池(小果扫描产出)", "rows": 185, "readers": [ - "promote_candidates", "candidate_filter", + "accumulation_scanner", "mofin_db", - "accumulation_scanner" + "promote_candidates" ], "writers": [ - "promote_candidates", "candidate_filter", "market_scanner", - "accumulation_scanner" + "accumulation_scanner", + "promote_candidates" ], "has_input": true, "has_output": true, @@ -1112,14 +1112,14 @@ "desc": "资金流缓存", "rows": 1, "readers": [ - "per_stock_reassess", + "merge_third_db", "batch_reassess", - "mofin_db", - "merge_third_db" + "per_stock_reassess", + "mofin_db" ], "writers": [ - "mofin_db", - "merge_third_db" + "merge_third_db", + "mofin_db" ], "has_input": true, "has_output": true, @@ -1195,25 +1195,25 @@ "desc": "每只股票的完整策略参数", "rows": 227, "readers": [ - "mofin_collect", - "promote_candidates", - "check_db_state", + "mofin_db", + "per_stock_reassess", "data_governance", - "watchlist_auto_exit", - "mo_data", - "price_monitor", - "generate_report", - "system_health_check", - "sync_decisions_to_db" + "verify_300308", + "mofin_collect", + "system_audit", + "verify_reassess_pipeline", + "accumulation_scanner", + "check_db_state", + "generate_report" ], "writers": [ - "promote_candidates", - "data_governance", - "sync_decisions_to_db", - "batch_reassess", - "watchlist_auto_exit", + "mofin_db", "per_stock_reassess", - "mofin_db" + "data_governance", + "promote_candidates", + "batch_reassess", + "sync_decisions_to_db", + "watchlist_auto_exit" ], "has_input": true, "has_output": true, @@ -1241,21 +1241,21 @@ "desc": "当前持仓(权威源)", "rows": 14, "readers": [ + "mo_alphasift_bridge", + "mofin_db", + "per_stock_reassess", "mofin_collect", "prepare_recommendation", - "mo_data", - "price_monitor", - "system_health_check", - "run_all_tests", + "system_audit", + "accumulation_scanner", + "trend_detector", "refresh_mtf_cache", - "prepare_report_data", - "capital_flow_collector", - "per_stock_reassess" + "import_holding_xls" ], "writers": [ + "import_holding_xls", "mofin_db", - "price_monitor", - "import_holding_xls" + "price_monitor" ], "has_input": true, "has_output": true, @@ -1283,14 +1283,14 @@ "desc": "所有持仓+自选最新实时价", "rows": 232, "readers": [ - "stale_push_wlin", - "generate_report", - "verify_reassess_pipeline", "candidate_filter", - "cron_health_monitor", - "mo_data", + "stale_push_wlin", "mofin_db", - "system_audit" + "generate_report", + "cron_health_monitor", + "system_audit", + "verify_reassess_pipeline", + "mo_data" ], "writers": [ "mo_data", @@ -1321,15 +1321,15 @@ "desc": "宏观上下文(大盘偏向/指数)", "rows": 81, "readers": [ - "strategy_tree", "stale_push_wlin", - "divergence_detector", - "batch_reassess", - "stock_profile", - "strategy_lifecycle", "per_stock_reassess", "system_audit", - "xiaoguo_signal_consumer" + "stock_profile", + "batch_reassess", + "divergence_detector", + "xiaoguo_signal_consumer", + "strategy_lifecycle", + "strategy_tree" ], "writers": [ "refresh_macro_context" @@ -1357,8 +1357,8 @@ "desc": "宏观新闻原始数据", "rows": 17383, "readers": [ - "macro_context_collector", - "system_audit" + "system_audit", + "macro_context_collector" ], "writers": [ "macro_context_collector" @@ -1384,18 +1384,18 @@ "desc": "大盘指数快照(每10分)", "rows": 989, "readers": [ - "market_screener", - "trend_detector", + "mofin_db", "mofin_query", + "trend_detector", + "merge_third_db", + "system_audit", "market_scanner", "prepare_report_data", - "merge_third_db", - "mofin_db", - "system_audit" + "market_screener" ], "writers": [ - "mofin_db", - "merge_third_db" + "merge_third_db", + "mofin_db" ], "has_input": true, "has_output": true, @@ -1420,13 +1420,13 @@ "desc": "多周期均线缓存", "rows": 64, "readers": [ - "mofin_db", + "multi_timeframe", "technical_analysis", - "multi_timeframe" + "mofin_db" ], "writers": [ - "mofin_db", - "multi_timeframe" + "multi_timeframe", + "mofin_db" ], "has_input": true, "has_output": true, @@ -1452,17 +1452,17 @@ "rows": 1, "readers": [ "check_db_state", - "prepare_report_data", + "mofin_db", "price_monitor", "import_holding_xls", "mo_data", - "preflight_verify", - "mofin_db" + "prepare_report_data", + "preflight_verify" ], "writers": [ + "import_holding_xls", "mofin_db", - "price_monitor", - "import_holding_xls" + "price_monitor" ], "has_input": true, "has_output": true, @@ -1489,21 +1489,21 @@ "desc": "价格区间突破事件日志", "rows": 6353, "readers": [ - "test_raw_insert", - "check_price_events", - "test_dual_write", "mofin_db", + "test_raw_insert", + "backfill_price_events", "test_db_write", "test_db_only", - "backfill_price_events" + "test_dual_write", + "check_price_events" ], "writers": [ - "test_raw_insert", - "test_dual_write", "mofin_db", + "test_raw_insert", + "backfill_price_events", "test_db_write", "test_db_only", - "backfill_price_events" + "test_dual_write" ], "has_input": true, "has_output": true, @@ -1525,14 +1525,14 @@ "desc": "行业信号(趋势检测产出)", "rows": 653, "readers": [ - "xiaoguo_news_processor", "server", "mofin_news", + "xiaoguo_news_processor", "trend_detector" ], "writers": [ - "xiaoguo_news_processor", "mofin_news", + "xiaoguo_news_processor", "trend_detector" ], "has_input": true, @@ -1560,17 +1560,17 @@ "desc": "行业板块数据", "rows": 68408, "readers": [ - "market_screener", + "mofin_db", "trend_detector", - "market_scanner", "merge_third_db", "inspect_third_db", + "market_scanner", "strategy_lifecycle", - "mofin_db" + "market_screener" ], "writers": [ - "mofin_db", - "merge_third_db" + "merge_third_db", + "mofin_db" ], "has_input": true, "has_output": true, @@ -1595,22 +1595,22 @@ "desc": "信号相关新闻", "rows": 1287, "readers": [ - "macro_signal_consumer", - "intraday_health_check", "server", - "batch_reassess", "per_stock_reassess", "system_audit", - "xiaoguo_signal_consumer" + "batch_reassess", + "intraday_health_check", + "xiaoguo_signal_consumer", + "macro_signal_consumer" ], "writers": [ - "xiaoguo_scanner", - "macro_signal_consumer", "mofin_news", "divergence_detector", - "xiaoguo_news_processor", + "xiaoguo_signal_consumer", "macro_context_collector", - "xiaoguo_signal_consumer" + "macro_signal_consumer", + "xiaoguo_news_processor", + "xiaoguo_scanner" ], "has_input": true, "has_output": true, @@ -1726,12 +1726,12 @@ "desc": "股票行业映射", "rows": 64, "readers": [ + "mofin_db", "trend_detector", - "mofin_news", - "xiaoguo_news_processor", - "strategy_lifecycle", "per_stock_reassess", - "mofin_db" + "mofin_news", + "strategy_lifecycle", + "xiaoguo_news_processor" ], "writers": [ "mofin_db" @@ -1776,19 +1776,19 @@ "desc": "全量股票代码", "rows": 5575, "readers": [ - "trend_detector", - "accumulation_scanner", - "mofin_news", - "xiaoguo_news_processor", - "import_full_stocks", + "check_stocks_table", "mofin_db", - "check_stocks_table" + "trend_detector", + "xiaoguo_news_processor", + "mofin_news", + "accumulation_scanner", + "import_full_stocks" ], "writers": [ "import_full_stocks", + "backfill_price_events", "mofin_db", - "price_monitor", - "backfill_price_events" + "price_monitor" ], "has_input": true, "has_output": true, @@ -1813,8 +1813,8 @@ "desc": "策略重评历史记录", "rows": 217, "readers": [ - "verify_reassess_pipeline", - "mofin_db" + "mofin_db", + "verify_reassess_pipeline" ], "writers": [ "mofin_collect" @@ -1868,20 +1868,20 @@ "desc": "自愈任务队列", "rows": 96, "readers": [ - "intraday_health_check", + "self_todo_executor", "merge_third_db", "morning_health_check", - "self_todo_executor", + "intraday_health_check", "strategy-staleness-check" ], "writers": [ + "self_todo_executor", + "merge_third_db", + "cron_health_monitor", + "morning_health_check", "mofin_collect", "intraday_health_check", - "merge_third_db", - "morning_health_check", - "self_todo_executor", "strategy-staleness-check", - "cron_health_monitor", "preflight_verify" ], "has_input": true, @@ -1929,16 +1929,16 @@ "desc": "自选股列表", "rows": 69, "readers": [ - "mofin_collect", - "trend_detector", "stale_push_wlin", - "xiaoguo_scanner", - "refresh_mtf_cache", + "mo_alphasift_bridge", "mofin_db", - "stock_quote", - "per_stock_reassess", "run_all_tests", - "mo_alphasift_bridge" + "trend_detector", + "per_stock_reassess", + "stock_quote", + "mofin_collect", + "refresh_mtf_cache", + "xiaoguo_signal_consumer" ], "writers": [ "per_stock_reassess", @@ -2105,15 +2105,15 @@ { "name": "mofin_health.json", "desc": "健康监控数据", - "size_kb": 89.3, + "size_kb": 89.6, "readers": [ - "analyze_health", - "verify_self_check_section", "verify_deployment", + "verify_self_check_section", + "analyze_health", "verify_health_json" ], "writers": [], - "last_modified": "07-20 21:16", + "last_modified": "07-20 21:45", "warn": false, "migrated_to_db": null }, @@ -2245,7 +2245,7 @@ "script": "fix_gateway_port.py", "schedule": "every 10m", "status": "ok", - "last_run": "2026-07-20T21:24:02", + "last_run": "2026-07-20T21:55:11", "profile": "position-analyst" }, { @@ -2254,7 +2254,7 @@ "script": "self_repair.py", "schedule": "*/30 9-16,20-22 * * 1-5", "status": "ok", - "last_run": "2026-07-20T21:00:53", + "last_run": "2026-07-20T21:30:06", "profile": "position-analyst" }, { @@ -2362,7 +2362,7 @@ "script": "mofin_health.py", "schedule": "*/15 9-16,20-22 * * 1-5", "status": "ok", - "last_run": "2026-07-20T21:16:11", + "last_run": "2026-07-20T21:45:17", "profile": "position-analyst" }, { @@ -2416,7 +2416,7 @@ "script": "functional_health_check.py", "schedule": "*/15 9-16,20-22 * * 1-5", "status": "ok", - "last_run": "2026-07-20T21:15:59", + "last_run": "2026-07-20T21:45:11", "profile": "position-analyst" }, { @@ -2434,7 +2434,7 @@ "script": "", "schedule": "{'kind': 'cron', 'expr': '*/10 * * * *'}", "status": "ok", - "last_run": "2026-07-20T21:21:29", + "last_run": "2026-07-20T21:50:39", "profile": "default" }, { @@ -2749,7 +2749,7 @@ "script": "self_todo_executor.py", "schedule": "*/10 8-22 * * 1-5", "status": "ok", - "last_run": "2026-07-20T21:20:59", + "last_run": "2026-07-20T21:50:10", "profile": "position-analyst" }, { @@ -2866,46 +2866,46 @@ "table": "mtf_cache", "label": "多周期均线缓存", "last_record": "07-20 17:08", - "age_hours": 4.4, + "age_hours": 4.9, "warn": false }, { "table": "macro_context_log", "label": "宏观上下文", "last_record": "07-20 15:31", - "age_hours": 6.0, + "age_hours": 6.5, "warn": false }, { "table": "market_snapshots", "label": "市场快照", "last_record": "07-20 15:50", - "age_hours": 5.7, + "age_hours": 6.2, "warn": false }, { "table": "live_prices", "label": "实时价格", "last_record": "07-20 18:12", - "age_hours": 3.3, + "age_hours": 3.8, "warn": false }, { "table": "price_events", "label": "价格事件", "last_record": "07-20 17:06", - "age_hours": 4.4, + "age_hours": 4.9, "warn": false } ], "self_check": { "functional": { - "generated_at": "2026-07-20 21:30:05", - "status": "ok", + "generated_at": "2026-07-20 22:00:13", + "status": "warn", "summary": { - "total": 9, + "total": 10, "ok": 3, - "warn": 0, + "warn": 1, "fail": 0, "skip": 6 }, @@ -2944,7 +2944,7 @@ "module": "premarket", "function": "盘前全量重评(premarket summary)", "status": "ok", - "reason": "799min前", + "reason": "829min前", "repair": { "action": "rerun_script", "script": "premarket_full_review.py" @@ -2953,8 +2953,17 @@ { "module": "gateway_llm", "function": "LLM调用链可用(gateway agent.log)", + "status": "warn", + "reason": "最近成功LLM调用在 39min 前(无新流量,可能正常)", + "repair": { + "action": "llm_diagnose" + } + }, + { + "module": "sense_ocr", + "function": "识图服务(SenseNova OCR配置+API可达)", "status": "ok", - "reason": "latency=9.5s", + "reason": "配置 OK + token.sensenova.cn:443 可达", "repair": { "action": "llm_diagnose" } diff --git a/strategy_lifecycle.py b/strategy_lifecycle.py index 12dce8e9..b0f0867e 100644 --- a/strategy_lifecycle.py +++ b/strategy_lifecycle.py @@ -90,6 +90,14 @@ STRATEGY_QUALITY_GATES = [ "severity": "HIGH", "fix": "设置 d['currency']='HKD'" }, + { + "id": "GATE_ZONE_SANITY", + "desc": "买入区中心不得偏离现价超过3倍(防坏行情/LLM幻觉注入异常值,如15只股被统一写成97的教训)", + "check": lambda d: (lambda p, c: p <= 0 or c <= 0 or (p >= c * 0.3 and p <= c * 3.0))( + d.get("price") or 0, ((d.get("entry_low") or 0) + (d.get("entry_high") or 0)) / 2), + "severity": "CRITICAL", + "fix": "买入区与现价偏离超3倍,疑似坏数据。用 technical_analysis 重算支撑阻力或人工修正" + }, # --- 第4条 CRITICAL 红线:9维交叉验证 (2026-07-02 Dad要求) --- # 策略不能只有价格数字,必须有证据经过了多维分析: # 横切面: 大盘+行业+个股 | 纵切面: 基本面+消息面+技术面+资金流