diff --git a/deploy/profile-scripts/sync_decisions_to_db.py b/archive/20260723-landmine/sync_decisions_to_db.py similarity index 100% rename from deploy/profile-scripts/sync_decisions_to_db.py rename to archive/20260723-landmine/sync_decisions_to_db.py diff --git a/deploy/profile-scripts/accumulation_scanner.py b/deploy/profile-scripts/accumulation_scanner.py index 0600e9c5..93606cf4 100644 --- a/deploy/profile-scripts/accumulation_scanner.py +++ b/deploy/profile-scripts/accumulation_scanner.py @@ -227,11 +227,16 @@ def main(): ).fetchone() if exists: continue - + + # UPSERT:只更新扫描器自有列,保留 score_*/pass_*/promoted/log/zhiwei_* 等计算列 + # (原 INSERT OR REPLACE 会把 promoted=1 的行整行替换,计算列全部清零——2026-07-23 审计发现) conn.execute( - "INSERT OR REPLACE INTO candidates (code, name, sector, reason, " + "INSERT INTO candidates (code, name, sector, reason, " "entry_range, stop_loss, target, created_at) " - "VALUES (?,?,?,?,?,?,?,datetime('now','localtime'))", + "VALUES (?,?,?,?,?,?,?,datetime('now','localtime')) " + "ON CONFLICT(code) DO UPDATE SET " + "name=excluded.name, sector=excluded.sector, reason=excluded.reason, " + "entry_range=excluded.entry_range, stop_loss=excluded.stop_loss, target=excluded.target", (code, name, "accumulation", f"主力建仓特征({reasons}) 评分{score}/7", f"{entry_low}~{entry_high}", sl, tp) diff --git a/deploy/profile-scripts/market_scanner.py b/deploy/profile-scripts/market_scanner.py index 2bdb6b9d..62f8935d 100644 --- a/deploy/profile-scripts/market_scanner.py +++ b/deploy/profile-scripts/market_scanner.py @@ -159,17 +159,22 @@ def scan_candidates(): new_candidates.append(candidate) print(f" ✅ {code} {name} 价{price} (+{chg:.1f}%) 评分{score}", flush=True) - # 4. 写入candidates表 + # 4. 写入candidates表(对齐真实表结构:表无 price/change_pct/score/entry_low/entry_high/ + # take_profit/source 列,原 INSERT 必失败——2026-07-23 审计实测确认。 + # UPSERT 只更新扫描器自有列,保留 score_*/pass_*/promoted/log 等计算列) if new_candidates: conn = get_conn() for c in new_candidates: conn.execute( - "INSERT OR REPLACE INTO candidates (code, name, price, change_pct, score, " - "entry_low, entry_high, stop_loss, take_profit, source, sector, reason, created_at) " - "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,datetime('now','localtime'))", - (c["code"], c["name"], c["price"], c["change_pct"], c["score"], - c["entry_low"], c["entry_high"], c["stop_loss"], c["take_profit"], - c["source"], c["sector"], c["reason"]) + "INSERT INTO candidates (code, name, sector, reason, " + "entry_range, stop_loss, target, created_at) " + "VALUES (?,?,?,?,?,?,?,datetime('now','localtime')) " + "ON CONFLICT(code) DO UPDATE SET " + "name=excluded.name, sector=excluded.sector, reason=excluded.reason, " + "entry_range=excluded.entry_range, stop_loss=excluded.stop_loss, target=excluded.target", + (c["code"], c["name"], c.get("sector") or c.get("source", "market_scanner"), + f"{c['reason']} 价{c['price']}(+{c['change_pct']:.1f}%) 评分{c['score']}", + f"{c['entry_low']}~{c['entry_high']}", c["stop_loss"], c["take_profit"]) ) conn.commit() conn.close()