fix(audit): candidates UPSERT保计算列+market_scanner INSERT对齐表结构+拆除sync_decisions_to_db地雷

举一反三审计结果:
- accumulation_scanner: INSERT OR REPLACE整行替换,promoted=1的候选被重置score/promoted/log
  → ON CONFLICT DO UPDATE只更新扫描器自有列(cron活跃,今日必修)
- market_scanner: INSERT引用表中不存在的列(price/score/entry_low等),实测必失败
  → 对齐真实schema+同款UPSERT(孤儿脚本顺手修)
- sync_decisions_to_db.py: 全表DELETE再从已不存在的decisions.json重建,地雷→归档
This commit is contained in:
hmo
2026-07-23 14:23:06 +08:00
parent 12f7f87a2e
commit 6eab2148eb
3 changed files with 20 additions and 10 deletions
@@ -228,10 +228,15 @@ def main():
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)
+12 -7
View File
@@ -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()