Fix false options close sync, restore bar layout, and show open premium in history.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -176,6 +176,8 @@ def sync_open_options_trades(
|
||||
closed_at = datetime.fromtimestamp(int(exp_ms) / 1000, tz=timezone.utc).strftime(
|
||||
"%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
else:
|
||||
continue
|
||||
|
||||
conn.execute(
|
||||
"""
|
||||
@@ -207,6 +209,57 @@ def sync_open_options_trades(
|
||||
return updated
|
||||
|
||||
|
||||
def reconcile_live_open_trades(
|
||||
conn: sqlite3.Connection,
|
||||
*,
|
||||
live_inst_ids: set[str],
|
||||
) -> int:
|
||||
"""交易所有持仓但本地误标 closed 时恢复为 open."""
|
||||
fixed = 0
|
||||
for inst_id in live_inst_ids:
|
||||
if not inst_id:
|
||||
continue
|
||||
open_row = conn.execute(
|
||||
"SELECT id FROM options_trades WHERE inst_id = ? AND status = 'open' LIMIT 1",
|
||||
(inst_id,),
|
||||
).fetchone()
|
||||
if open_row:
|
||||
continue
|
||||
row = conn.execute(
|
||||
"""
|
||||
SELECT id, close_ord_id, realized_pnl
|
||||
FROM options_trades
|
||||
WHERE inst_id = ? AND status = 'closed'
|
||||
ORDER BY id DESC LIMIT 1
|
||||
""",
|
||||
(inst_id,),
|
||||
).fetchone()
|
||||
if not row:
|
||||
continue
|
||||
if row["close_ord_id"]:
|
||||
continue
|
||||
if row["realized_pnl"] is not None:
|
||||
continue
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE options_trades
|
||||
SET status = 'open',
|
||||
close_quote = NULL,
|
||||
premium_received = NULL,
|
||||
realized_pnl = NULL,
|
||||
closed_at = NULL,
|
||||
signal_note = CASE
|
||||
WHEN signal_note = '到期结算' THEN NULL
|
||||
ELSE signal_note
|
||||
END
|
||||
WHERE id = ?
|
||||
""",
|
||||
(int(row["id"]),),
|
||||
)
|
||||
fixed += 1
|
||||
return fixed
|
||||
|
||||
|
||||
def options_monitor_loop(
|
||||
*,
|
||||
enabled: bool,
|
||||
|
||||
@@ -147,7 +147,7 @@ def _sync_options_trades(cfg: dict[str, Any]) -> None:
|
||||
if ex is None:
|
||||
return
|
||||
from lib.exchange.okx_options_lib import fetch_option_position_history
|
||||
from lib.options.options_monitor_lib import sync_open_options_trades
|
||||
from lib.options.options_monitor_lib import reconcile_live_open_trades, sync_open_options_trades
|
||||
|
||||
raw = cfg["fetch_option_positions"](ex)
|
||||
live_ids = {str(p.get("instId") or "") for p in raw if str(p.get("instId") or "")}
|
||||
@@ -158,6 +158,7 @@ def _sync_options_trades(cfg: dict[str, Any]) -> None:
|
||||
conn = cfg["get_db"]()
|
||||
try:
|
||||
init_options_tables(conn)
|
||||
reconcile_live_open_trades(conn, live_inst_ids=live_ids)
|
||||
sync_open_options_trades(conn, live_inst_ids=live_ids, fetch_history_fn=_hist)
|
||||
conn.commit()
|
||||
finally:
|
||||
@@ -715,13 +716,14 @@ def _start_monitor_thread(app: Flask, cfg: dict[str, Any]) -> None:
|
||||
|
||||
def _sync(conn):
|
||||
from lib.exchange.okx_options_lib import fetch_option_position_history
|
||||
from lib.options.options_monitor_lib import sync_open_options_trades
|
||||
from lib.options.options_monitor_lib import reconcile_live_open_trades, sync_open_options_trades
|
||||
|
||||
ex = cfg.get("exchange_options")
|
||||
if ex is None:
|
||||
return 0
|
||||
raw = cfg["fetch_option_positions"](ex)
|
||||
live_ids = {str(p.get("instId") or "") for p in raw if str(p.get("instId") or "")}
|
||||
reconcile_live_open_trades(conn, live_inst_ids=live_ids)
|
||||
return sync_open_options_trades(
|
||||
conn,
|
||||
live_inst_ids=live_ids,
|
||||
|
||||
@@ -137,4 +137,4 @@
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/options_expiry_countdown.js?v=1"></script>
|
||||
<script src="/static/options_panel.js?v=15"></script>
|
||||
<script src="/static/options_panel.js?v=16"></script>
|
||||
|
||||
Reference in New Issue
Block a user