修复 OKX 期权翻倍出场与币本位浮盈:中控/看板按指数折 U,避免 BTC 币数量当美金。

翻倍出场按全仓买一判定且对冲表异常不再整段跳过;面板按当前倍数展示需回收公式。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-09-30 22:17:02 +08:00
parent bd4adc9eca
commit 32746b0a34
9 changed files with 212 additions and 71 deletions
+32 -4
View File
@@ -124,14 +124,42 @@ def display_pnl_from_option_row(row: dict[str, Any]) -> float | None:
return _safe_float(row.get("upl"))
def display_pnl_usdt_from_option_row(row: dict[str, Any]) -> float | None:
"""顶栏/看板/中控「实时盈亏」用:币本位净盈亏按指数折 USDT;USDC 仓原样.
BTC/ETH 币本位若不折算,会被界面标成 U 而数值仍是币数量(BTC 尤为离谱).
"""
pnl = display_pnl_from_option_row(row)
if pnl is None:
return None
ccy = str(row.get("premium_ccy") or "USDC").strip().upper() or "USDC"
if not ccy or ccy == "USDC":
# 兜底:按合约推断币本位,避免 premium_ccy 缺失时把 BTC 盈亏当 U
inst = str(row.get("inst_id") or row.get("instId") or "")
mode = str(row.get("margin_mode") or "").strip().lower()
if mode == "coin" or (
"-USD-" in inst.upper() and "_UM" not in inst.upper()
):
underly = str(row.get("underlying") or (inst.split("-")[0] if inst else "") or "").upper()
if underly in ("ETH", "BTC"):
ccy = underly
if ccy in ("ETH", "BTC"):
idx = _safe_float(row.get("idx_px") or row.get("idxPx") or row.get("index_px"))
if idx is None or idx <= 0:
# 无指数时无法折算,跳过该仓以免把「币数量」当成 U
return None
return float(pnl) * float(idx)
return float(pnl)
def sum_options_net_pnl_usdc(
cfg: dict[str, Any],
ex: Any,
raw_positions: list[dict[str, Any]] | None = None,
) -> float | None:
"""
期权浮盈合计(USDC),与顶栏实时盈亏/中控口径对齐为「净盈亏」:
各仓买一可回收 − 权利金之和;残档则回退该仓交易所 upl.
期权浮盈合计(USDT/USDC 口径),与顶栏实时盈亏/中控对齐:
各仓买一可回收 − 权利金;币本位再 × 指数折成 U;残档回退该仓 upl(同样折算).
获取失败返回 None;无持仓返回 0.
"""
raw = raw_positions
@@ -145,12 +173,12 @@ def sum_options_net_pnl_usdc(
total = 0.0
found = False
for p in positions:
pnl = display_pnl_from_option_row(p)
pnl = display_pnl_usdt_from_option_row(p)
if pnl is None:
continue
found = True
total += float(pnl)
return round(total, 8) if found else (0.0 if not positions else None)
return round(total, 4) if found else (0.0 if not positions else None)
def build_display_option_positions(