feat: macro_context/market数据全部DB优先,JSON回退

- 建 macro_context_log 表,macro_context_collector.py 双写
- strategy_lifecycle.py load_macro_context() 优先DB
- strategy_tree.py detect_scenario() 优先DB
- stale_push_wlin.py load_macro_line() 优先DB
- xiaoguo_signal_consumer.py 大盘判断优先DB
- stock_profile.py load_macro() 优先DB
- system_audit.py 管道审计改查DB market_snapshots
- JSON保留作fallback,确保过渡期不中断
This commit is contained in:
知微
2026-06-24 22:34:08 +08:00
parent 843012e045
commit 39ff4d95f7
8 changed files with 132 additions and 39 deletions
Binary file not shown.
Binary file not shown.
+22
View File
@@ -111,6 +111,28 @@ NON_BUY_SIGNALS = ["观望", "弱势持有", "深套持有"]
def load_macro_line():
"""加载大盘和市场的简要描述"""
parts = []
try:
# 优先 DB
import sqlite3
db = sqlite3.connect("/home/hmo/MoFin/data/mofin.db")
row = db.execute(
"SELECT structure FROM macro_context_log "
"WHERE has_valid_data=1 ORDER BY created_at DESC LIMIT 1"
).fetchone()
db.close()
if row and row[0]:
m = json.loads(row[0])
else:
raise ValueError("no db data")
overall = m.get("overall", "neutral")
desc = m.get("description", "")
if "bearish" in overall:
parts.append("大盘偏弱")
elif overall == "bullish":
parts.append("大盘偏强")
elif desc:
parts.append(f"大盘{desc}")
except Exception:
try:
with open(MACRO_CTX) as f:
m = json.load(f).get("structure", {})
+24 -2
View File
@@ -74,8 +74,30 @@ def quick_assess(quote):
score = 0
reasons = []
# 大盘环境(简化:交易日9:30-15:00且在涨
# 引用 macro_context.json 中的大盘方向
# 大盘环境,从DB读(回退JSON
try:
import sqlite3
conn = sqlite3.connect(str(DB_PATH))
row = conn.execute(
"SELECT indices FROM macro_context_log WHERE has_valid_data=1 ORDER BY created_at DESC LIMIT 1"
).fetchone()
conn.close()
if row and row[0]:
mc = json.loads(row[0])
else:
raise ValueError
sh = 0
for k, v in mc.items():
if "上证" in k:
sh = v.get("change_pct", 0)
break
if sh > 0.5:
score += 1
reasons.append(f"大盘+{sh:.1f}%偏强")
elif sh < -0.5:
score -= 1
reasons.append(f"大盘{sh:.1f}%偏弱")
except Exception:
try:
mc = json.loads((DATA / "macro_context.json").read_text())
sh = mc.get("shanghai", {}).get("change_pct", 0)
+15 -1
View File
@@ -119,7 +119,21 @@ def load_mtf_cache() -> dict:
def load_macro() -> dict:
"""加载宏观上下文"""
"""加载宏观上下文,优先DB"""
try:
import sqlite3
conn = sqlite3.connect(os.path.join(DATA_DIR, "mofin.db"))
row = conn.execute(
"SELECT indices, structure, key_sectors FROM macro_context_log "
"WHERE has_valid_data=1 ORDER BY created_at DESC LIMIT 1"
).fetchone()
conn.close()
if row:
return {"indices": json.loads(row[0] or "{}"),
"structure": json.loads(row[1] or "{}"),
"key_sectors": json.loads(row[2] or "[]")}
except:
pass
try:
with open(MACRO_PATH) as f:
return json.load(f)
+20 -3
View File
@@ -286,12 +286,31 @@ def compute_sector_adjustment(code, market_ctx, stock_sector_map):
def load_macro_context():
"""读取宏观上下文,返回 (bias, desc)bias 取 0.8/1.0/1.1 分别对应 bearish/neutral/bullish"""
"""读取宏观上下文,返回 (bias, desc)优先 DB,回退 JSON"""
try:
import sqlite3
from pathlib import Path
conn = sqlite3.connect(str(Path(__file__).parent.parent / "data" / "mofin.db"))
row = conn.execute(
"SELECT indices, structure FROM macro_context_log "
"WHERE has_valid_data=1 ORDER BY created_at DESC LIMIT 1"
).fetchone()
conn.close()
if row:
indices = json.loads(row[0]) if row[0] else {}
structure = json.loads(row[1]) if row[1] else {}
overall = structure.get("overall", "neutral")
desc = structure.get("description", "")
else:
raise ValueError("no db data")
except Exception:
try:
with open(MACRO_CONTEXT_PATH) as f:
ctx = json.load(f)
overall = ctx.get("structure", {}).get("overall", "neutral")
desc = ctx.get("structure", {}).get("description", "")
except Exception:
return 1.0, "宏观未加载"
if "bearish" in overall:
return 0.8, f"宏观{desc}"
elif overall == "bullish":
@@ -300,8 +319,6 @@ def load_macro_context():
return 1.1, f"宏观{desc}"
else:
return 1.0, f"宏观{desc}"
except Exception:
return 1.0, "宏观未加载"
def batch_fetch_prices(codes):
+19 -4
View File
@@ -69,16 +69,31 @@ def detect_scenario():
scenario_id = "weak_consolidation" # 默认
confidence = 0.5
try:
# 优先 DB
import sqlite3
from pathlib import Path
db = sqlite3.connect(str(Path(__file__).parent / "data" / "mofin.db"))
mrow = db.execute(
"SELECT indices, structure, sector_mood FROM macro_context_log "
"WHERE has_valid_data=1 ORDER BY created_at DESC LIMIT 1"
).fetchone()
db.close()
if mrow:
structure = json.loads(mrow[1]) if mrow[1] else {}
overall = structure.get("overall", "").lower()
mood = (mrow[2] or "").lower() if len(mrow) > 2 else ""
else:
raise ValueError("no db data")
except Exception:
try:
macro = json.load(open(MACRO_PATH))
market = json.load(open(MARKET_PATH))
except Exception:
return {"id": scenario_id, "label": "默认-弱势震荡", "confidence": 0.3, "portfolio_action": "观望"}
mood = market.get("mood", "").lower()
# Try to get trend from macro_context
structure = macro.get("structure", {})
overall = structure.get("overall", "").lower()
except Exception:
return {"id": "weak_consolidation", "label": "默认-弱势震荡", "confidence": 0.3, "portfolio_action": "观望"}
trend_desc = structure.get("description", "").lower()
# Check for sharp decline
+11 -8
View File
@@ -128,16 +128,19 @@ def audit_portfolio(conn):
# ── 6. 数据管道审计 ──
def audit_pipeline():
# 检查market.json是否今天更新
# 检查DB市场数据是否今天更新
try:
mkt = json.loads((DATA_DIR / "market.json").read_text())
mkt_ts = mkt.get("timestamp", "")
if mkt_ts[:10] == datetime.now().strftime("%Y-%m-%d"):
log_ok("数据管道", f"市场数据今天更新({mkt_ts})")
conn = sqlite3.connect(str(DATA_DIR / "mofin.db"))
row = conn.execute(
"SELECT created_at FROM market_snapshots ORDER BY created_at DESC LIMIT 1"
).fetchone()
conn.close()
if row and row[0][:10] == datetime.now().strftime("%Y-%m-%d"):
log_ok("数据管道", f"市场数据今天更新({row[0]})")
else:
log_issue("数据管道", "HIGH", f"市场数据未更新, 最后{mkt_ts}")
except:
log_issue("数据管道", "HIGH", "market.json缺失")
log_issue("数据管道", "HIGH", f"市场数据未更新(DB), 最后{row[0] if row else '无数据'}")
except Exception as e:
log_issue("数据管道", "HIGH", f"DB检查失败: {e}")
# ── 7. 系统服务 ──