Load options review from local records with compact journal UI.

Drop exchange sync for the review page, auto-import closed local options and hedge plans, and match contract-style multi-timeframe upload styling with smaller fonts.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-17 09:54:35 +08:00
parent c6142dc246
commit 48afc8ebe3
6 changed files with 194 additions and 102 deletions
+76 -4
View File
@@ -133,6 +133,69 @@ def upsert_option_history_row(conn: sqlite3.Connection, row: dict[str, Any]) ->
return "inserted"
def sync_options_from_local_trades(conn: sqlite3.Connection) -> dict[str, Any]:
"""从本地 options_trades 已平仓记录导入复盘快照(不访问交易所)."""
init_options_review_tables(conn)
from lib.options.options_db import init_options_tables
init_options_tables(conn)
rows = conn.execute(
"""
SELECT id, inst_id, underlying, opt_type, strike, exp_time, sheets,
open_quote, close_quote, premium_paid, realized_pnl,
created_at, closed_at, signal_note, status
FROM options_trades
WHERE status = 'closed'
ORDER BY id DESC
LIMIT 500
"""
).fetchall()
inserted = updated = skipped = 0
for r in rows:
trade_id = int(r["id"])
history_key = f"local_opt:{trade_id}"
pnl = _safe_float(r["realized_pnl"])
opened_at = r["created_at"]
closed_at = r["closed_at"]
action = upsert_option_history_row(
conn,
{
"history_key": history_key,
"pos_id": f"local:{trade_id}",
"inst_id": r["inst_id"],
"underlying": r["underlying"],
"opt_type": r["opt_type"],
"strike": r["strike"],
"exp_time": r["exp_time"],
"sheets": r["sheets"],
"open_avg_px": r["open_quote"],
"close_avg_px": r["close_quote"],
"premium_paid": r["premium_paid"],
"realized_pnl": pnl,
"created_at": opened_at,
"closed_at": closed_at,
"status_label": "已平",
},
)
if action == "inserted":
inserted += 1
elif action == "updated":
updated += 1
else:
skipped += 1
set_sync_state(conn, "options_last_sync_at", _now_str())
set_sync_state(conn, "options_last_count", str(len(rows)))
set_sync_state(conn, "options_sync_source", "local")
return {
"ok": True,
"source": "local",
"fetched": len(rows),
"inserted": inserted,
"updated": updated,
"skipped": skipped,
}
def sync_options_from_exchange(
conn: sqlite3.Connection,
ex: Any,
@@ -141,7 +204,7 @@ def sync_options_from_exchange(
fetch_fn: Optional[Callable[..., list[dict[str, Any]]]] = None,
format_fn: Optional[Callable[..., dict[str, Any]]] = None,
) -> dict[str, Any]:
"""从 OKX positions-history 导入已全平期权仓位."""
"""从 OKX positions-history 导入已全平期权仓位(可选,默认不用)."""
init_options_review_tables(conn)
from lib.exchange.okx_options_lib import (
fetch_all_option_positions_history,
@@ -171,8 +234,10 @@ def sync_options_from_exchange(
skipped += 1
set_sync_state(conn, "options_last_sync_at", _now_str())
set_sync_state(conn, "options_last_count", str(len(raw_rows)))
set_sync_state(conn, "options_sync_source", "exchange")
return {
"ok": True,
"source": "exchange",
"fetched": len(raw_rows),
"inserted": inserted,
"updated": updated,
@@ -326,24 +391,31 @@ def sync_hedge_plans_closed(conn: sqlite3.Connection) -> dict[str, Any]:
def sync_all_review_sources(
conn: sqlite3.Connection,
ex: Any | None,
ex: Any | None = None,
*,
options_limit: int = 500,
from_exchange: bool = False,
fetch_fn: Optional[Callable[..., list[dict[str, Any]]]] = None,
format_fn: Optional[Callable[..., dict[str, Any]]] = None,
) -> dict[str, Any]:
"""默认只读本地 options_trades + 已结束对冲计划;不访问交易所."""
init_options_review_tables(conn)
out: dict[str, Any] = {"ok": True, "options": None, "hedge": None}
if ex is not None:
if from_exchange and ex is not None:
out["options"] = sync_options_from_exchange(
conn, ex, limit=options_limit, fetch_fn=fetch_fn, format_fn=format_fn
)
else:
out["options"] = {"ok": False, "msg": "期权 exchange 未就绪"}
out["options"] = sync_options_from_local_trades(conn)
out["hedge"] = sync_hedge_plans_closed(conn)
return out
def ensure_local_review_synced(conn: sqlite3.Connection) -> dict[str, Any]:
"""列表/统计前轻量刷新本地源."""
return sync_all_review_sources(conn, from_exchange=False)
def _row_to_dict(row: Any) -> dict[str, Any]:
return dict(row) if row is not None else {}