(function (global) { "use strict"; function fmt(v, d) { if (v === null || v === undefined || Number.isNaN(Number(v))) return "—"; return Number(v).toFixed(d == null ? 2 : d); } function fmtDisplay(v, fallback) { if (v !== null && v !== undefined && String(v).trim() !== "") return String(v); if (fallback !== undefined) return fmtDisplay(fallback); return "—"; } function fmtOptionPx(v, tickSz) { if (v === null || v === undefined || Number.isNaN(Number(v))) return "—"; const n = Number(v); const tick = Number(tickSz); if (!tickSz || Number.isNaN(tick) || tick <= 0) return String(n); let decimals = 0; if (tick < 1) decimals = Math.max(0, -Math.round(Math.log10(tick))); else if (String(tick).indexOf(".") >= 0) decimals = String(tick).split(".")[1].length; let s = n.toFixed(decimals); // 仅裁小数尾零;整数 tick(BTC=5)时绝不能把 1370 裁成 137 if (decimals > 0) s = s.replace(/\.?0+$/, ""); return s || "0"; } function fmtUsdc(v) { if (v === null || v === undefined || Number.isNaN(Number(v))) return "—"; return Number(v).toFixed(2); } function optTypeLabel(t) { return (t || "").toUpperCase() === "P" ? "看跌 Put" : "看涨 Call"; } function pnlCls(upl, hub) { if (upl > 0) return hub ? "pnl-pos" : "pos-pnl-profit"; if (upl < 0) return hub ? "pnl-neg" : "pos-pnl-loss"; return ""; } function fmtPxSz(px, sz, tickSz) { if (px === null || px === undefined || Number.isNaN(Number(px))) return "—"; let price = fmtOptionPx(px, tickSz); if (sz === null || sz === undefined || sz === "" || Number.isNaN(Number(sz))) return price; const s = Number(sz); const size = Math.abs(s - Math.round(s)) < 1e-9 ? String(Math.round(s)) : String(s); return price + "/" + size; } /** 买盘深度:价格/流动性;仅展示平仓所需档位(买一不够才出买二…). */ function fmtCloseLevels(preview, tickSz) { if (preview && (preview.auto_close_blocked || preview.bid_invalid)) { return "暂无有效买盘"; } const levels = ((preview && preview.levels) || []).slice(0, 5); if (!levels.length) return "—"; return levels.map(function (x, idx) { const levelNo = x.level != null ? x.level : idx + 1; const liq = x.available_sheets != null ? x.available_sheets : x.sz; return "买" + levelNo + " " + fmtPxSz(x.px, liq, tickSz); }).join(" · "); } function netPnlFromPos(p) { const preview = (p && p.close_preview) || {}; if (preview.estimated_pnl != null && !Number.isNaN(Number(preview.estimated_pnl))) { return Number(preview.estimated_pnl); } const recv = Number(preview.total_received); const prem = Number(p && p.premium_paid); if (preview.total_received != null && !Number.isNaN(recv) && !Number.isNaN(prem)) { return recv - prem; } return null; } function netRoiFromPos(p, net) { const preview = (p && p.close_preview) || {}; if (preview.estimated_pnl_ratio_pct != null && !Number.isNaN(Number(preview.estimated_pnl_ratio_pct))) { return Number(preview.estimated_pnl_ratio_pct); } const prem = Number(p && p.premium_paid); if (net == null || Number.isNaN(prem) || prem <= 0) return null; return (net / prem) * 100; } function fmtClosePreview(preview, premiumPaid, hub) { if (!preview || preview.total_received == null) return "—"; const recvTxt = fmtUsdc(preview.total_received); let cls = ""; const prem = Number(premiumPaid); const recv = Number(preview.total_received); if (!Number.isNaN(prem) && !Number.isNaN(recv)) { if (recv > prem) cls = " " + pnlCls(1, hub); else if (recv < prem) cls = " " + pnlCls(-1, hub); } return '' + recvTxt + " USDC"; } function expiryCdHtml(expMs) { const ms = expMs != null && expMs !== "" ? String(expMs) : ""; if (!ms) return "—"; return '—'; } function renderCardInner(p, opts) { opts = opts || {}; const hub = !!opts.hub; const readOnly = !!opts.readOnly; const net = netPnlFromPos(p); const roi = netRoiFromPos(p, net); const uplCls = pnlCls(net, hub); const sideCls = (p.opt_type || "").toUpperCase() === "P" ? "pos-side-short" : "pos-side-long"; const expMs = p.exp_time_ms != null ? p.exp_time_ms : p.exp_time; const expAttr = expMs != null && expMs !== "" ? String(expMs) : ""; const closePreview = p.close_preview || {}; const tickSz = p.tick_sz; const premTxt = fmtDisplay(p.premium_paid_fmt, p.premium_paid != null ? fmtUsdc(p.premium_paid) : null); const avgTxt = fmtDisplay(p.avg_px_fmt, fmtOptionPx(p.avg_px, tickSz)); const markTxt = fmtDisplay(p.mark_px_fmt, fmtOptionPx(p.mark_px, tickSz)); let headActions = ""; if (!readOnly) { const closeSheets = p.avail_pos != null && Number(p.avail_pos) > 0 ? p.avail_pos : p.pos; headActions = '