From fd4597f7355c07414a5192766c021444094b2097 Mon Sep 17 00:00:00 2001 From: dekun Date: Sat, 25 Jul 2026 09:28:40 +0800 Subject: [PATCH] Compute option UPL as initial premium minus bid times size. Co-authored-by: Cursor --- backend/app/sim/matcher.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/backend/app/sim/matcher.py b/backend/app/sim/matcher.py index e7b2f06..cdca3ef 100644 --- a/backend/app/sim/matcher.py +++ b/backend/app/sim/matcher.py @@ -467,33 +467,38 @@ class Matcher: oq = get_exchange().quote(opt_inst) if opt_inst else None if oq is None: oq = snap.call if option_side == "call" else snap.put + initial_premium = float(pos["initial_premium"] or 0) option_upl = 0.0 + option_econ = 0.0 # 真实经济盈亏:买一市值 − 开仓权利金 est_opt_close_fee = 0.0 opt_mark = None if oq and oq.bid is not None: + bid = float(oq.bid) of = option_fill( action="close", - bid=float(oq.bid), - ask=float(oq.ask or oq.bid), + bid=bid, + ask=float(oq.ask or bid), qty_eth=opt_qty, fee_rate=fee_rate, ) - option_upl = (of.fill_px - opt_entry) * opt_qty est_opt_close_fee = of.fee - opt_mark = of.fill_px + opt_mark = bid + # 浮盈亏展示:初始权利金 − 买一×数量 + option_upl = initial_premium - bid * opt_qty + option_econ = bid * opt_qty - initial_premium elif oq: opt_mark = oq.bid or oq.mark_px if opt_mark is not None: - option_upl = (float(opt_mark) - opt_entry) * opt_qty + option_upl = initial_premium - float(opt_mark) * opt_qty + option_econ = float(opt_mark) * opt_qty - initial_premium est_close_fees = est_perp_close_fee + est_opt_close_fee - # 净盈利口径与平仓结算一致:双腿盈亏 − 预估平仓手续费 - net_pnl = perp_upl + option_upl - est_close_fees + # 净盈利用经济口径(含预估平仓费);期权浮盈亏字段单独按权利金−买一市值 + net_pnl = perp_upl + option_econ - est_close_fees entry_idx = float(pos["entry_index_px"] or 0) move = abs(float(index_px) - entry_idx) if index_px is not None and entry_idx else 0.0 move_pct = (move / entry_idx * 100.0) if entry_idx > 0 else 0.0 - initial_premium = float(pos["initial_premium"] or 0) premium_gap = initial_premium - perp_upl leverage = self.ledger.get_setting_float("leverage", s.leverage) notional = abs(perp_entry * perp_qty)