From 9f5bc8b0042ec1cace045ff16e06cf44410f9e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=A5=E5=BE=AE?= Date: Wed, 8 Jul 2026 11:09:33 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20macro=5Fcontext=5Flog=2012=E5=A4=A9?= =?UTF-8?q?=E4=B8=8D=E6=9B=B4=E6=96=B0+=E8=87=AA=E6=A3=80=E8=A6=86?= =?UTF-8?q?=E7=9B=96+JSON=E6=96=87=E4=BB=B6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/cron_health_monitor.py | 3 +- scripts/refresh_macro_context.py | 82 ++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 scripts/refresh_macro_context.py diff --git a/scripts/cron_health_monitor.py b/scripts/cron_health_monitor.py index 1402e8ab..3a0c9556 100644 --- a/scripts/cron_health_monitor.py +++ b/scripts/cron_health_monitor.py @@ -29,7 +29,8 @@ CRITICAL_JOBS = { "宏观风险信号消费": {"max_idle_min": 40}, # 每15分 "重评管道审计": {"max_idle_min": 90}, # 每30分 "全局cron健康监控": {"max_idle_min": 30}, # 每10分 ← 自己 - "实时消息中继": {"max_idle_min": 20}, # 每5分 + "实时消息中继": {"max_idle_min": 20}, + "宏观上下文刷新": {"max_idle_min": 90}, # 每5分 } def xmpp_push(text): diff --git a/scripts/refresh_macro_context.py b/scripts/refresh_macro_context.py new file mode 100644 index 00000000..5d96a292 --- /dev/null +++ b/scripts/refresh_macro_context.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +"""refresh_macro_context.py — 刷新macro_context_log + +读取最新market_snapshots + 腾讯实时指数, 写入macro_context_log +让load_macro_context()拿到最新市场偏向, 而不是12天前的数据 + +每30分钟跑一次(交易日) +""" +import json, sqlite3, urllib.request, re, sys +from pathlib import Path +from datetime import datetime + +DB = Path("/home/hmo/MoFin/data/mofin.db") + +def fetch_index(code, name): + """从腾讯API拿指数行情""" + try: + url = f"http://qt.gtimg.cn/q={code}" + req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) + resp = urllib.request.urlopen(req, timeout=5) + text = resp.read().decode("gbk") + m = re.search(r'~([^~]*)~([^~]*)~([\d.]+)~([\d.]+)~([\d.]+)~([\d.]+)', text) + if m: + _, _, price, prev_close, open_p, high_low = m.groups() + high = high_low.split("~")[0] if "~" in high_low else high_low[:8] + low = high_low.split("~")[1] if "~" in high_low else "0" + change_pct = (float(price) - float(prev_close)) / float(prev_close) * 100 if float(prev_close) else 0 + return { + "price": float(price), + "change_pct": round(change_pct, 2), + "high": float(high) if high else float(price), + "low": float(low) if low else float(price) + } + except: + return None + +def main(): + # 采集各指数 + indices = { + "上证指数": fetch_index("sh000001", "上证指数"), + "深证成指": fetch_index("sz399001", "深证成指"), + "创业板指": fetch_index("sz399006", "创业板指"), + "恒生指数": fetch_index("szHSI", "恒生指数"), + "国企指数": fetch_index("szHSCEI", "国企指数"), + } + indices = {k: v for k, v in indices.items() if v} + + # 计算偏向 + sh = indices.get("上证指数", {}) + sh_change = sh.get("change_pct", 0) if sh else 0 + if sh_change < -1.5: + overall = "bearish" + desc = "大盘偏弱" + elif sh_change > 1.0: + overall = "bullish" + desc = "大盘偏强" + else: + overall = "neutral" + desc = "大盘震荡" + + structure = json.dumps({"overall": overall, "description": desc}, ensure_ascii=False) + indices_json = json.dumps(indices, ensure_ascii=False) + + # 写入macro_context_log + now = datetime.now() + session = "midday" if now.hour >= 12 else "morning" + ts = now.strftime("%Y-%m-%d %H:%M:%S") + try: + conn = sqlite3.connect(str(DB)) + conn.execute(""" + INSERT INTO macro_context_log + (data_timestamp, session, has_valid_data, indices, structure, created_at) + VALUES (?, ?, 1, ?, ?, ?) + """, (ts, session, indices_json, structure, ts)) + conn.commit() + conn.close() + print(f"[SILENT] macro_context updated: {overall} {desc} {len(indices)} indices") + except Exception as e: + print(f"[SILENT] macro_context write failed: {e}") + +if __name__ == "__main__": + main()