Files
MoFin/scripts/check_97_bug.py
T
hmo 7b26c373d1 fix(reassess): stale_detector timeout 60->240s + batch cap 5/run + GATE_ZONE_SANITY
Three issues from zhiwei's strategy report:

1. '37 reassess all timed out (subprocess 60s)': real cause is per-call LLM
   latency exceeding the 60s per-subprocess limit during the key5-dead/
   gateway-unstable window. NOT 'no concurrency control' as reported (60s
   is per stock, not for the batch). Fixes: per-call timeout 60->240s
   (LLM cold-start is 20-100s), and cap AUTO_REASSESS batch to 5 stocks
   per run with remainder continuing next run (was unbounded serial calls
   that also blew the 120s cron script window).

2. '15 stocks entry-zone center wrongly 97.0': quality gates had no
   zone-sanity-vs-price check, so bad data (bad quote or LLM template
   output) could be written freely. New GATE_ZONE_SANITY (CRITICAL):
   zone center must be within 0.3x-3x of current price. Verified: rejects
   the exact 97-center-vs-5.69-price corruption, passes legit zones.

3. 'reassess overwrites manual SQL fixes': true by design; with
   GATE_ZONE_SANITY at write time, reassess can no longer overwrite good
   values with garbage - invalid writes get rejected + flagged instead.
2026-07-20 22:05:00 +08:00

37 lines
1.9 KiB
Python

import sqlite3
conn = sqlite3.connect('/home/hmo/MoFin/data/mofin.db')
conn.row_factory = sqlite3.Row
# 1. 找曾被 zhiwei 修过的 15 只(她提到的几只)当前值
codes = ['000711', '603766', '600617', '688271']
print('=== holding_strategies 当前值(她修过的几只)===')
for code in codes:
r = conn.execute(
"SELECT code, name, entry_low, entry_high, stop_loss, take_profit, strategy_type, "
"quality_check, created_at, updated_at FROM holding_strategies WHERE code=? AND status='active'",
(code,)).fetchone()
if r:
c = (r['entry_low'] + r['entry_high']) / 2 if r['entry_low'] and r['entry_high'] else 0
print(f" {r['code']} {r['name']}: 区{r['entry_low']}~{r['entry_high']} 中心{c:.2f} | type={r['strategy_type']} | created={r['created_at']} updated={r['updated_at']}")
# 2. 找 candidates 里这些股票的评分/买入区(看是不是 promote 写进来的)
print()
print('=== candidates 对应记录 ===')
for code in codes:
r = conn.execute(
"SELECT code, name, score, entry_low, entry_high, stop_loss, take_profit, promoted, created_at "
"FROM candidates WHERE code=?", (code,)).fetchone()
if r:
print(f" {r['code']} {r['name']}: score={r['score']}{r['entry_low']}~{r['entry_high']} promoted={r['promoted']} created={r['created_at']}")
# 3. 还有谁可能是 97 中心:找 entry 中心在 90~105 的活跃自选
print()
print('=== 当前活跃自选里中心 90~105 的(可能还有漏网的)===')
rows = conn.execute(
"SELECT code, name, entry_low, entry_high FROM holding_strategies "
"WHERE status='active' AND decision_type='自选策略' AND entry_low > 0").fetchall()
for r in rows:
c = (r['entry_low'] + r['entry_high']) / 2
if 90 <= c <= 105:
print(f" {r['code']} {r['name']}: 区{r['entry_low']}~{r['entry_high']} 中心{c:.2f}")
conn.close()