Deduct round-trip taker fees from estimated perp PnL.
Unify hub/instance TP profit, calc_pnl, and push/accounting to net of 0.05% per side; leave exchange floating PnL unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2281,7 +2281,7 @@ def format_hold_minutes(minutes):
|
||||
|
||||
|
||||
def calc_pnl(direction, trigger_price, exit_price, margin_capital, leverage, notional_usdt=None):
|
||||
"""估算盈亏(USDT).优先用名义价值 notional_usdt,否则 margin×leverage."""
|
||||
"""估算净盈亏(USDT).优先用名义价值 notional_usdt,否则 margin×leverage;扣双边 taker 费."""
|
||||
try:
|
||||
trigger = float(trigger_price)
|
||||
exit_p = float(exit_price)
|
||||
@@ -2299,7 +2299,14 @@ def calc_pnl(direction, trigger_price, exit_price, margin_capital, leverage, not
|
||||
pnl_ratio = (trigger - exit_p) / trigger
|
||||
else:
|
||||
pnl_ratio = (exit_p - trigger) / trigger
|
||||
return round(notional * pnl_ratio, FUNDS_DECIMALS)
|
||||
gross = notional * pnl_ratio
|
||||
try:
|
||||
from lib.trade.trade_fee_lib import net_pnl_after_fee
|
||||
|
||||
net = net_pnl_after_fee(gross, trigger, exit_p, open_notional=notional)
|
||||
return round(float(net), FUNDS_DECIMALS) if net is not None else round(gross, FUNDS_DECIMALS)
|
||||
except Exception:
|
||||
return round(gross, FUNDS_DECIMALS)
|
||||
except Exception:
|
||||
return 0.0
|
||||
|
||||
@@ -2449,7 +2456,7 @@ def _sum_binance_income(entries, income_types, trade_ids=None):
|
||||
|
||||
|
||||
def calc_pnl_from_closing_trades(direction, entry_price, trades, exchange_symbol=None):
|
||||
"""按减仓成交数量×价差汇总盈亏(不含资金费;比单点标记价更接近交易所)."""
|
||||
"""按减仓成交数量×价差汇总净盈亏(扣固定双边 taker 费;不含资金费)."""
|
||||
try:
|
||||
entry = float(entry_price)
|
||||
except (TypeError, ValueError):
|
||||
@@ -2465,6 +2472,7 @@ def calc_pnl_from_closing_trades(direction, entry_price, trades, exchange_symbol
|
||||
contract_size = 1.0
|
||||
pnl = 0.0
|
||||
qty = 0.0
|
||||
notional_close = 0.0
|
||||
for t in trades:
|
||||
try:
|
||||
price = float(t.get("price") or 0)
|
||||
@@ -2474,13 +2482,22 @@ def calc_pnl_from_closing_trades(direction, entry_price, trades, exchange_symbol
|
||||
if price <= 0 or amount <= 0:
|
||||
continue
|
||||
qty += amount
|
||||
notional_close += amount * price
|
||||
if direction == "short":
|
||||
pnl += amount * (entry - price)
|
||||
else:
|
||||
pnl += amount * (price - entry)
|
||||
if qty <= 0:
|
||||
return None
|
||||
return round(pnl, FUNDS_DECIMALS)
|
||||
exit_px = (notional_close / qty) if qty > 0 else entry
|
||||
try:
|
||||
from lib.trade.trade_fee_lib import net_pnl_after_fee
|
||||
|
||||
# amount 已乘 contractSize,此处面值用 1
|
||||
net = net_pnl_after_fee(pnl, entry, exit_px, qty, 1.0)
|
||||
return round(float(net), FUNDS_DECIMALS) if net is not None else round(pnl, FUNDS_DECIMALS)
|
||||
except Exception:
|
||||
return round(pnl, FUNDS_DECIMALS)
|
||||
|
||||
|
||||
def resolve_trade_pnl_amount(
|
||||
@@ -2535,10 +2552,31 @@ def resolve_trade_pnl_amount(
|
||||
ex_sym, direction, open_ms, close_ms, closing_trades=closing_trades
|
||||
)
|
||||
if net is not None:
|
||||
# income 已含真实手续费,直接用.
|
||||
return net, exit_price, eo, ec, sync_key
|
||||
if closing_trades:
|
||||
trade_pnl = calc_binance_realized_pnl_from_trades(closing_trades)
|
||||
if trade_pnl is not None:
|
||||
# fill.realizedPnl 通常不含 commission,补固定双边费.
|
||||
try:
|
||||
from lib.trade.trade_fee_lib import net_pnl_after_fee
|
||||
|
||||
entry = float(entry_price or 0)
|
||||
exit_p = float(exit_price or entry or 0)
|
||||
if entry > 0 and exit_p > 0:
|
||||
open_n = get_plan_notional_usdt(row)
|
||||
if open_n is None:
|
||||
margin = row["margin_capital"] if hasattr(row, "keys") else row.get("margin_capital")
|
||||
lev = row["leverage"] if hasattr(row, "keys") else row.get("leverage")
|
||||
try:
|
||||
open_n = float(margin or 0) * float(lev or 1)
|
||||
except (TypeError, ValueError):
|
||||
open_n = None
|
||||
adj = net_pnl_after_fee(trade_pnl, entry, exit_p, open_notional=open_n)
|
||||
if adj is not None:
|
||||
trade_pnl = adj
|
||||
except Exception:
|
||||
pass
|
||||
return trade_pnl, exit_price, None, None, None
|
||||
fill_pnl = calc_pnl_from_closing_trades(direction, entry_price, closing_trades, ex_sym)
|
||||
if fill_pnl is not None:
|
||||
|
||||
Reference in New Issue
Block a user