Use exchange fees, UPL, funding for LIVE PnL; USDC 1:1 to USDT.

Option open P&L stays local (option net); exit target ignores estimated close fees.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-26 21:49:20 +08:00
parent b7e055e37b
commit ca66c494e7
12 changed files with 685 additions and 25 deletions
+58 -1
View File
@@ -32,6 +32,41 @@ class BinanceLiveExecutor(Matcher):
return reason
return None
def unrealized(self) -> dict:
base = super().unrealized()
if not base.get("has_position"):
return base
from .live_pnl import enrich_live_unrealized
s = get_settings()
gid = base.get("group_id")
open_at = None
if gid:
g = self.db.fetchone(
"SELECT open_at_ms, perp_inst_id FROM groups WHERE group_id=?",
(gid,),
)
if g:
open_at = int(g["open_at_ms"] or 0) or None
perp_inst = str(g["perp_inst_id"] or s.perp_inst_id)
else:
perp_inst = s.perp_inst_id
else:
perp_inst = s.perp_inst_id
try:
client = self._client()
except Exception:
return base
return enrich_live_unrealized(
base=base,
db=self.db,
client=client,
exchange="binance",
perp_inst_id=perp_inst,
perp_side=str(base.get("perp_side") or ""),
open_at_ms=open_at,
)
def open_group(
self,
*,
@@ -747,10 +782,32 @@ class BinanceLiveExecutor(Matcher):
)
self.db._conn.commit()
from .live_pnl import reconcile_closed_group_pnl
g2 = self.db.fetchone(
"SELECT open_at_ms, perp_inst_id FROM groups WHERE group_id=?",
(group_id,),
)
net = reconcile_closed_group_pnl(
db=self.db,
client=self._client(),
exchange="binance",
group_id=group_id,
perp_inst_id=str((g2["perp_inst_id"] if g2 else None) or s.perp_inst_id),
open_at_ms=int(g2["open_at_ms"]) if g2 and g2["open_at_ms"] else None,
local_net=float(net) if net is not None else None,
)
return CloseResult(
ok=True,
detail="closed_live_binance",
data={"group_id": group_id, "reason": reason, "net_pnl": net, "exec_mode": "LIVE"},
data={
"group_id": group_id,
"reason": reason,
"net_pnl": net,
"exec_mode": "LIVE",
"pnl_source": "live_exchange",
},
)
def close_perp_abandon_option(