feat: 代码级策略新鲜度强制检查 — mofin_collect.py步骤0, 推荐前先检策略是否最新, 过期自动创TODO
This commit is contained in:
@@ -2,13 +2,14 @@
|
||||
"""mofin_collect.py — MoFin 数据采集链
|
||||
|
||||
每轮盯盘 cron 前运行,顺序执行:
|
||||
0. 策略新鲜度强制检查(代码级约束:推荐前必须先检查策略是否最新)
|
||||
1. market_watch — 拉90个行业板块数据(9:30前跳过,市场未开)
|
||||
2. trend_detector — 检测17种信号(依赖板块数据,同跳)
|
||||
3. mofin_news — 搜新闻+小果分析
|
||||
4. stock_quote — 所有持仓最新行情(CRITICAL: LLM唯一价格源)
|
||||
"""
|
||||
|
||||
import subprocess, sys, time
|
||||
import subprocess, sys, time, json
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
@@ -17,6 +18,80 @@ BASE = Path(__file__).parent.parent if "hermes" in str(Path(__file__).resolve())
|
||||
now = datetime.now()
|
||||
market_open = (now.hour >= 9 and now.minute >= 30) or now.hour >= 10
|
||||
|
||||
# ── 步骤0: 策略新鲜度强制检查(代码级约束)──
|
||||
# 在LLM看到任何数据前,先确保所有持仓策略是新鲜的
|
||||
# 策略过期(>4h未更新) → 创建TODO触发重评 + 注入STALE标记到LLM context
|
||||
# LLM看到STALE标记:禁止对该股给出任何操作建议
|
||||
print("--- strategy_freshness_check ---", flush=True)
|
||||
try:
|
||||
sys.path.insert(0, str(BASE))
|
||||
from mofin_db import get_conn
|
||||
conn = get_conn()
|
||||
cur = conn.cursor()
|
||||
# 读所有活跃持仓及其最新策略更新时间
|
||||
rows = cur.execute("""
|
||||
SELECT h.code, h.name, h.price, h.position_pct,
|
||||
hs.stop_loss, hs.take_profit, hs.entry_low, hs.entry_high,
|
||||
hs.created_at, hs.action
|
||||
FROM holdings h
|
||||
LEFT JOIN (
|
||||
SELECT code, stop_loss, take_profit, entry_low, entry_high,
|
||||
created_at, action,
|
||||
ROW_NUMBER() OVER (PARTITION BY code ORDER BY id DESC) AS rn
|
||||
FROM holding_strategies
|
||||
) hs ON h.code = hs.code AND hs.rn = 1
|
||||
WHERE h.is_active = 1
|
||||
ORDER BY h.code
|
||||
""").fetchall()
|
||||
|
||||
stale_count = 0
|
||||
fresh_count = 0
|
||||
no_strategy_count = 0
|
||||
|
||||
for r in rows:
|
||||
code = r["code"]
|
||||
name = r["name"]
|
||||
last_update = r["created_at"]
|
||||
has_strategy = last_update is not None
|
||||
|
||||
if has_strategy:
|
||||
try:
|
||||
last_dt = datetime.fromisoformat(last_update)
|
||||
hours_stale = (now - last_dt).total_seconds() / 3600
|
||||
except:
|
||||
hours_stale = 999
|
||||
|
||||
if hours_stale > 4:
|
||||
# 策略过期→创建TODO触发重评
|
||||
stale_count += 1
|
||||
todo_sql = """
|
||||
INSERT OR IGNORE INTO todos
|
||||
(title, code, fix_action, source, priority, status, created_at)
|
||||
VALUES (?, ?, 'reassess_strategy', 'freshness_check', 'high', 'pending', ?)
|
||||
"""
|
||||
cur.execute(todo_sql, (
|
||||
f"策略过期需重评: {code} {name} ({hours_stale:.0f}h未更新)",
|
||||
code,
|
||||
now.isoformat()
|
||||
))
|
||||
print(f" ⚠️ STALE {code} {name}: {hours_stale:.0f}h未更新 → 已创建重评TODO", flush=True)
|
||||
else:
|
||||
fresh_count += 1
|
||||
print(f" ✅ FRESH {code} {name}: {hours_stale:.1f}h前更新", flush=True)
|
||||
else:
|
||||
no_strategy_count += 1
|
||||
print(f" ❌ NO_STRATEGY {code} {name}: 无策略记录", flush=True)
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
total = len(rows)
|
||||
print(f"策略检查完成: {total}只持仓, {fresh_count}新鲜, {stale_count}过期(已创TODO), {no_strategy_count}无策略", flush=True)
|
||||
if stale_count > 0 or no_strategy_count > 0:
|
||||
print(f"⚠️ LLM注意: 有{stale_count + no_strategy_count}只持仓策略不是最新状态, 禁止对这些股给出操作建议", flush=True)
|
||||
except Exception as e:
|
||||
print(f"WARN: strategy_freshness_check跳过 ({e})", flush=True)
|
||||
|
||||
# 步骤1-3: 行业/新闻数据
|
||||
SCRIPTS = []
|
||||
if market_open:
|
||||
|
||||
Reference in New Issue
Block a user