feat: data-layering 第二批消费层读DB(divergence/staleness/accumulation/collect_eval/strategy_review/mo_provider/multi_timeframe/chip_factors)

This commit is contained in:
xxm
2026-08-26 21:25:32 +08:00
parent bd1ef0c9a4
commit a819033175
8 changed files with 337 additions and 337 deletions
+35 -59
View File
@@ -14,7 +14,7 @@ divergence_detector.py — 跨市场背离监测器(no_agent)
- 状态文件 macro_divergence_state.json
- no_agent: 有信号才出声
"""
import sys, json, re, datetime, os, requests
import sys, json, datetime, os
from pathlib import Path
# ── 消息通道统一路由(broadcast/xmpp by delivery) ──
@@ -47,69 +47,45 @@ DIVERGENCE_MODERATE = 3.0 # >3% → moderate信号
STREAK_DAYS = 3 # 连涨/连跌3天 → 信号
def fetch_indices():
"""获取所有指数实时数据(直接调用新浪API,mo_data不支持指数代码"""
import requests
sina_map = {
"sh000001": "s_sh000001",
"sz399001": "s_sz399001",
"sz399006": "s_sz399006",
"sh000688": "s_sh000688",
"sh000016": "s_sh000016",
"sh000300": "s_sh000300",
"hkHSI": "rt_hkHSI",
"hkHSCEI": "rt_hkHSCEI",
"""获取所有指数数据(读 DB stock_daily 收盘价,2026-08-26 分层铁律:消费层不直连新浪API"""
import sqlite3
# 指数代码 → 中文名(stock_daily 表已有 sh000001/sz399001/sz399006/sh000688
index_map = {
"sh000001": "上证指数",
"sz399001": "深证成指",
"sz399006": "创业板指",
"sh000688": "科创50",
"sh000016": "上证50",
"sh000300": "沪深300",
}
url = "http://hq.sinajs.cn/list=" + ",".join(sina_map.values())
headers = {"Referer": "https://finance.sina.com.cn"}
indices = {}
try:
r = requests.get(url, headers=headers, timeout=10)
r.encoding = "gbk"
conn = sqlite3.connect(str(DB_PATH), timeout=5)
for sym, cname in index_map.items():
rows = conn.execute(
"SELECT date, close, high, low FROM stock_daily "
"WHERE code=? ORDER BY date DESC LIMIT 2", (sym,)
).fetchall()
if not rows:
continue
latest = rows[0]
prev_close = rows[1][1] if len(rows) > 1 else latest[1]
price = latest[1] or 0
change_pct = (price - prev_close) / prev_close * 100 if prev_close else 0
indices[sym] = {
"name": cname,
"price": price,
"close": price,
"change_pct": round(change_pct, 2),
"high": latest[2] or 0,
"low": latest[3] or 0,
"timestamp": latest[0],
}
conn.close()
except Exception as e:
print(f"[DIVERGE] 采集失败: {e}", file=sys.stderr)
return {}
indices = {}
for line in r.text.strip().split("\n"):
line = line.strip()
if not line:
continue
# Parse: var hq_str_XXXX="fields,...";
try:
var_name = line.split('"')[0].rsplit("_", 1)[-1].rstrip("=")
fields = line.split('"')[1].split(",")
except (IndexError, ValueError):
continue
# Find the symbol
sym = None
for s, sn in sina_map.items():
if sn.endswith(var_name):
sym = s
break
if not sym:
continue
if sym.startswith("hk"):
# HK: name,price,open,high,low,prev_close,change,change_pct,...
name = fields[1]
price = float(fields[2]) if fields[2] else 0
change_pct = float(fields[8]) if len(fields) > 8 and fields[8] else 0
else:
# A-share: name,price,change,change_pct,...
name = fields[0]
price = float(fields[1]) if fields[1] else 0
change_pct = float(fields[3]) if len(fields) > 3 and fields[3] else 0
indices[sym] = {
"name": name,
"price": price,
"close": 0,
"change_pct": change_pct,
"high": 0,
"low": 0,
"timestamp": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
}
# 港股指数 hkHSI/hkHSCEI 不在 stock_daily,读不到则不返回(中性值,由调用方跳过低检测)
return indices
def load_history():