币本位数据统计改为U展示,已平盈亏按指数折U与浮盈口径一致。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -8,6 +8,94 @@ from lib.instance.instance_embed_context_lib import profit_loss_ratio_from_avera
|
||||
from lib.options.options_db import init_options_tables
|
||||
|
||||
|
||||
def _safe_float(v: Any) -> float | None:
|
||||
if v is None or v == "":
|
||||
return None
|
||||
try:
|
||||
return float(v)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def _underlying_index_usdt(ex: Any, underly: str) -> float | None:
|
||||
"""取标的 USDT 近似指数(币本位已平盈亏折 U).优先公开 ticker,避免私钥失败."""
|
||||
u = (underly or "ETH").strip().upper() or "ETH"
|
||||
pubs: list[Any] = []
|
||||
try:
|
||||
from lib.sim.hooks import _APP_MODULE, _sim_public_exchange
|
||||
|
||||
pub = _sim_public_exchange(ex) if _APP_MODULE is not None else None
|
||||
if pub is not None:
|
||||
pubs.append(pub)
|
||||
except Exception:
|
||||
pass
|
||||
if ex is not None and ex not in pubs:
|
||||
pubs.append(ex)
|
||||
from lib.exchange.okx_options_lib import fetch_index_price
|
||||
|
||||
for pub in pubs:
|
||||
try:
|
||||
if hasattr(pub, "public_get_market_ticker"):
|
||||
rows = (pub.public_get_market_ticker({"instId": f"{u}-USDT"}) or {}).get("data") or []
|
||||
if rows:
|
||||
last = _safe_float(rows[0].get("last") or rows[0].get("lastPx"))
|
||||
if last is not None and last > 0:
|
||||
return float(last)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
px = fetch_index_price(pub, f"{u}-USD")
|
||||
if px is not None and float(px) > 0:
|
||||
return float(px)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
t = pub.fetch_ticker(f"{u}/USDT") or {}
|
||||
last = _safe_float(t.get("last") or t.get("close"))
|
||||
if last is not None and last > 0:
|
||||
return float(last)
|
||||
except Exception:
|
||||
continue
|
||||
return None
|
||||
|
||||
|
||||
def history_pnl_to_usdt(history: list[dict[str, Any]], ex: Any = None) -> list[dict[str, Any]]:
|
||||
"""
|
||||
统计用:币本位 realized_pnl(ETH/BTC) 按指数折成 U;USDC 原样.
|
||||
折算失败的币仓剔除盈亏字段,避免把「币数量」当成 U.
|
||||
"""
|
||||
from lib.options.options_margin_mode_lib import margin_mode_from_inst_id, premium_ccy_for_mode
|
||||
|
||||
idx_cache: dict[str, float | None] = {}
|
||||
out: list[dict[str, Any]] = []
|
||||
for row in history:
|
||||
r = dict(row)
|
||||
if r.get("status") == "open":
|
||||
out.append(r)
|
||||
continue
|
||||
pnl = _safe_float(r.get("realized_pnl"))
|
||||
if pnl is None:
|
||||
out.append(r)
|
||||
continue
|
||||
inst = str(r.get("inst_id") or "")
|
||||
underly = str(r.get("underlying") or (inst.split("-")[0] if inst else "ETH") or "ETH")
|
||||
ccy = str(r.get("premium_ccy") or "").strip().upper()
|
||||
if not ccy:
|
||||
ccy = premium_ccy_for_mode(margin_mode_from_inst_id(inst), underly)
|
||||
if ccy in ("ETH", "BTC"):
|
||||
if underly not in idx_cache:
|
||||
idx_cache[underly] = _underlying_index_usdt(ex, underly)
|
||||
idx = idx_cache.get(underly)
|
||||
if idx is None or idx <= 0:
|
||||
r["realized_pnl"] = None
|
||||
else:
|
||||
r["realized_pnl"] = round(float(pnl) * float(idx), 4)
|
||||
else:
|
||||
r["realized_pnl"] = round(float(pnl), 4)
|
||||
out.append(r)
|
||||
return out
|
||||
|
||||
|
||||
def _parse_ts(raw: Any) -> datetime | None:
|
||||
if raw is None or raw == "":
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user