Files
MoFin/scripts/check_db_state.py
T
hmo a40b97f5ca feat(analysis): systematic daily 12-dim LLM analysis for holdings+watchlist
Gap (reported by user via zhiwei): premarket full review updated technical
params but full_analysis (12-dim LLM matrix) was empty for new holdings
and stale for old ones — batch_reassess existed but was never wired into
the daily pipeline and only covered watchlist.

System fix:
- premarket_full_review.py: new Step 1.5 runs batch_reassess --type
  holding --today every trading day 08:10 (force-refresh today's analysis,
  timeout 3600s, result in summary.json)
- batch_reassess.py:
  - coverage: --type holding|watchlist|all (was watchlist-only)
  - staleness: analysis >20h stale gets refreshed (was: skip if any
    analysis exists = forever stale)
  - --today flag: force re-analyze if not reassessed since 04:00 today
  - cash/total read live from portfolio_summary (was hardcoded 321271/
    952879 from weeks ago)
  - HK stock prefix fix (5-digit codes -> hk, was sending sz00700)
- watchlist_12d_backfill.py: wrapper for hermes cron (no args support)
- cron job '批量补全九维分析-一次性' -> '自选12维分析补全-每日午间'
  (daily 12:30 weekdays, covers 109 watchlist stocks missing analysis)

Verified: 300308 got 1920-char 12-dim analysis written to DB at 08:41,
signal=观望, stop/take-profit updated.
2026-07-20 08:48:08 +08:00

25 lines
1.1 KiB
Python

import sqlite3
conn = sqlite3.connect('/home/hmo/MoFin/data/mofin.db')
print('=== portfolio_summary schema ===')
for r in conn.execute("SELECT sql FROM sqlite_master WHERE name='portfolio_summary'"):
print(r[0])
print()
print('=== latest row ===')
cur = conn.execute('SELECT * FROM portfolio_summary ORDER BY id DESC LIMIT 1')
cols = [d[0] for d in cur.description]
row = cur.fetchone()
for c, v in zip(cols, row):
print(f' {c} = {v}')
print()
print('=== decision_type distribution ===')
for r in conn.execute("SELECT decision_type, COUNT(*) FROM holding_strategies WHERE status='active' GROUP BY decision_type"):
print(f' {r[0]}: {r[1]}')
print()
print('=== full_analysis staleness ===')
for r in conn.execute("""
SELECT decision_type,
SUM(CASE WHEN full_analysis IS NULL OR LENGTH(full_analysis)<500 THEN 1 ELSE 0 END) as missing,
SUM(CASE WHEN LENGTH(full_analysis)>=500 THEN 1 ELSE 0 END) as has_fa,
COUNT(*) as total
FROM holding_strategies WHERE status='active' GROUP BY decision_type"""):
print(f' {r[0]}: missing={r[1]} has={r[2]} total={r[3]}')