trading skills: 文档同步 (单币上限规则/平仓盈亏字段/静默规则/推送模板)
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# 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 倍数推送
|
||||
Reference in New Issue
Block a user