refactor: write_holding_strategy改UPSERT,DELETE+INSERT模式退役
- 只写自有列; rr_low/rr_high(recompute_rr拥有)/superseded_at/created_at不在写集→天然保留 - 未来新增计算列自动免疫(老爸: 新增计算列为什么要用delete+insert?不该用update吗?) - 消除DELETE→INSERT崩溃窗口和created_at被重置副作用
This commit is contained in:
+29
-13
@@ -1488,11 +1488,9 @@ def write_holding_strategy(conn, code: str, name: str, data: dict,
|
||||
_old_sig = ''
|
||||
_old_ra = ''
|
||||
_old_action = ''
|
||||
_old_rr_lo = 0
|
||||
_old_rr_hi = 0
|
||||
if True:
|
||||
try:
|
||||
_old = conn.execute("SELECT full_analysis, reassessed_at, tag, timing_signal, action, rr_low, rr_high FROM holding_strategies WHERE code=? ORDER BY id DESC LIMIT 1", (code,)).fetchone()
|
||||
_old = conn.execute("SELECT full_analysis, reassessed_at, tag, timing_signal, action FROM holding_strategies WHERE code=? ORDER BY id DESC LIMIT 1", (code,)).fetchone()
|
||||
if _old:
|
||||
if not _existing_fa:
|
||||
if _old[0]: _existing_fa = _old[0]
|
||||
@@ -1501,8 +1499,6 @@ def write_holding_strategy(conn, code: str, name: str, data: dict,
|
||||
_old_sig = _old[3] or ''
|
||||
_old_ra = _old[1] or ''
|
||||
_old_action = _old[4] or ''
|
||||
_old_rr_lo = _old[5] or 0
|
||||
_old_rr_hi = _old[6] or 0
|
||||
except:
|
||||
pass
|
||||
# ── 信号权威层级(2026-07-22):新鲜(<20h)12维动作级信号,
|
||||
@@ -1550,8 +1546,10 @@ def write_holding_strategy(conn, code: str, name: str, data: dict,
|
||||
|
||||
# ── action 权限保护已在上方信号权威块中统一处理 ──
|
||||
|
||||
# DELETE + INSERT
|
||||
conn.execute("DELETE FROM holding_strategies WHERE code=?", (code,))
|
||||
# ── UPSERT(2026-07-23 老爸:新增计算列不该用DELETE+INSERT,该用UPDATE)──
|
||||
# 只写本函数拥有的列;rr_low/rr_high(recompute_rr拥有)、superseded_at(data_governance
|
||||
# 拥有)、created_at(创建时间)不在写集内 → 天然保留,未来新增计算列自动免疫。
|
||||
# 同时消除 DELETE→INSERT 之间崩溃=行丢失的原子性窗口,以及 created_at 被重置的副作用。
|
||||
conn.execute("""
|
||||
INSERT INTO holding_strategies
|
||||
(code, name, version, price, cost, shares, stop_loss, take_profit,
|
||||
@@ -1562,10 +1560,31 @@ def write_holding_strategy(conn, code: str, name: str, data: dict,
|
||||
avg_price, decision_timestamp, note, quality_check,
|
||||
quality_checked_at, quality_issues_json, position_advice,
|
||||
signal_factors_json, time_horizon, decision_type,
|
||||
full_analysis, reassessed_at, tag, rr_low, rr_high)
|
||||
full_analysis, reassessed_at, tag)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,
|
||||
datetime('now','localtime'),
|
||||
?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
ON CONFLICT(code) DO UPDATE SET
|
||||
name=excluded.name, version=excluded.version, price=excluded.price,
|
||||
cost=excluded.cost, shares=excluded.shares,
|
||||
stop_loss=excluded.stop_loss, take_profit=excluded.take_profit,
|
||||
entry_low=excluded.entry_low, entry_high=excluded.entry_high,
|
||||
currency=excluded.currency, strategy_type=excluded.strategy_type,
|
||||
action=excluded.action, timing_signal=excluded.timing_signal,
|
||||
rr_ratio=excluded.rr_ratio, tech_snapshot=excluded.tech_snapshot,
|
||||
stock_category=excluded.stock_category, sector_context=excluded.sector_context,
|
||||
status=excluded.status, trigger_json=excluded.trigger_json,
|
||||
changelog_json=excluded.changelog_json, source=excluded.source,
|
||||
reason=excluded.reason, updated_at=excluded.updated_at,
|
||||
avg_price=excluded.avg_price, decision_timestamp=excluded.decision_timestamp,
|
||||
note=excluded.note, quality_check=excluded.quality_check,
|
||||
quality_checked_at=excluded.quality_checked_at,
|
||||
quality_issues_json=excluded.quality_issues_json,
|
||||
position_advice=excluded.position_advice,
|
||||
signal_factors_json=excluded.signal_factors_json,
|
||||
time_horizon=excluded.time_horizon, decision_type=excluded.decision_type,
|
||||
full_analysis=excluded.full_analysis, reassessed_at=excluded.reassessed_at,
|
||||
tag=excluded.tag
|
||||
""", (
|
||||
code, name,
|
||||
data.get('version', 1), data.get('price'), data.get('cost'),
|
||||
@@ -1588,13 +1607,10 @@ def write_holding_strategy(conn, code: str, name: str, data: dict,
|
||||
signal_factors_j,
|
||||
data.get('time_horizon', ''),
|
||||
data.get('type', data.get('strategy_type', 'holding')),
|
||||
# 保留full_analysis和reassessed_at
|
||||
# 保留full_analysis和reassessed_at(合并逻辑在上方完成)
|
||||
_existing_fa,
|
||||
_existing_ra,
|
||||
_existing_tag,
|
||||
# rr_low/rr_high: 调用方不提供时保留旧值(防DELETE+INSERT把计算列冲零)
|
||||
data.get('rr_low') or _old_rr_lo,
|
||||
data.get('rr_high') or _old_rr_hi,
|
||||
))
|
||||
conn.commit()
|
||||
# ── 推荐转场:LLM路径新转为 current_recommend → 记入摘要队列(不逐只推送)──
|
||||
|
||||
Reference in New Issue
Block a user