Improve OKX options sizing, expiry sync, and multi-position accordion UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-09 16:51:48 +08:00
parent d092f213a7
commit f41af0bf1c
7 changed files with 542 additions and 18 deletions
+54
View File
@@ -644,6 +644,60 @@ def fetch_option_positions(ex: ccxt.okx) -> list[dict[str, Any]]:
return []
def fetch_option_position_history(
ex: ccxt.okx,
inst_id: str,
*,
limit: int = 20,
) -> list[dict[str, Any]]:
"""OKX 期权历史仓位(含到期结算/平仓)."""
inst_id = (inst_id or "").strip()
if not inst_id:
return []
try:
resp = ex.private_get_account_positions_history(
{
"instType": "OPTION",
"instId": inst_id,
"limit": str(max(1, min(int(limit), 100))),
}
)
rows = (resp or {}).get("data") or []
return [r for r in rows if isinstance(r, dict)]
except Exception:
return []
def resolve_option_close_from_history(
hist_rows: list[dict[str, Any]],
*,
open_ms: int | None = None,
) -> dict[str, Any] | None:
"""从 positions-history 中选取最近一条有效平仓/结算记录."""
best: dict[str, Any] | None = None
best_utime = -1
for row in hist_rows:
u_ms = _safe_float(row.get("uTime"))
if u_ms is None or u_ms <= 0:
continue
if open_ms is not None and u_ms < int(open_ms) - 60_000:
continue
if u_ms > best_utime:
best = row
best_utime = int(u_ms)
if not best:
return None
realized = _safe_float(best.get("realizedPnl"))
if realized is None:
realized = _safe_float(best.get("pnl"))
return {
"close_quote": _safe_float(best.get("closeAvgPx")),
"realized_pnl": realized,
"close_ms": best_utime,
"pos_id": str(best.get("posId") or "").strip() or None,
}
def fetch_options_unrealized_pnl_usdc(ex: ccxt.okx) -> float | None:
"""期权持仓未实现盈亏合计(USDC,统计口径与 USDT 1:1)."""
total = 0.0