@@ -51,6 +51,8 @@ def _enrich_hub_protocol(snap: dict[str, Any], *, app_module: Any) -> dict[str,
|
|||||||
|
|
||||||
positions = out.get("positions") if isinstance(out.get("positions"), list) else []
|
positions = out.get("positions") if isinstance(out.get("positions"), list) else []
|
||||||
slim_pos = []
|
slim_pos = []
|
||||||
|
premium_total_usdt = 0.0
|
||||||
|
has_premium = False
|
||||||
for p in positions:
|
for p in positions:
|
||||||
if not isinstance(p, dict):
|
if not isinstance(p, dict):
|
||||||
continue
|
continue
|
||||||
@@ -86,12 +88,26 @@ def _enrich_hub_protocol(snap: dict[str, Any], *, app_module: Any) -> dict[str,
|
|||||||
pnl_usdt = display_pnl_usdt_from_option_row(p)
|
pnl_usdt = display_pnl_usdt_from_option_row(p)
|
||||||
except Exception:
|
except Exception:
|
||||||
pnl_usdt = p.get("net_pnl_usdt")
|
pnl_usdt = p.get("net_pnl_usdt")
|
||||||
|
premium_paid = p.get("premium_paid")
|
||||||
|
premium_usdt = None
|
||||||
|
try:
|
||||||
|
from lib.options.options_positions_lib import premium_paid_usdt_from_option_row
|
||||||
|
|
||||||
|
premium_usdt = premium_paid_usdt_from_option_row(p)
|
||||||
|
except Exception:
|
||||||
|
premium_usdt = None
|
||||||
|
if premium_usdt is not None:
|
||||||
|
has_premium = True
|
||||||
|
premium_total_usdt += float(premium_usdt)
|
||||||
slim_pos.append(
|
slim_pos.append(
|
||||||
{
|
{
|
||||||
"inst_id": p.get("inst_id"),
|
"inst_id": p.get("inst_id"),
|
||||||
"opt_type": p.get("opt_type"),
|
"opt_type": p.get("opt_type"),
|
||||||
"sheets": p.get("sheets") or p.get("pos"),
|
"sheets": p.get("sheets") or p.get("pos"),
|
||||||
"pnl_usdt": pnl_usdt,
|
"pnl_usdt": pnl_usdt,
|
||||||
|
"premium_paid": premium_paid,
|
||||||
|
"premium_paid_usdt": round(float(premium_usdt), 4) if premium_usdt is not None else None,
|
||||||
|
"premium_ccy": p.get("premium_ccy"),
|
||||||
"mark": p.get("mark") or p.get("mark_px"),
|
"mark": p.get("mark") or p.get("mark_px"),
|
||||||
"underlying": p.get("underlying"),
|
"underlying": p.get("underlying"),
|
||||||
"source_label": p.get("source_label"),
|
"source_label": p.get("source_label"),
|
||||||
@@ -113,15 +129,44 @@ def _enrich_hub_protocol(snap: dict[str, Any], *, app_module: Any) -> dict[str,
|
|||||||
"margin_mode": out.get("options_margin_mode") or "coin",
|
"margin_mode": out.get("options_margin_mode") or "coin",
|
||||||
"underly": out.get("options_underly") or "ETH",
|
"underly": out.get("options_underly") or "ETH",
|
||||||
}
|
}
|
||||||
|
funding_usdt = out.get("funding_usdt")
|
||||||
|
trading_usdt = out.get("trading_usdt")
|
||||||
|
funding_usdc = out.get("funding_usdc")
|
||||||
|
trading_usdc = out.get("trading_usdc")
|
||||||
out["funds"] = {
|
out["funds"] = {
|
||||||
"funding_usdt": out.get("funding_usdt"),
|
"funding_usdt": funding_usdt,
|
||||||
"trading_usdt": out.get("trading_usdt"),
|
"trading_usdt": trading_usdt,
|
||||||
"funding_usdc": out.get("funding_usdc"),
|
"funding_usdc": funding_usdc,
|
||||||
"trading_usdc": out.get("trading_usdc"),
|
"trading_usdc": trading_usdc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _f(v: Any) -> float | None:
|
||||||
|
if v is None or v == "":
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return float(v)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 账户资金口径:优先 USDT 资+交;都空则回退 USDC(≈U)
|
||||||
|
equity_parts = [_f(trading_usdt), _f(funding_usdt)]
|
||||||
|
if all(x is None for x in equity_parts):
|
||||||
|
equity_parts = [_f(trading_usdc), _f(funding_usdc)]
|
||||||
|
known = [x for x in equity_parts if x is not None]
|
||||||
|
equity_usdt = round(sum(known), 4) if known else None
|
||||||
|
premium_usdt = round(premium_total_usdt, 4) if has_premium else (0.0 if not slim_pos else None)
|
||||||
|
ratio_pct = None
|
||||||
|
if premium_usdt is not None and equity_usdt is not None and equity_usdt > 1e-9:
|
||||||
|
ratio_pct = round(float(premium_usdt) / float(equity_usdt) * 100.0, 2)
|
||||||
|
|
||||||
out["pnl"] = {
|
out["pnl"] = {
|
||||||
"unrealized_usdt": out.get("upl_total_usdc"),
|
"unrealized_usdt": out.get("upl_total_usdc"),
|
||||||
}
|
}
|
||||||
|
out["premium"] = {
|
||||||
|
"paid_usdt": premium_usdt,
|
||||||
|
"equity_usdt": equity_usdt,
|
||||||
|
"ratio_pct": ratio_pct,
|
||||||
|
}
|
||||||
out["positions_brief"] = slim_pos
|
out["positions_brief"] = slim_pos
|
||||||
try:
|
try:
|
||||||
from lib.options.options_time_lib import options_app_now_str
|
from lib.options.options_time_lib import options_app_now_str
|
||||||
|
|||||||
@@ -136,9 +136,26 @@ def display_pnl_usdt_from_option_row(row: dict[str, Any]) -> float | None:
|
|||||||
pnl = display_pnl_from_option_row(row)
|
pnl = display_pnl_from_option_row(row)
|
||||||
if pnl is None:
|
if pnl is None:
|
||||||
return None
|
return None
|
||||||
|
return _coin_amount_to_usdt(pnl, row)
|
||||||
|
|
||||||
|
|
||||||
|
def premium_paid_usdt_from_option_row(row: dict[str, Any]) -> float | None:
|
||||||
|
"""开仓权利金折 USDT:币本位 × 指数;USDC 原样."""
|
||||||
|
paid = _safe_float(row.get("premium_paid"))
|
||||||
|
if paid is None:
|
||||||
|
return None
|
||||||
|
return _coin_amount_to_usdt(paid, row)
|
||||||
|
|
||||||
|
|
||||||
|
def _coin_amount_to_usdt(amount: float, row: dict[str, Any]) -> float | None:
|
||||||
|
"""币本位金额按指数折 U;USDC 原样."""
|
||||||
|
try:
|
||||||
|
n = float(amount)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return None
|
||||||
ccy = str(row.get("premium_ccy") or "USDC").strip().upper() or "USDC"
|
ccy = str(row.get("premium_ccy") or "USDC").strip().upper() or "USDC"
|
||||||
if not ccy or ccy == "USDC":
|
if not ccy or ccy == "USDC":
|
||||||
# 兜底:按合约推断币本位,避免 premium_ccy 缺失时把 BTC 盈亏当 U
|
# 兜底:按合约推断币本位,避免 premium_ccy 缺失时把 BTC 数量当 U
|
||||||
inst = str(row.get("inst_id") or row.get("instId") or "")
|
inst = str(row.get("inst_id") or row.get("instId") or "")
|
||||||
mode = str(row.get("margin_mode") or "").strip().lower()
|
mode = str(row.get("margin_mode") or "").strip().lower()
|
||||||
if mode == "coin" or (
|
if mode == "coin" or (
|
||||||
@@ -150,10 +167,9 @@ def display_pnl_usdt_from_option_row(row: dict[str, Any]) -> float | None:
|
|||||||
if ccy in ("ETH", "BTC"):
|
if ccy in ("ETH", "BTC"):
|
||||||
idx = _safe_float(row.get("idx_px") or row.get("idxPx") or row.get("index_px"))
|
idx = _safe_float(row.get("idx_px") or row.get("idxPx") or row.get("index_px"))
|
||||||
if idx is None or idx <= 0:
|
if idx is None or idx <= 0:
|
||||||
# 无指数时无法折算,跳过该仓以免把「币数量」当成 U
|
|
||||||
return None
|
return None
|
||||||
return float(pnl) * float(idx)
|
return float(n) * float(idx)
|
||||||
return float(pnl)
|
return float(n)
|
||||||
|
|
||||||
|
|
||||||
def sum_options_net_pnl_usdc(
|
def sum_options_net_pnl_usdc(
|
||||||
|
|||||||
Reference in New Issue
Block a user