127 lines
5.0 KiB
Markdown
127 lines
5.0 KiB
Markdown
# 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
|
||
|
||
```python
|
||
# 之前 (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 字段
|
||
|
||
```python
|
||
# 之前:
|
||
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 显示
|
||
|
||
```python
|
||
# 之前 (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` (前置) |