Prevent duplicate strategy trade snapshots on plan close.

Finalize plans before writing snapshots, dedupe on startup and page load, and add a cleanup script for existing repeated rows.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-08 09:00:51 +08:00
parent ea92160d54
commit e71bfe095c
6 changed files with 355 additions and 11 deletions
+53 -10
View File
@@ -667,6 +667,47 @@ def _trend_plan_trade_exists(conn, plan_id: int) -> bool:
return False
def _bump_session_capital_no_commit(
m, conn, session_date: str, pnl_amount: float
) -> float | None:
"""更新当日资金,不单独 commit(与 _finalize_plan 同一事务)。"""
try:
row = conn.execute(
"SELECT current_capital FROM trading_sessions WHERE session_date = ?",
(session_date,),
).fetchone()
if not row:
start_cap = float(getattr(m, "DAILY_START_CAPITAL", 0) or 0)
if start_cap <= 0:
ensure = getattr(m, "ensure_session", None)
if callable(ensure):
ensured = ensure(conn, session_date)
row = ensured
else:
return None
else:
conn.execute(
"INSERT OR IGNORE INTO trading_sessions "
"(session_date, start_capital, current_capital) VALUES (?,?,?)",
(session_date, start_cap, start_cap),
)
row = conn.execute(
"SELECT current_capital FROM trading_sessions WHERE session_date = ?",
(session_date,),
).fetchone()
if not row:
return None
new_capital = float(row["current_capital"]) + float(pnl_amount)
conn.execute(
"UPDATE trading_sessions SET current_capital = ?, updated_at = CURRENT_TIMESTAMP "
"WHERE session_date = ?",
(round(new_capital, 4), session_date),
)
return round(new_capital, 4)
except Exception:
return None
def _finalize_plan(cfg: dict, conn, row, result_label: str, exit_price: float) -> None:
m = _m(cfg)
plan_id = int(row["id"])
@@ -700,6 +741,13 @@ def _finalize_plan(cfg: dict, conn, row, result_label: str, exit_price: float) -
except (TypeError, ValueError):
pass
planned_rr = m.calc_rr_ratio(direction, avg_e, float(row["stop_loss"]), float(row["take_profit"]))
st = _plan_stop_status(result_label)
cur = conn.execute(
"UPDATE trend_pullback_plans SET status=?, message=? WHERE id=? AND status='active'",
(st, res, plan_id),
)
if not getattr(cur, "rowcount", 0):
return
try:
from strategy_snapshot_lib import save_trend_plan_snapshot
@@ -710,6 +758,7 @@ def _finalize_plan(cfg: dict, conn, row, result_label: str, exit_price: float) -
result_label=result_label,
exit_price=float(exit_price) if exit_price is not None else None,
pnl_amount=float(pnl_amount) if pnl_amount is not None else None,
closed_at=closed_at,
)
except Exception:
pass
@@ -717,9 +766,12 @@ def _finalize_plan(cfg: dict, conn, row, result_label: str, exit_price: float) -
cancel_symbol_orders(cfg, ex_sym)
except Exception:
pass
session_capital = None
if not _trend_plan_trade_exists(conn, plan_id):
session_date = row["session_date"] or m.get_trading_day()
session_capital = m.update_session_capital(conn, session_date, pnl_amount)
session_capital = _bump_session_capital_no_commit(
m, conn, session_date, pnl_amount
)
_call_insert_trade_record(
m,
plan_id,
@@ -746,15 +798,6 @@ def _finalize_plan(cfg: dict, conn, row, result_label: str, exit_price: float) -
entry_reason=ENTRY_REASON_TREND_PULLBACK,
),
)
else:
session_capital = None
st = _plan_stop_status(result_label)
cur = conn.execute(
"UPDATE trend_pullback_plans SET status=?, message=? WHERE id=? AND status='active'",
(st, res, plan_id),
)
if not getattr(cur, "rowcount", 0):
return
conn.commit()
try:
from strategy_wechat_notify import notify_trend_plan_ended