Files
Hermes-Skills/okx-auto-position/references/v4.5.43-close-pnl-delete-display.md

5.0 KiB
Raw Permalink Blame History

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 fee
  • format_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)

  1. 用户从 OKX app 看真盈亏 — agent 推送不显示不确定的 PnL 数字
  2. 算不出来就删字段 — 不要用 unrealizedPnl 凑数
  3. 手续费 + funding fee 必须考虑 — 否则数字会差 4-5 USDT
  4. close_price + 入场价 足够用户自己算 → 保留这两个 + 删除 PnL 字段
  5. 预测盈利额 (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.py line 692-721 (fetch_my_trades fillPnl)
  • scripts/okx_position_advisor.py line 739-749 (format_close_result)
  • scripts/process_signal.py line 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 (前置)