fix多笔买/卖回用VWAP计入真盈亏,卖完再结算并标记待卖回。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-13 10:38:46 +08:00
parent 42a7ee9961
commit 53a624633d
11 changed files with 451 additions and 28 deletions
+68 -4
View File
@@ -202,6 +202,62 @@ def true_pnl_usdt_premium_move(
return round(float(pnl) * float(close_px) - prem_move, 4)
def resolve_spot_vwap_prices(
conn: Any = None,
*,
bridge_id: Any = None,
open_index_px: Any = None,
close_index_px: Any = None,
) -> tuple[float | None, float | None, str]:
"""开仓价/卖回价:优先桥上多笔 VWAP,否则冻结指数.
返回 (open_px, close_px, gate):
gate='' 可算; 'pending_sell' 卖回未完成; 'missing' 缺价
"""
open_px = _safe_float(open_index_px)
close_px = _safe_float(close_index_px)
bid = None
try:
if bridge_id is not None and str(bridge_id).strip() != "":
bid = int(bridge_id)
except (TypeError, ValueError):
bid = None
if conn is not None and bid is not None:
try:
from lib.options.options_spot_bridge_lib import (
BRIDGE_CLOSED,
BRIDGE_PENDING_SELL,
bridge_buy_vwap,
bridge_sell_vwap,
ensure_bridge_table,
)
ensure_bridge_table(conn)
bv = bridge_buy_vwap(conn, bid)
if bv is not None and bv > 0:
open_px = bv
row = conn.execute(
"SELECT status FROM options_spot_bridge WHERE id=?",
(bid,),
).fetchone()
st = str(
row["status"] if row and hasattr(row, "keys") else (row[0] if row else "") or ""
)
if st == BRIDGE_PENDING_SELL:
return open_px, None, "pending_sell"
sv = bridge_sell_vwap(conn, bid)
if sv is not None and sv > 0:
close_px = sv
elif st == BRIDGE_CLOSED and (close_px is None or close_px <= 0):
# 已关桥但无 VWAP/冻结卖回价
return open_px, None, "missing"
except Exception:
pass
if open_px is None or open_px <= 0 or close_px is None or close_px <= 0:
return open_px, close_px, "missing"
return open_px, close_px, ""
def resolve_true_pnl_usdt_from_trade(
*,
premium_paid: Any = None,
@@ -213,10 +269,12 @@ def resolve_true_pnl_usdt_from_trade(
close_fee: Any = 0,
premium_ccy: str | None = None,
fee_ccy: str | None = None,
conn: Any = None,
bridge_id: Any = None,
) -> tuple[float | None, str]:
"""由成交字段算复盘真盈亏;不含现货多买/账户差分.
"""由成交字段算复盘真盈亏;开/卖回价优先多笔 VWAP.
返回 (pnl_u, source): premium_move | stable | none
返回 (pnl_u, source): premium_move | stable | pending_sell | none
"""
del fee_ccy # 费率折 U 已体现在历史币盈亏里;本函数不重扣
pc = str(premium_ccy or "").strip().upper()
@@ -233,8 +291,14 @@ def resolve_true_pnl_usdt_from_trade(
return round(float(coin), 4), "stable"
return None, "none"
open_px = _safe_float(open_index_px)
close_px = _safe_float(close_index_px)
open_px, close_px, gate = resolve_spot_vwap_prices(
conn,
bridge_id=bridge_id,
open_index_px=open_index_px,
close_index_px=close_index_px,
)
if gate == "pending_sell":
return None, "pending_sell"
# 优先严格按用户式:历史币盈亏×卖回价 − 权利金×(开仓价−卖回价)
usdt = true_pnl_usdt_premium_move(
coin_pnl=coin,