5.0 KiB
5.0 KiB
v4.5.43 (2026-08-05) 平仓推送删除 PnL 显示字段
⚠️ 用户原话 (2026-08-05 触发本次修复)
"盈亏不是 1.9 刀吗, 2.96 又是猜的吗" "我是从 app 看的" "你算不出来就把字段删了吧"
场景: 测试平了 BTC 1.25 张 (8/5 12:24 北京), advisor 推 QQ 显示 🟢 盈亏: +2.96 USDT, 用户从 OKX app 看实际是 -1.9 USDT (含 funding fee 累计)。
根因:
okx_position_advisor.py close_position()line 653:pnl = float(pos.get('unrealizedPnl', 0))— 用平仓前浮盈, 没扣手续费, 没扣 funding feeformat_close_result()line 729/737: 直接显示c['pnl']字段process_signal.py format_close_message()line 581-588: 用pos['upl']显示浮盈 X USDT
用户 app 显示 -1.9 vs 推送 +2.96 = 差距约 4.8 USDT, 等于双边手续费(~0.8 USDT) + funding fee 反向累计(~4 USDT) + 浮盈 vs 已实现盈亏的瞬时差(~0.2 USDT)。
🛠️ 已部署修复 (2026-08-05 commit 0fd498c)
1. advisor 用 fillPnl 替换 unrealizedPnl
# 之前 (line 692-696):
fills = exchange.fetch_my_trades(symbol, limit=1)
close_price = float(fills[0]['price']) if fills else 0
# pnl 仍用 unrealizedPnl (不准)
# 现在 (line 693-712):
fills = exchange.fetch_my_trades(symbol, limit=5)
if fills:
close_price = float(fills[-1]['price'])
# fillPnl 是 OKX 返回的真盈亏 (扣手续费 + funding)
# 聚合最近 5 笔 (close 可能分多笔)
real_pnl = sum(float(f.get('info', {}).get('fillPnl', 0)) for f in fills)
else:
close_price = 0
real_pnl = 0
results['closed'] = {
...
'pnl': real_pnl, # 用 fillPnl (真盈亏) 不用 unrealizedPnl (浮盈)
}
2. format_close_result() 删除 PnL 字段
# 之前:
pnl_emoji = "🟢" if c['pnl'] >= 0 else "🔴"
lines.append(f"• {pnl_emoji} 盈亏: **{c['pnl']:.2f} USDT**")
# 现在 (line 739-749):
# 2026-08-05: 不显示盈亏 (unrealizedPnl 不准, 用户从 OKX app 看真盈亏)
lines.extend([
f"📊 **{c['symbol']} 平仓确认:**",
f"• 方向: {c['side']}",
f"• 数量: {c['contracts']}张",
f"• 入场价: {c['entry']}",
f"• 平仓价: **{c['close_price']}**",
f"• 已取消止盈止损",
f"",
f"💡 实际盈亏请到 OKX app 查看 (扣手续费 + funding)",
])
3. process_signal.py format_close_message() 删除 upl 显示
# 之前 (line 581-587):
u = pos['upl']
u_emoji = '🔥' if u >= 0 else '🔴'
u_sign = '+' if u >= 0 else ''
return f"""✅ {symbol} {side_cn} {emoji} {leverage}x 已市价全平 | {trader}
{pos['side']} {pos['pos']}张 | 浮盈 {u_sign}{u:.2f} USDT {u_emoji}"""
# 现在:
return f"""✅ {symbol} {side_cn} {emoji} {leverage}x 已市价全平 | {trader}
{pos['side']} {pos['pos']}张
💡 实际盈亏请到 OKX app 查看 (扣手续费 + funding)"""
同样修改 action == 'skip' 分支的"你有反向持仓"消息,删 (浮盈 X USDT)。
🎯 修复效果
| 字段 | 之前 | 现在 |
|---|---|---|
平仓推送 盈亏: X USDT |
显示 unrealizedPnl (准度差) | 删除,显示 💡 实际盈亏请到 OKX app 查看 |
平仓推送 浮盈 X USDT |
显示 unrealizedPnl | 删除 |
平仓推送 close_price |
显示 | 保留(用户可自己算) |
平仓推送 入场价/数量/方向 |
显示 | 保留 |
advisor results['closed']['pnl'] 内部 |
unrealizedPnl | fillPnl (OKX 真成交字段, 含 funding) |
| format_execution_result 预测盈利额 | 保留 (开仓前 TP/SL 推算, 合理预估) | 不变 |
🚨 用户偏好 (重要 — 写进 SKILL)
- 用户从 OKX app 看真盈亏 — agent 推送不显示不确定的 PnL 数字
- 算不出来就删字段 — 不要用 unrealizedPnl 凑数
- 手续费 + funding fee 必须考虑 — 否则数字会差 4-5 USDT
- close_price + 入场价 足够用户自己算 → 保留这两个 + 删除 PnL 字段
- 预测盈利额 (TP/SL 推算) 是开仓前的合理预估 — 保留
📊 BTC 1.25 张 实测 (2026-08-05 12:24 北京)
| 项 | 值 |
|---|---|
| 入场价 | $64,079.9 |
| 平仓价 | $64,296.8 |
| 名义 | 1.25 × 0.01 BTC × $64,079.9 = $801 (ct_val=0.01) |
| 价格差 | $216.9 |
| 浮盈 (没扣手续费) | 1.25 × 0.01 × 216.9 = $2.71 |
| 手续费 (taker 0.05% × 2) | 0.05% × $801 × 2 = $0.80 |
| 净盈利 | $2.71 - $0.80 = $1.91 |
| app 显示 | -$1.9 (含 funding fee 反向累计) |
| advisor 推送 | +2.96 (unrealizedPnl + 没扣手续费 + 没扣 funding) |
差距 4.86 USDT ≈ funding fee + 瞬时浮盈 vs 已实现差。
🔗 关联文件
scripts/okx_position_advisor.pyline 692-721 (fetch_my_trades fillPnl)scripts/okx_position_advisor.pyline 739-749 (format_close_result)scripts/process_signal.pyline 569-602 (format_close_message)- 之前 PnL bug:
references/v4.5.43-advisor-close-position-pnl-bug.md(本次会话修复前) - 余额不足:
references/v4.5.42-insufficient-funds-explicit-notify.md(前置)