实盘数据统计改用期权历史交易所盈亏;模拟盘仍走本地结算。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -466,12 +466,8 @@ def repair_double_counted_fee_pnl(conn, ex: Any = None) -> int:
|
||||
|
||||
|
||||
def load_local_options_stats_history(conn, ex: Any = None) -> list[dict[str, Any]]:
|
||||
"""本地已平(含冻结 U/手续费净额) + 当前 open,供统计/中控窗口复用."""
|
||||
"""本地已平(模拟盘口径) + 当前 open."""
|
||||
init_options_tables(conn)
|
||||
try:
|
||||
recompute_closed_realized_pnl_usdt(conn, ex)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
freeze_missing_realized_pnl_usdt(conn, ex)
|
||||
except Exception:
|
||||
@@ -486,7 +482,86 @@ def load_local_options_stats_history(conn, ex: Any = None) -> list[dict[str, Any
|
||||
return history
|
||||
|
||||
|
||||
def apply_exchange_pnl_freeze(
|
||||
conn,
|
||||
history: list[dict[str, Any]],
|
||||
ex: Any = None,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""实盘:以期权历史里的交易所 realized_pnl 为准,首次折 U 后按 history_key 冻结."""
|
||||
from lib.options.options_pnl_settle_lib import settle_exchange_realized_pnl
|
||||
from lib.options.options_time_lib import options_app_now_str
|
||||
|
||||
init_options_tables(conn)
|
||||
out: list[dict[str, Any]] = []
|
||||
for row in history or []:
|
||||
r = dict(row)
|
||||
if r.get("status") == "open":
|
||||
out.append(r)
|
||||
continue
|
||||
key = str(r.get("history_key") or "").strip()
|
||||
pnl = _safe_float(r.get("realized_pnl"))
|
||||
if not key or pnl is None:
|
||||
out.append(r)
|
||||
continue
|
||||
frozen = conn.execute(
|
||||
"""
|
||||
SELECT realized_pnl_usdt, close_index_px, realized_pnl
|
||||
FROM options_exchange_pnl_freeze WHERE history_key = ?
|
||||
""",
|
||||
(key,),
|
||||
).fetchone()
|
||||
if frozen is not None and _safe_float(_row_get(frozen, "realized_pnl_usdt")) is not None:
|
||||
r["realized_pnl_usdt"] = _row_get(frozen, "realized_pnl_usdt")
|
||||
r["close_index_px"] = _row_get(frozen, "close_index_px")
|
||||
# 币数量仍以当前交易所行为准(防历史修订);U 用冻结值
|
||||
out.append(r)
|
||||
continue
|
||||
ccy = str(r.get("premium_ccy") or "").strip().upper()
|
||||
underly = str(r.get("underlying") or "").strip()
|
||||
inst = str(r.get("inst_id") or "")
|
||||
if not underly and inst:
|
||||
underly = inst.split("-")[0]
|
||||
from lib.options.options_pnl_settle_lib import resolve_close_index_px
|
||||
|
||||
idx = resolve_close_index_px(ex, inst_id=inst, underlying=underly)
|
||||
settled = settle_exchange_realized_pnl(
|
||||
realized_pnl=pnl,
|
||||
premium_ccy=ccy or "ETH",
|
||||
index_px=idx,
|
||||
)
|
||||
usdt = settled.get("realized_pnl_usdt")
|
||||
close_idx = settled.get("close_index_px")
|
||||
if usdt is not None:
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO options_exchange_pnl_freeze(
|
||||
history_key, realized_pnl, realized_pnl_usdt, close_index_px,
|
||||
premium_ccy, updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(history_key) DO UPDATE SET
|
||||
realized_pnl = excluded.realized_pnl,
|
||||
realized_pnl_usdt = excluded.realized_pnl_usdt,
|
||||
close_index_px = excluded.close_index_px,
|
||||
premium_ccy = excluded.premium_ccy,
|
||||
updated_at = excluded.updated_at
|
||||
""",
|
||||
(
|
||||
key,
|
||||
float(pnl),
|
||||
float(usdt),
|
||||
close_idx,
|
||||
ccy or "",
|
||||
options_app_now_str(),
|
||||
),
|
||||
)
|
||||
r["realized_pnl_usdt"] = float(usdt)
|
||||
r["close_index_px"] = close_idx
|
||||
out.append(r)
|
||||
return out
|
||||
|
||||
|
||||
def compute_options_stats(get_db, ex: Any = None) -> dict[str, Any]:
|
||||
"""模拟盘:本地交易结算.实盘请用 compute_options_stats_live_exchange."""
|
||||
conn = get_db()
|
||||
try:
|
||||
history = load_local_options_stats_history(conn, ex)
|
||||
@@ -494,12 +569,43 @@ def compute_options_stats(get_db, ex: Any = None) -> dict[str, Any]:
|
||||
conn.commit()
|
||||
except Exception:
|
||||
pass
|
||||
# 优先冻结 U;缺省再按指数折(与 /api/options/stats 一致)
|
||||
return compute_options_stats_from_history(history_pnl_to_usdt(history, ex))
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def compute_options_stats_live_exchange(cfg: dict[str, Any], ex: Any) -> dict[str, Any]:
|
||||
"""实盘:与「期权历史」同一数据源(交易所 positions-history),盈亏以交易所为准."""
|
||||
from lib.options.options_history_lib import load_options_history
|
||||
|
||||
history = load_options_history(ex, cfg)
|
||||
conn = cfg["get_db"]()
|
||||
try:
|
||||
history = apply_exchange_pnl_freeze(conn, history, ex)
|
||||
try:
|
||||
conn.commit()
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
conn.close()
|
||||
return compute_options_stats_from_history(history_pnl_to_usdt(history, ex))
|
||||
|
||||
|
||||
def compute_options_stats_auto(cfg: dict[str, Any], ex: Any = None) -> dict[str, Any]:
|
||||
"""模拟盘走本地结算;实盘走交易所期权历史原生盈亏."""
|
||||
get_db = cfg.get("get_db")
|
||||
try:
|
||||
from lib.sim.mode_lib import is_sim_mode
|
||||
|
||||
if callable(get_db) and is_sim_mode(get_db):
|
||||
return compute_options_stats(get_db, ex)
|
||||
except Exception:
|
||||
pass
|
||||
if ex is None:
|
||||
ex = cfg.get("exchange_options")
|
||||
return compute_options_stats_live_exchange(cfg, ex)
|
||||
|
||||
|
||||
def _stats_from_option_trade_rows(closed_rows, open_rows, *, ex: Any = None) -> dict[str, Any]:
|
||||
"""兼容旧调用;内部统一折 U 后走 compute_options_stats_from_history."""
|
||||
history = _closed_trade_dicts(closed_rows)
|
||||
|
||||
Reference in New Issue
Block a user