fix真盈亏只认卖光收回减买币,禁止权利金指数冒充。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -190,9 +190,13 @@ def try_settle_after_sellback(
|
||||
block = sellable_coin_blocks_settle(ex, uly)
|
||||
if block:
|
||||
return 0
|
||||
try:
|
||||
from lib.exchange.okx_options_lib import invalidate_options_balance_cache
|
||||
|
||||
invalidate_options_balance_cache()
|
||||
except Exception:
|
||||
pass
|
||||
after = fetch_trading_usdt(pack, ex)
|
||||
if after is None:
|
||||
return 0
|
||||
n = 0
|
||||
if bridge_id is not None:
|
||||
n = settle_closed_trades_from_trading_account(
|
||||
@@ -232,21 +236,83 @@ def try_settle_after_sellback(
|
||||
pass
|
||||
|
||||
|
||||
def resolve_true_pnl_usdt(
|
||||
conn,
|
||||
*,
|
||||
trading_usdt_before: Any = None,
|
||||
trading_usdt_after: Any = None,
|
||||
bridge_id: Any = None,
|
||||
realized_pnl_usdt: Any = None,
|
||||
pnl_settled: Any = False,
|
||||
) -> tuple[float | None, str]:
|
||||
"""真盈亏(口径 A)=卖光标的币收回 USDT − 开仓买币花费.
|
||||
|
||||
优先账户快照 after−before(与上式等价);其次已关桥的「卖回累计−买币预算」.
|
||||
绝不回退权利金×指数(那是口径 B / 期权腿).
|
||||
返回 (pnl_u, source): account | bridge | frozen | none
|
||||
"""
|
||||
before = _safe_float(trading_usdt_before)
|
||||
after = _safe_float(trading_usdt_after)
|
||||
if before is not None and after is not None:
|
||||
return round(float(after) - float(before), 4), "account"
|
||||
|
||||
bid = None
|
||||
try:
|
||||
if bridge_id is not None and str(bridge_id).strip() != "":
|
||||
bid = int(bridge_id)
|
||||
except (TypeError, ValueError):
|
||||
bid = None
|
||||
if bid is not None:
|
||||
try:
|
||||
from lib.options.options_spot_bridge_lib import (
|
||||
BRIDGE_CLOSED,
|
||||
cash_pnl_usdt_from_bridge,
|
||||
ensure_bridge_table,
|
||||
)
|
||||
|
||||
ensure_bridge_table(conn)
|
||||
brow = conn.execute(
|
||||
"SELECT status, usdt_recovered FROM options_spot_bridge WHERE id=?",
|
||||
(bid,),
|
||||
).fetchone()
|
||||
if brow:
|
||||
st = str(brow["status"] if hasattr(brow, "keys") else brow[0] or "")
|
||||
recovered = _safe_float(
|
||||
brow["usdt_recovered"] if hasattr(brow, "keys") else brow[1]
|
||||
)
|
||||
if st == BRIDGE_CLOSED and recovered is not None:
|
||||
bp = cash_pnl_usdt_from_bridge(conn, bid)
|
||||
if bp is not None:
|
||||
return bp, "bridge"
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
settled = int(pnl_settled or 0) == 1
|
||||
except (TypeError, ValueError):
|
||||
settled = bool(pnl_settled)
|
||||
frozen = _safe_float(realized_pnl_usdt)
|
||||
# 仅承认「有 before 且已账户结算」的旧冻结;无快照的指数折 U 不算真盈亏
|
||||
if settled and before is not None and frozen is not None:
|
||||
return round(float(frozen), 4), "frozen"
|
||||
return None, "none"
|
||||
|
||||
|
||||
def settle_closed_trades_from_trading_account(
|
||||
conn,
|
||||
*,
|
||||
trading_usdt_after: float,
|
||||
trading_usdt_after: float | None = None,
|
||||
bridge_id: int | None = None,
|
||||
trade_id: int | None = None,
|
||||
) -> int:
|
||||
"""卖回后:对本桥/本单未结算已平仓位冻结 after−before.
|
||||
"""卖回后:对本桥/本单未结算已平仓位冻结真盈亏.
|
||||
|
||||
优先 after−before;账户 after 缺失时用桥「卖回−买币」.
|
||||
已 pnl_settled=1 的行永不改写.
|
||||
"""
|
||||
after = _safe_float(trading_usdt_after)
|
||||
if after is None:
|
||||
return 0
|
||||
after = round(float(after), 8)
|
||||
if after is not None:
|
||||
after = round(float(after), 8)
|
||||
clauses = ["status='closed'", "COALESCE(pnl_settled, 0)=0", "trading_usdt_before IS NOT NULL"]
|
||||
params: list[Any] = []
|
||||
if trade_id is not None:
|
||||
@@ -259,7 +325,7 @@ def settle_closed_trades_from_trading_account(
|
||||
return 0
|
||||
rows = conn.execute(
|
||||
f"""
|
||||
SELECT id, trading_usdt_before, realized_pnl_usdt
|
||||
SELECT id, trading_usdt_before, realized_pnl_usdt, bridge_id
|
||||
FROM options_trades
|
||||
WHERE {" AND ".join(clauses)}
|
||||
""",
|
||||
@@ -267,10 +333,27 @@ def settle_closed_trades_from_trading_account(
|
||||
).fetchall()
|
||||
updated = 0
|
||||
for row in rows:
|
||||
tid = int(row["id"] if hasattr(row, "keys") else row[0])
|
||||
before = _safe_float(row["trading_usdt_before"] if hasattr(row, "keys") else row[1])
|
||||
if before is None:
|
||||
continue
|
||||
pnl_u = round(float(after) - float(before), 4)
|
||||
row_bid = row["bridge_id"] if hasattr(row, "keys") else row[3]
|
||||
if row_bid is None and bridge_id is not None:
|
||||
row_bid = bridge_id
|
||||
after_use = after
|
||||
if after_use is not None:
|
||||
pnl_u = round(float(after_use) - float(before), 4)
|
||||
else:
|
||||
pnl_u, src = resolve_true_pnl_usdt(
|
||||
conn,
|
||||
trading_usdt_before=before,
|
||||
trading_usdt_after=None,
|
||||
bridge_id=row_bid,
|
||||
pnl_settled=0,
|
||||
)
|
||||
if pnl_u is None or src != "bridge":
|
||||
continue
|
||||
after_use = round(float(before) + float(pnl_u), 8)
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE options_trades
|
||||
@@ -279,7 +362,7 @@ def settle_closed_trades_from_trading_account(
|
||||
pnl_settled = 1
|
||||
WHERE id = ? AND COALESCE(pnl_settled, 0)=0
|
||||
""",
|
||||
(after, pnl_u, int(row["id"] if hasattr(row, "keys") else row[0])),
|
||||
(after_use, pnl_u, tid),
|
||||
)
|
||||
updated += 1
|
||||
return updated
|
||||
|
||||
Reference in New Issue
Block a user