diff --git a/deploy/profile-scripts/functional_health_check.py b/deploy/profile-scripts/functional_health_check.py index ecbb7509..7b868d29 100644 --- a/deploy/profile-scripts/functional_health_check.py +++ b/deploy/profile-scripts/functional_health_check.py @@ -47,6 +47,9 @@ REGISTRY = [ "check": {"type": "file_freshness", "path": "/tmp/mofin_premarket/summary.json", "max_age_h": 26, "when": "daily"}, "repair": {"action": "rerun_script", "script": "premarket_full_review.py"}}, + {"module": "reassess_daily", "function": "每日12维重评完成度(持仓当日覆盖+分析存在率)", + "check": {"type": "reassess_daily", "when": "daily"}, + "repair": {"action": "rerun_script", "script": "batch_reassess.py --type holding --today"}}, {"module": "gateway_llm", "function": "LLM调用链可用(gateway agent.log)", "check": {"type": "agent_log", "max_age_min": 30, "when": "always"}, "repair": {"action": "llm_diagnose"}}, @@ -180,6 +183,58 @@ def check_cron_engine(chk, now): return "fail", f"检查失败: {e}" +def check_reassess_daily(conn, now): + """每日12维重评完成度: + - 持仓:当日已重评比例(交易日13:00后应≈100%,此前按上一交易日)+ 有分析比例 + - 自选:近24h重评比例(补评管道是否活着) + 阈值:持仓当日覆盖<50% 或 分析存在率<70% → fail;<90% → warn + """ + try: + today = now.strftime("%Y-%m-%d") + rows = conn.execute( + "SELECT decision_type, reassessed_at, full_analysis FROM holding_strategies WHERE status='active'").fetchall() + h_total = h_today = h_fa = w_total = w_24h = 0 + cutoff = now - timedelta(hours=24) + for dt, ra, fa in rows: + fa_ok = bool(fa and str(fa).strip()) + ra_dt = None + if ra: + try: + ra_dt = datetime.fromisoformat(str(ra)[:19]) + except Exception: + pass + if dt == '持仓策略': + h_total += 1 + if fa_ok: + h_fa += 1 + if ra_dt and ra_dt.strftime("%Y-%m-%d") == today: + h_today += 1 + else: + w_total += 1 + if ra_dt and ra_dt >= cutoff: + w_24h += 1 + if h_total == 0: + return "fail", "holding_strategies 无持仓数据" + h_cov = h_today / h_total + h_fa_rate = h_fa / h_total + w_cov = w_24h / w_total if w_total else 1 + detail = (f"持仓 今日重评{h_today}/{h_total}({h_cov:.0%}) 有分析{h_fa}/{h_total}({h_fa_rate:.0%}) | " + f"自选 24h重评{w_24h}/{w_total}({w_cov:.0%})") + # 12:35 前补评窗口未完成属正常,降级 warn + grace = now.hour < 13 or now.weekday() >= 5 + if h_fa_rate < 0.7: + return "fail", f"分析存在率过低: {detail}" + if h_cov < 0.5 and not grace: + return "fail", f"今日持仓重评覆盖不足: {detail}" + if h_cov < 0.9 and not grace: + return "warn", f"覆盖不完整: {detail}" + if grace and (h_cov < 0.9 or w_cov < 0.2): + return "warn", f"补评窗口中: {detail}" + return "ok", detail + except Exception as e: + return "fail", f"检查异常: {e}" + + def main(): now = datetime.now() trading = is_trading_now(now) @@ -212,6 +267,8 @@ def main(): status, reason = check_ocr_health(chk, now) elif t == "cron_engine": status, reason = check_cron_engine(chk, now) + elif t == "reassess_daily": + status, reason = check_reassess_daily(conn, now) else: status, reason = "fail", f"未知检查类型 {t}"