146 lines
5.7 KiB
Markdown
146 lines
5.7 KiB
Markdown
# v4.5.64 (2026-08-26) 调杠杆信号必须自动跟进 + raw REST 参数顺序陷阱
|
||
|
||
**本次 session 在 v4.5.63 (手动锁 + symbol 一致性 + ETH ghost close) 基础上的新教训**
|
||
|
||
---
|
||
|
||
## 教训 1: 调杠杆信号不在 advisor 的"性价比低"覆盖范围
|
||
|
||
**用户质问**: "这个怎么没有跟调杠杆?"
|
||
|
||
**症状**: 熬鹰发出 `🔧 注意, 大佬修改了杠杆 3→4x` 信号, process_signal 分类为新开仓 (`'open'`), 进 advisor → advisor 看 avgPx × 当前价格 × 杠杆 → 报"1.4张 性价比低" 或 "0.01张 性价比低" → 跳过。结果: 用户的 ETH long 1.4张@3x 没自动调到 4x。
|
||
|
||
**根因**:
|
||
- `classify_signal()` 没有 `adjust_leverage` 类型, 信号被默认归为 `'open'`
|
||
- advisor 只计算 open/add/reduce 的仓位, 不处理 set-leverage
|
||
- 白名单闸 (`'open', 'add', 'reduce'`) 也不会拦到调杠杆, 但调杠杆信号照样进 advisor → 报"性价比低" → 跳过
|
||
|
||
**修复** (已合入 `scripts/process_signal.py`):
|
||
|
||
1. **`classify_signal()` 加 `adjust_leverage` 类型识别**:
|
||
|
||
```python
|
||
# 加仓信号
|
||
if '加仓' in text or '追仓' in text:
|
||
return 'add'
|
||
|
||
# 调杠杆信号 (2026-08-26: 必须跟, 不算性价比低 — 熬鹰调整杠杆是策略节奏)
|
||
if '修改了杠杆' in text or '调整了杠杆' in text or '调杠杆' in text:
|
||
return 'adjust_leverage'
|
||
|
||
# 默认为新开仓
|
||
return 'open'
|
||
```
|
||
|
||
2. **白名单闸加 `adjust_leverage`**:
|
||
|
||
```python
|
||
if _sig_type_for_gate in ('open', 'add', 'reduce', 'adjust_leverage') and trader not in _TRADER_WHITELIST:
|
||
return f"⏭️ 跳过: trader [{trader}] 不在白名单 | {symbol} {side}"
|
||
```
|
||
|
||
3. **process_signal() 主流程加独立分支** (在 close 信号之后, 2分钟窗口 dedup 之前):
|
||
|
||
```python
|
||
# 调杠杆信号 (2026-08-26: 熬鹰调整杠杆要跟, 不走 advisor, 直接 set-leverage)
|
||
if signal_type == 'adjust_leverage':
|
||
dedup_conn = init_dedup_db()
|
||
if is_duplicate(dedup_conn, text, symbol, trader):
|
||
dedup_conn.close()
|
||
return "⏭️ 重复信号,跳过"
|
||
record_signal(dedup_conn, text, symbol, trader)
|
||
dedup_conn.close()
|
||
symbol_usdt = fields['symbol']
|
||
new_lev = int(fields.get('leverage') or '10')
|
||
lev_result = adjust_leverage_raw(symbol_usdt, new_lev)
|
||
if lev_result and lev_result.get('ok'):
|
||
msg = f"⚙️ **杠杆已调整** | {symbol_usdt} → {new_lev}x"
|
||
push_to_qq(msg)
|
||
return f"✅ 调杠杆: {symbol_usdt} → {new_lev}x"
|
||
else:
|
||
err = lev_result.get('error', '未知')
|
||
return f"❌ 调杠杆失败: {err} | {symbol_usdt}"
|
||
```
|
||
|
||
**为什么不走 advisor?**
|
||
- advisor 只算 open/add/reduce 仓位, 不算 set-leverage
|
||
- 走 advisor 会被 `性价比低` 闸拦掉
|
||
- 调杠杆本质是**单参数调用** (POST /api/v5/account/set-leverage), 不需要 advisor 的仓位计算
|
||
|
||
---
|
||
|
||
## 教训 2: `_okx_raw_request` 参数顺序陷阱 (POST body 必须 keyword arg)
|
||
|
||
**症状**: 调用 `adjust_leverage_raw` 第一次报 `'❌ 调杠杆失败: Incorrect json data format'`
|
||
|
||
**根因**:
|
||
|
||
```python
|
||
def _okx_raw_request(method, path, params=None, body=None, timeout=15):
|
||
...
|
||
```
|
||
|
||
签名是 `(method, path, params, body, timeout)`, 第 3 位是 `params`, 第 4 位才是 `body`。
|
||
|
||
**错误写法** (第 3 位传 body, 被当成 params):
|
||
```python
|
||
resp = _okx_raw_request('POST', '/api/v5/account/set-leverage', body)
|
||
# 实际上 body 被当 params={...} 传了 → OKX 服务端签名校验失败
|
||
```
|
||
|
||
**正确写法**:
|
||
```python
|
||
resp = _okx_raw_request('POST', '/api/v5/account/set-leverage', body=body)
|
||
```
|
||
|
||
**SOP (硬规则, v4.5.64 起执行)**:
|
||
- 任何 `_okx_raw_request` POST 调用 → body 必须 keyword arg (`body=...`)
|
||
- 这是 v4.5.63 ETH ghost close 调查时埋下的同源 bug (虽然当时没暴露, 因为 close 路径用的是 GET)
|
||
- v4.5.62 手动 execute 模板 (manual_order.py) 也可能踩这个坑 → **下次 session 第一件事检查 manual_order.py 的 okx_post 函数**
|
||
|
||
**验证**:
|
||
```bash
|
||
# 调杠杆信号后, check_account.py 应该看到新的 lever 字段
|
||
python3 ~/.hermes/skills/trading/okx-auto-position/scripts/check_account.py <INST_ID>
|
||
# 检查 "lever" 字段 = 目标倍数
|
||
```
|
||
|
||
---
|
||
|
||
## 实战时间线 (本次 session)
|
||
|
||
1. 用户 ETH long 1.4张@3x 已开仓 (v4.5.63 残留)
|
||
2. 熬鹰 ETH 调杠杆 3→5x 信号进来 → process_signal 走 advisor → 报"性价比低" → **跳过**
|
||
3. 用户质问: "这个怎么没有跟调杠杆?"
|
||
4. 我手动 raw REST set-leverage 4x → USDT 占用从 $87.72 → $70.12 (降, 因为杠杆升)
|
||
5. 用户: "要 [改代码]"
|
||
6. 我加 `adjust_leverage_raw` + `adjust_leverage` 类型 + 主流程分支
|
||
7. 测试调杠杆信号 → 先报 `'❌ Incorrect json data format'` → 找到参数顺序 bug
|
||
8. 修复后: `✅ 调杠杆: ETH → 5x` (从 4x 升 5x)
|
||
|
||
**最终持仓**:
|
||
- ETH long 1.4张@5x (avgPx 2486.74, 浮盈+$2.45, 占用 $70.12)
|
||
- USDT 可用 $87.99 / 权益 $158.10
|
||
- ETH 锁 ✅ 熬鹰资本 long (手动锁)
|
||
- MSTR short 4.01张@5x (avgPx 126.04, 浮亏-$0.21, 占用 $101.12)
|
||
|
||
---
|
||
|
||
## 部署清单 (下次 session 第一件事)
|
||
|
||
- [ ] `manual_order.py` 的 okx_post 函数: 确认所有 POST 都用 keyword arg `body=body`, 不能位置传 body
|
||
- [ ] process_signal 加 `adjust_leverage_raw` 调用也走 dedup (已实现)
|
||
- [ ] 测试: 调杠杆信号进来 → 自动 set-leverage + 推 QQ
|
||
- [ ] 调杠杆失败时: 区分"无持仓可调" (要查持仓) vs "API 报错" (重试)
|
||
- [ ] 白名单闸的 signal_type 集合统一抽到顶层常量 (现在散落在多处)
|
||
|
||
---
|
||
|
||
## 跨 session 索引
|
||
|
||
- v4.5.38: 实时数据查询硬规则
|
||
- v4.5.53: trader='未知' 闸
|
||
- v4.5.61: trader 白名单 (只跟熬鹰)
|
||
- v4.5.62: dedup 手动清 + 手动加仓模板
|
||
- v4.5.63: 手动锁 + symbol 一致性
|
||
- **v4.5.64 (本次)**: 调杠杆信号自动跟进 + _okx_raw_request 参数顺序陷阱 |