Files
Hermes-Skills/okx-auto-position/references/okx-pnl-from-bills-api.md
T

94 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OKX 已实现盈亏 = /account/bills balChg (2026-09-22)
## 核心结论
**永远不要用 `(exit - entry) * 张数 * ctVal` 自己算 pnl** —— OKX app 显示的真实数 = `/api/v5/account/bills` 的 `balChg` 累加。
实测对账:
| 币种 | 公式算 | OKX app | 用 bills 拿 | 差 |
|---|---|---|---|---|
| BTC (平 2.58 张) | 取决于入场价 | -$46.51 | **-$46.14** | 0.37 (funding 几小时) |
| ZEC (平 157 张) | +$10.79 假设 | +$13.44 | **+$14.42** | 0.98 (funding 累计) |
## API: /api/v5/account/bills
参数:
```
GET /api/v5/account/bills
instId: ZEC-USDT-SWAP # 不传也返回全部 (按 instType 过滤)
instType: SWAP # 必填, 否则 50014
type: 2 # 2 = 交易/手续费类
subType: 1 / 2 # 1=已实现盈亏账单, 2=单笔成交
limit: 50
begin: <ms-timestamp> # 7天前
```
返回字段 (per item):
- `ts`: 时间戳 (毫秒)
- `instId`: 币种
- `type`: 2 (永不变)
- `subType`: 1 (已实现盈亏/手续费) 或 2 (单笔成交)
- `pnl`: 单笔盈亏 (subType=2 有值, subType=1=0)
- `balChg`: **真实数** (含手续费/funding) ← 这就是 OKX app 显示值
- `fillPx`: 成交价 (subType=2 有)
- `fillSz`: 成交张数 (subType=2 有)
## 算法 (唯一可信)
```python
def _fetch_close_pnl(symbol_usdt):
inst_id = f"{symbol_usdt}-USDT-SWAP"
bills = _okx_raw_request('GET', '/api/v5/account/bills', {
'instId': inst_id, 'instType': 'SWAP', 'type': '2',
'limit': '50', 'begin': str(<7d-ago-ms>)
})
# 找最新一次"平仓"事件 = 绝对值最大的 type=2 账单
# (过滤掉手续费 subType=1, 绝对值 < 5 的)
latest_ts = None
for b in bills['data']:
if b['type'] != '2':
continue
st = b['subType']
bal = float(b['balChg'])
if st == '1' and abs(bal) < 5.0: # 过滤手续费
continue
ts = int(b['ts'])
if latest_ts is None or ts > latest_ts:
latest_ts = ts
# 累加同一时刻 ±30 秒所有 type=2 账单
pnl_total = sum(
float(b['balChg']) for b in bills['data']
if b['type'] == '2' and abs(int(b['ts']) - latest_ts) <= 30000
)
return latest_ts, pnl_total
```
## 推送格式 (已集成 process_signal.py)
```
✅ ZEC 做多 🟩 10x 已市价全平 | 熬鹰
long 157张 @ 1247.50 → 平仓价 $1248.19
⏱ 持仓: 1天3小时
💰 实际盈亏: **+$14.42** (OKX 实测, 含手续费/funding)
💡 OKX 历史订单实数据
```
## 关键 bug 教训 (2026-09-22)
### ❌ 旧算法 (错的)
用 `/api/v5/trade/orders-history` 的 `info.pnl` 字段 — **只算单笔成交盈亏**,**不含手续费和 funding**,与 OKX app 不符。
### ❌ 早期尝试 (错)
用 `(exit - entry) * contracts * ctVal` 自己算 — **不包含手续费和 funding**,**实际是大码折扣**。
### ✅ 唯一对的
`/api/v5/account/bills` 的 `balChg` 字段 + 30秒窗口累加 = OKX app。
## 与 cron 30秒精度配合
`check_upl_notify.py` 也算 pnl —— 如果做推送,可以用同样的 bills 接口拿**实时已实现**+ `fetch_positions` 的 UPL 做**总盈亏**。
## 相关代码
- `process_signal.py: process_signal_close() close_position_raw()` — 平仓函数
- `process_signal.py: _fetch_close_pnl_details()` — bills 累加 (实际盈亏拿法)
- `check_upl_notify.py: should_notify()` — UPL 跨 100 倍数推送