163 lines
8.9 KiB
Markdown
163 lines
8.9 KiB
Markdown
# v4.5.93 (2026-09-18) Signal Storm Cookbook — Dedup Clear, Lock Flow, Manual Execute with Proxy Flaky
|
||
|
||
**会话**: 9/16-9/18 全周期实战 — 信号风暴中(熬鹰资本/币安实盘/FOMO/交易信号 4 个 trader 同时活跃, 每条信号间隔 < 5 分钟), 反复踩到同一组边缘 case. 沉淀出一套**快速判断 + 手动执行**cookbook.
|
||
|
||
## 1. 4 个熬鹰号 lock 冲突诊断与两步法
|
||
|
||
**症状**: 同一币种在 `position_locks` 中存在**两条记录**, 一条是 `熬鹰资本 long`, 一条是 `熬鹰币安实盘 short`, trader 不一致 + 方向不一致.
|
||
|
||
**诊断**:
|
||
```bash
|
||
sqlite3 ~/.hermes/trading/signal_history.db "SELECT * FROM position_locks WHERE symbol='<COIN>';"
|
||
```
|
||
|
||
**正解 — 两步法** (直接 acquire 同 trader 反向**会失败**):
|
||
```python
|
||
from signal_tracker import release_lock, acquire_lock
|
||
release_lock("<COIN>", "<OLD_TRADER>", auto=True) # 释放旧锁
|
||
acquire_lock("<COIN>", "<NEW_TRADER>", "<NEW_SIDE>", reason="手动反转锁", auto=False) # 新锁
|
||
```
|
||
|
||
**实战**: 9/16 ETH long 由 `熬鹰资本 long` 反转为 `熬鹰币安实盘 short` 时踩到. lock 表本身就是 sqlite row,没有方向字段,只有 `trader+symbol+side` 三元组. 手动两步法绕开 `check_signal_lock` 的方向判断.
|
||
|
||
## 2. Dedup 清理 routine (单条信号重跑)
|
||
|
||
**症状**: 信号由于网络/proxy 失败没真下, 但 `signal_dedup.db::processed.msg_hash` 已 record; 再跑一次直接 skip; 但 user 想重做(例如修改 advisor 参数后想再看一次).
|
||
|
||
**正解 — 清 dedup 表重跑**:
|
||
```bash
|
||
sqlite3 ~/.hermes/trading/signal_dedup.db "DELETE FROM processed WHERE 1=1;"
|
||
# 也清 recent_signals 同币种
|
||
sqlite3 ~/.hermes/trading/signal_dedup.db "DELETE FROM recent_signals WHERE symbol='<COIN>';"
|
||
```
|
||
|
||
**注意**: 不要删整个 db 里的数据, 只删 processed (msg_hash 索引) + 该币种的 recent_signals. 其他币种的 dedup 不动.
|
||
|
||
## 3. Manual Execute with Proxy Flaky — 完整 5 级回退路径
|
||
|
||
proxy 抽风时 `process_signal.close_position_raw` 返回 `None`, 触发 null guard 返回失败. 此时手动 raw REST 是唯一选项. **5 级回退按序尝试**:
|
||
|
||
```
|
||
Level 1: process_signal 重跑 (sleep 20s, 清 dedup)
|
||
└→ sleep 20 && sqlite3 ... "DELETE FROM processed" && process_signal.py <<EOF ... EOF
|
||
|
||
Level 2: 手动 raw REST (模板见 templates/manual_order_template.py)
|
||
└→ cat > /tmp/close_<COIN>.py <<PYEOF
|
||
# 含 okx_post(path, body) 函数 + reduceOnly=True + 对应 side
|
||
# 平 long: side=buy; 平 short: side=sell ← 易写反
|
||
body={"instId":"<COIN>-USDT-SWAP","tdMode":"cross","side":"<SIDE>","posSide":"net",
|
||
"ordType":"market","sz":"<QTY>","reduceOnly":True}
|
||
PYEOF
|
||
python3 /tmp/close_<COIN>.py
|
||
|
||
Level 3: 验证 (check_account.py)
|
||
└→ timeout 30 python3 check_account.py # 确认 has_position=false
|
||
|
||
Level 4: 解锁 (手动平/手动execute后必做)
|
||
└→ from signal_tracker import release_lock
|
||
release_lock("<COIN>", "<TRADER>", auto=True)
|
||
|
||
Level 5: 静默 / 推 QQ 告诉 user
|
||
└→ push_to_qq 或 silent 完成
|
||
```
|
||
|
||
**关键铁律**:
|
||
- ❌ **禁止以"测试"为由调 raw REST 下单** (真钱, 0.01 张也是钱). 用 `check_account.py` 或 `okx_proxy_test.sh` 才是真测试.
|
||
- ✅ 平 long 用 `side=buy`, 平 short 用 `side=sell` (新手易错)
|
||
- ✅ `tdMode=cross, posSide=net, reduceOnly=True` 三件套必须齐
|
||
- ✅ `sz` 是张数不是币数; ZEC 1 张 = 0.01 ZEC (contractSize ≠ 1)
|
||
- ✅ 手动 execute 后**必须** record_position_history 或 release_lock (audit trail / 防止 72h 锁残留挡信号)
|
||
|
||
## 4. OKX 59108 降杠杆错误 — Cross 模式分账户余额不足
|
||
|
||
**症状**: `set-leverage` 时收到 `code=59108, msg="Your account leverage is too low and has insufficient margins. Please increase the leverage."`
|
||
|
||
**根因**: OKX cross 模式下, 分账户余额(`availBal`) 不足以支持新杠杆要求的初始保证金. 不是"杠杆数字"问题.
|
||
|
||
**正解**:
|
||
1. **先减仓**到分账户余额够降杠杆的位置, 再 `set-leverage`
|
||
2. 或者**保留高杠杆**(熬鹰调杠杆信号本身就是风控信号, 减仓已部分实现风控, 杠杆不变也行)
|
||
3. **不要重试**, 不需要 fallback, 返回失败就静默 (调杠杆失败不影响现有仓位)
|
||
|
||
**实战**: 9/16 熬鹰币安 ETH 5→4x 调杠杆尝试失败 (你分账户余额不够 4x 保证金), ZEC 4→2x 失败, BTC 10→5x 失败. 三次都正确**不重试**, 仓位继续运行.
|
||
|
||
## 5. Signal Source Unknown 闸 vs Whitelist 闸 — 两层独立闸
|
||
|
||
**两闸独立**:
|
||
- **白名单闸**: trader 在不在 `whitelist.json` 配置的白名单里
|
||
- **未知 trader 闸**: trader='未知' (parse_signal 没匹配到任何 trader 字段)
|
||
|
||
**两者都需过**, 顺序: 未知闸先 → 白名单闸后.
|
||
|
||
**实战 (9/9 ZEC close 信号)**:
|
||
- trader='熬鹰FOMO合约实盘' (新 trader, 9/9 之前白名单只有"熬鹰资本")
|
||
- 未知闸过 (trader 非 '未知')
|
||
- 白名单闸拦 (trader 不在白名单)
|
||
- → 跳过不 execute
|
||
|
||
**修复后 (v4.5.77)**: 即使 close 信号也走白名单闸. 9/9 user "那是新trader, 不在白名单, 为什么要平?" 后改为 close 也必须 trader 匹配.
|
||
|
||
## 6. 4 熬鹰号 Trader Variants — 同一人不同平台
|
||
|
||
**实际**: 熬鹰资本 / 熬鹰币安实盘 / 熬鹰FOMO合约实盘 / 熬鹰交易信号 = **同一人** (熬鹰本人在 OKX/币安/FOMO/交易信号 4 个平台账号的直播号). 9/10 user 明确 "一个意思, 都是熬鹰的" → whitelist.json 扩为 4 个.
|
||
|
||
**对比**:
|
||
| Trader | 是否同一人 | 是否白名单 |
|
||
|---|---|---|
|
||
| 熬鹰资本 | 熬鹰本号 | ✅ |
|
||
| 熬鹰币安实盘 | 同上 | ✅ (9/10 扩入) |
|
||
| 熬鹰FOMO合约实盘 | 同上 | ✅ (9/10 扩入) |
|
||
| 熬鹰交易信号 | 同上 | ✅ (9/10 扩入) |
|
||
| 巨鲸内幕哥ca88 | 不同人 | ❌ |
|
||
| 予与实盘 | 不同人 | ❌ |
|
||
|
||
**拦截后 trader 赚大钱怎么办**: 9/9 session 中熬鹰FOMO SKHX +$9.6k / 币安 BTC +$17.3k / 币安 SKHYNIX +$49k 都被白名单拦了, user 9/10 澄清"都是熬鹰的" → 立即扩名单. **教训**: 名单归属最终解释权在 user, 不要默认只留主号 — 拦截后如果 trader 持续盈利, 应该问 user "这个 trader 跟你白名单 trader 是同一人吗" 而不是默认只留主号.
|
||
|
||
## 7. 推送格式变化 — "当前全部持仓" 汇总播报识别
|
||
|
||
**新格式**:
|
||
```
|
||
【熬鹰币安实盘】
|
||
熬鹰当前全部持仓
|
||
【持仓数量】:1
|
||
1. 币种:XXX 永续 | 全仓 | 5x
|
||
【方向】:做空 🟥
|
||
... (持仓量/开仓均价/当前价格/标记价格/保证金/实际杠杆/强平价格/浮动收益/已实现盈亏)
|
||
【总保证金】:xxx USDT
|
||
...
|
||
```
|
||
|
||
**特点**: 用全角冒号 `:` (不是 `:`), 编号列表 `1.`, 字段用空格/换行分隔, **无【】标签**.
|
||
|
||
**parse_signal 行为**: parse 失败 → `⚠️ 无法解析信号` → 无操作. **这是好事**: 汇总播报不是真交易动作, parse 拒绝即安全.
|
||
|
||
**不要**为新格式适配 parse_signal (改了反而会误 execute 状态推送).
|
||
|
||
**如果未来熬鹰资本主号也发新格式**, 需要新增分类 `update_only` (已在 v4.5.77 加入) 跳过即可, 不必重新适配.
|
||
|
||
## 8. 单币 70% 上限 skip 路径
|
||
|
||
**症状**: advisor 报 0.85 张, 但 process_signal 在 execute 前 hard pre-trade check (v4.5.89+ 之后) 检测到加仓会让该币占用超 70%, 返回 `⏭️ 单币超限跳过 | <COIN> | $X > $Y`.
|
||
|
||
**实战 (9/16-9/18 BTC 风暴)**: 熬鹰BTC short 一连串加仓信号 (6.23→16.79→22.03→27.27→30.61), 你BTC short 2.58张已经接近 65% 占用, 后续加仓信号全部 skip. **正确行为**: skip 即可, 不要手动加仓 — 加仓可能超 70% 触发单币爆仓.
|
||
|
||
**诊断**: `process_signal.py` 输出的 `⏭️ 单币超限跳过 | <COIN> | $X > $Y` 中 `$X` 是该币种建议占用, `$Y` 是当前 max cap (total × 70%).
|
||
|
||
## 9. 不要让用户提醒"先查再说" — 这个违规出现了 3+ 次
|
||
|
||
**踩坑**: 多次让 user 提醒 agent 查持仓/查锁 (而不是自己先查), user 原话:
|
||
- "你要去查啊, 问我, 还要你干吗" (2026-09-01)
|
||
- "内存放不下的时候呢?" 衍生 (2026-09-16)
|
||
- 9/17 session 内让 user 问"你持仓呢?我等下"
|
||
|
||
**正解**: 任何状态查询 (持仓/余额/锁/业绩/价格) **必须**先 `check_account.py` 再回答, 严禁反问"你持仓是什么?". 加到 memory (已存) + skill 的每个跟单相关入口.
|
||
|
||
## 10. 一句话口诀
|
||
|
||
> **Qdrant 第一但 Qdrant 不信** (历史线索) · **live check_account 是唯一真值** (latency +3s, 必查)
|
||
> **advisor 报数 ≠ execute 实际** (1.5x~4200x 偏差) · **推送成功 ≠ 订单落地** (manual verify 必做)
|
||
> **decreased leverage OKX 59108** = cross 模式分账户余额不足 · **先减仓或不变, 不重试**
|
||
> **手动 execute 必 release_lock** · **手动 execute 必 record_position_history**
|
||
> **任何 trader 拦截后大赚 → 问 user 是不是同一人** · **拦截名单归属最终解释权在 user**
|
||
> **白名单配置驱动** (`whitelist.json`) · **绝不硬编码 trader/币种/阈值/比例**
|