diff --git a/scripts/macro_index_collector.py b/scripts/macro_index_collector.py deleted file mode 100644 index 07752da..0000000 --- a/scripts/macro_index_collector.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env python3 -"""macro_index_collector.py — 指数宏观数据采集 (no_agent) - -采集指数行情,写入 macro_context_log 表(积累每日快照)。 -与莫荷的 macro_context_collector.py(宏观新闻采集)分开,互不冲突。 - -在 9:35 和 12:00 由 cron 触发。 -""" - -import json, sqlite3, subprocess -from datetime import datetime -from pathlib import Path - -DATA_DIR = Path("/home/hmo/web-dashboard/data") -DB_PATH = Path("/home/hmo/MoFin/data/mofin.db") - -INDICES = [ - ("sh000001", "上证指数"), ("sz399001", "深证成指"), - ("sz399006", "创业板指"), ("sh000688", "科创50"), - ("hkHSI", "恒生指数"), ("hkHSCEI", "国企指数"), -] - -SECTOR_INDICES = [ - ("sz980017", "国证芯片"), ("sh000039", "上证信息"), - ("sz980022", "机器人产业"), ("sz980032", "新能电池"), - ("sz980076", "通用航空"), ("sh000063", "上证周期"), - ("sh000068", "上证资源"), ("sh000019", "治理指数"), -] - - -def fetch(symbol): - try: - r = subprocess.run(["curl", "-s", f"https://qt.gtimg.cn/q={symbol}"], - capture_output=True, timeout=8) - return r.stdout.decode("gbk", errors="replace") - except: - return None - - -def parse(text, name): - if not text or "pv_none_match" in text: - return None - try: - f = text.split("~") - if len(f) < 35: - return None - price = float(f[3]) if f[3] else 0 - prev = float(f[4]) if f[4] else 0 - high = float(f[33]) if len(f) > 33 and f[33] else 0 - low = float(f[34]) if len(f) > 34 and f[34] else 0 - chg = round((price - prev) / prev * 100, 2) if prev else 0 - return {"name": name, "price": price, "change_pct": chg, - "high": high, "low": low} - except: - return None - - -def assess(indices_data): - if not indices_data: - return "unknown", "unknown" - sh = next((i for i in indices_data if i and i["name"] == "上证指数"), None) - sz = next((i for i in indices_data if i and i["name"] == "深证成指"), None) - cyb = next((i for i in indices_data if i and i["name"] == "创业板指"), None) - avg = ((sh or {}).get("change_pct", 0) + (sz or {}).get("change_pct", 0) + - (cyb or {}).get("change_pct", 0)) / 3 - if avg > 1.5: - return "strong_bullish", "整体强势" - elif avg > 0.5: - return "bullish", "偏强" - elif avg > -0.5: - return "neutral", "震荡" - elif avg > -1.5: - return "bearish", "偏弱" - return "strong_bearish", "整体弱势" - - -def main(): - now = datetime.now() - indices_data = [] - for sym, name in INDICES: - raw = fetch(sym) - p = parse(raw, name) - if p: - indices_data.append(p) - - has_data = any(i for i in indices_data if i and i.get("price", 0) > 0) - overall, desc = assess(indices_data) - - # 读莫荷的 macro_risk_state.json 补充风险状态 - risk_state = {} - try: - risk_path = DATA_DIR / "macro_risk_state.json" - if risk_path.exists(): - risk_state = json.loads(risk_path.read_text()) - except: - pass - - context = { - "updated_at": now.strftime("%Y-%m-%d %H:%M:%S"), - "session": "morning" if now.hour < 12 else "midday", - "has_valid_data": has_data, - "indices": {i["name"]: {"price": i["price"], "change_pct": i["change_pct"], - "high": i.get("high", 0), "low": i.get("low", 0)} - for i in indices_data if i}, - "structure": {"overall": overall, "description": desc}, - "risk_level": risk_state.get("level", "none"), - "risk_reason": risk_state.get("reason", ""), - } - - # 写入DB - try: - conn = sqlite3.connect(str(DB_PATH)) - conn.execute('''INSERT INTO macro_context_log - (data_timestamp, session, has_valid_data, indices, structure, - key_sectors, top_gainers, top_losers, sector_up_ratio, sector_mood) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', - (context["updated_at"], context["session"], - 1 if has_data else 0, - json.dumps(context["indices"], ensure_ascii=False), - json.dumps(context["structure"], ensure_ascii=False), - "[]", "[]", "[]", 0, overall)) - conn.commit() - conn.close() - except: - pass - - # 写入 macro_context.json(兼容旧读取方) - try: - DATA_DIR.mkdir(parents=True, exist_ok=True) - (DATA_DIR / "macro_context.json").write_text( - json.dumps(context, ensure_ascii=False, indent=2)) - except: - pass - - if has_data: - idx_parts = [f"{i['name']}{'▲' if i['change_pct']>0 else '▼'}{i['change_pct']:+.2f}%" - for i in indices_data[:4] if i] - print(f"【宏观指数】{now.strftime('%H:%M')} | {desc}") - print(" | ".join(idx_parts)) - print(f"评估: {'整体强势' if overall=='strong_bullish' else '偏强' if overall=='bullish' else '震荡' if overall=='neutral' else '偏弱' if overall=='bearish' else '整体弱势'}") - if risk_state.get("level") == "high": - print(f"🔴 宏观风险: {risk_state.get('reason','')}") - else: - print("【宏观指数】数据不可用(非交易时段或行情未更新)") - - -if __name__ == "__main__": - main()