修复翻倍/目标位平仓把备注写进平仓时间:纠正 SQL 参数顺序并自动对调历史坏数据。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -353,7 +353,10 @@ def close_option_by_bid1(
|
|||||||
allocated += recv
|
allocated += recv
|
||||||
pnl = round(recv - paid, 4)
|
pnl = round(recv - paid, 4)
|
||||||
note_sql = ""
|
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:
|
if signal_note and i == len(open_rows) - 1:
|
||||||
note_sql = """,
|
note_sql = """,
|
||||||
signal_note = CASE
|
signal_note = CASE
|
||||||
@@ -361,9 +364,6 @@ def close_option_by_bid1(
|
|||||||
ELSE signal_note
|
ELSE signal_note
|
||||||
END"""
|
END"""
|
||||||
params.append(signal_note)
|
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"]))
|
params.append(int(row["id"]))
|
||||||
conn.execute(
|
conn.execute(
|
||||||
f"""
|
f"""
|
||||||
|
|||||||
@@ -715,9 +715,13 @@ def ensure_local_review_synced(
|
|||||||
backfill_exchange_pnl: bool = True,
|
backfill_exchange_pnl: bool = True,
|
||||||
) -> dict[str, Any]:
|
) -> 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)
|
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:
|
if backfill_exchange_pnl and ex is not None:
|
||||||
try:
|
try:
|
||||||
from lib.exchange.okx_options_lib import fetch_all_option_positions_history
|
from lib.exchange.okx_options_lib import fetch_all_option_positions_history
|
||||||
@@ -739,6 +743,7 @@ def ensure_local_review_synced(
|
|||||||
except Exception:
|
except Exception:
|
||||||
out["repaired_usdt"] = 0
|
out["repaired_usdt"] = 0
|
||||||
out["ts_migrate"] = ts_migrate
|
out["ts_migrate"] = ts_migrate
|
||||||
|
out["note_swap"] = note_swap
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ _APP_TZ = ZoneInfo(
|
|||||||
or "Asia/Shanghai"
|
or "Asia/Shanghai"
|
||||||
)
|
)
|
||||||
_MIGRATE_FLAG = "options_ts_utc_wall_to_app_done"
|
_MIGRATE_FLAG = "options_ts_utc_wall_to_app_done"
|
||||||
|
_SWAP_REPAIR_FLAG = "options_closed_at_note_swap_done"
|
||||||
|
|
||||||
|
|
||||||
def options_app_tz() -> ZoneInfo:
|
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")
|
set_sync_state(conn, _MIGRATE_FLAG, "1")
|
||||||
return {"skipped": 0, "trades": trades, "review": review, "hidden": hidden}
|
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}
|
||||||
|
|||||||
Reference in New Issue
Block a user