修复翻倍/目标位平仓把备注写进平仓时间:纠正 SQL 参数顺序并自动对调历史坏数据。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-09-16 05:48:43 +08:00
parent a38a89e274
commit bd4adc9eca
3 changed files with 70 additions and 5 deletions
+4 -4
View File
@@ -353,7 +353,10 @@ def close_option_by_bid1(
allocated += recv
pnl = round(recv - paid, 4)
note_sql = ""
params: list[Any] = [px, recv, pnl, oid or None]
from lib.options.options_time_lib import options_app_now_str
# 占位顺序必须与 SQL 一致: close_quote/recv/pnl/ord/closed_at/[signal_note]/id
params: list[Any] = [px, recv, pnl, oid or None, options_app_now_str()]
if signal_note and i == len(open_rows) - 1:
note_sql = """,
signal_note = CASE
@@ -361,9 +364,6 @@ def close_option_by_bid1(
ELSE signal_note
END"""
params.append(signal_note)
from lib.options.options_time_lib import options_app_now_str
params.append(options_app_now_str())
params.append(int(row["id"]))
conn.execute(
f"""
+6 -1
View File
@@ -715,9 +715,13 @@ def ensure_local_review_synced(
backfill_exchange_pnl: bool = True,
) -> dict[str, Any]:
"""列表/统计前轻量刷新本地源;有交易所时先用历史仓位盈亏覆盖本地再导入复盘."""
from lib.options.options_time_lib import migrate_options_utc_wall_clock_to_app
from lib.options.options_time_lib import (
migrate_options_utc_wall_clock_to_app,
repair_swapped_closed_at_signal_note,
)
ts_migrate = migrate_options_utc_wall_clock_to_app(conn)
note_swap = repair_swapped_closed_at_signal_note(conn)
if backfill_exchange_pnl and ex is not None:
try:
from lib.exchange.okx_options_lib import fetch_all_option_positions_history
@@ -739,6 +743,7 @@ def ensure_local_review_synced(
except Exception:
out["repaired_usdt"] = 0
out["ts_migrate"] = ts_migrate
out["note_swap"] = note_swap
return out
+60
View File
@@ -13,6 +13,7 @@ _APP_TZ = ZoneInfo(
or "Asia/Shanghai"
)
_MIGRATE_FLAG = "options_ts_utc_wall_to_app_done"
_SWAP_REPAIR_FLAG = "options_closed_at_note_swap_done"
def options_app_tz() -> ZoneInfo:
@@ -119,3 +120,62 @@ def migrate_options_utc_wall_clock_to_app(conn: sqlite3.Connection) -> dict[str,
set_sync_state(conn, _MIGRATE_FLAG, "1")
return {"skipped": 0, "trades": trades, "review": review, "hidden": hidden}
def repair_swapped_closed_at_signal_note(conn: sqlite3.Connection) -> dict[str, int]:
"""修复 close_option_by_bid1 曾把 signal_note 写入 closed_at 的坏行.
典型表现: closed_at='翻倍出场'/'目标位平仓', signal_note 反而是时间戳.
幂等:同步状态 options_closed_at_note_swap_done=1 后仍扫描可修行(新坏行可再修).
"""
from lib.options.options_review_db import init_options_review_tables
from lib.options.options_review_lib import set_sync_state
init_options_review_tables(conn)
trades_fixed = 0
review_fixed = 0
try:
from lib.options.options_db import init_options_tables
init_options_tables(conn)
rows = conn.execute(
"""
SELECT id, closed_at, signal_note
FROM options_trades
WHERE status = 'closed'
AND closed_at IS NOT NULL
AND TRIM(closed_at) != ''
"""
).fetchall()
for row in rows:
closed = str(row["closed_at"] or "").strip()
note = str(row["signal_note"] or "").strip()
if options_wall_clock_to_ms(closed) is not None:
continue
if options_wall_clock_to_ms(note) is None:
continue
conn.execute(
"""
UPDATE options_trades
SET closed_at = ?, signal_note = ?
WHERE id = ?
""",
(note, closed, int(row["id"])),
)
trades_fixed += 1
hk = f"local_opt:{int(row['id'])}"
cur = conn.execute(
"""
UPDATE options_review_trades
SET closed_at = ?
WHERE history_key = ?
AND (closed_at IS NULL OR TRIM(closed_at) = '' OR closed_at = ?)
""",
(note, hk, closed),
)
review_fixed += int(cur.rowcount or 0)
except Exception:
pass
set_sync_state(conn, _SWAP_REPAIR_FLAG, "1")
return {"trades": trades_fixed, "review": review_fixed}