154 lines
7.4 KiB
Markdown
154 lines
7.4 KiB
Markdown
# v4.5.62 (2026-08-23) Trader 白名单生效后实战经验:dedup需手动清 + raw REST 仓位调控
|
||
|
||
**用户指令**: "是的,暂时只做熬鹰的,。" (v4.5.61 已生效) → 后续实战暴露 3 个新坑。
|
||
|
||
---
|
||
|
||
## 坑 1: dedup 误跳后需手动清 `recent_signals` 解锁
|
||
|
||
**症状**: 熬鹰同一币种连续两条信号(如"加仓"+"调杠杆"),第二条常被报 `⏭️ 重复信号,跳过`,但实际是**不同动作**(加仓 vs 调杠杆)本应分别处理。
|
||
|
||
**根因**:
|
||
- `recent_signals` 表按 `(symbol, trader)` 记录,**不区分动作**(open/add/reduce/close/调杠杆)
|
||
- 调杠杆信号算 action="modify",但 `parse_signal` 不区分 modify,被归入"已有同币种同 trader 记录"
|
||
|
||
**解锁脚本** (sqlite3):
|
||
```bash
|
||
# 通用: 清特定币种的所有 recent_signals (会强制下次该币种信号重新走 advisor)
|
||
sqlite3 ~/.hermes/trading/signal_dedup.db "DELETE FROM recent_signals WHERE symbol LIKE '%<SYMBOL>%';"
|
||
|
||
# 实战示例:
|
||
sqlite3 ~/.hermes/trading/signal_dedup.db "DELETE FROM recent_signals WHERE symbol LIKE '%HYPE%' AND trader='熬鹰资本';"
|
||
sqlite3 ~/.hermes/trading/signal_dedup.db "DELETE FROM recent_signals WHERE symbol LIKE '%MU%';"
|
||
sqlite3 ~/.hermes/trading/signal_dedup.db "DELETE FROM recent_signals WHERE symbol LIKE '%ETH%';"
|
||
sqlite3 ~/.hermes/trading/signal_dedup.db "DELETE FROM recent_signals WHERE symbol LIKE '%SKHYNIX%';"
|
||
|
||
# ⚠ 慎用: 全清 (所有 trader 重新走 advisor)
|
||
sqlite3 ~/.hermes/trading/signal_dedup.db "DELETE FROM recent_signals WHERE 1=1;"
|
||
sqlite3 ~/.hermes/trading/signal_dedup.db "DELETE FROM processed WHERE 1=1;"
|
||
```
|
||
|
||
**判断时机**: 看到 `⏭️ 重复信号,跳过` 但用户提示信号确实新的(如调杠杆跟新开仓是不同动作)→ 立即清库 + 重跑 process_signal。
|
||
|
||
---
|
||
|
||
## 坑 2: advisor 建议张数 vs 实际 execute 张数不一致 (幽灵执行)
|
||
|
||
**症状**: advisor 报 "1.0张" 但实际 execute 成功 25张 或 33张。
|
||
|
||
**实战案例 (本次 session)**:
|
||
- 熬鹰 HYPE long 2x 信号 → advisor 推 1.0张 → execute 实际成交 25张@2x (avgPx 80.17,占用保证金 $101)
|
||
- 熬鹰 HYPE 调杠杆 2→5x 信号 → execute 实际 HYPE long 25→33 张 (杠杆升级时**重新加仓**了)
|
||
|
||
**根因**: `okx_position_advisor.py` 计算 `contracts` 字段时按 `availBal × pct / margin_per_contract`,但 execute 路径走 ccxt 的 `create_order` 时可能**忽略 contracts 字段**或**用全仓计算**。
|
||
|
||
**判定规则** (硬):
|
||
- advisor JSON 返回 `contracts < 10` 但 execute 后 check_account 显示 `contracts > 20` → **advisor 报的 contracts 不可信**
|
||
- execute 完成后**必须跑** `check_account.py` 反查实际张数,不能信 advisor
|
||
|
||
**回复模板** (execute 后必查):
|
||
```
|
||
[实测] {symbol} {side} {X}张 avgPx={x} mark={y} upl={z}; USDT{可用} / {权益}
|
||
```
|
||
**禁止**: 直接引用 advisor 返回的 contracts 数字。
|
||
|
||
**已知幽灵币种** (本次 session 验证):
|
||
- HYPE-USDT-SWAP (advisor 1张 → 实际 25/33 张)
|
||
- SNDK-USDT-SWAP (已知 execute 失败,v4.5.38 已记录)
|
||
- 1000PEPE-USDT-SWAP (execute 漏处理,v4.5.37 已记录)
|
||
|
||
**修复方向** (下次必修):
|
||
- [ ] okx_position_advisor.py 的 execute 路径必须 raw REST 反查 contracts,与 advisor JSON 对比,不一致就 warn + 用反查值
|
||
- [ ] process_signal 主流程在 `_okx_raw_request('GET', '/api/v5/account/positions')` 后写 `actual_contracts` 字段
|
||
- [ ] advisor JSON 加 `{"execute_verified": True, "actual_contracts": X}` 字段
|
||
|
||
---
|
||
|
||
## 坑 3: 用户手动 raw REST 加仓模板 (7 成 / 8 成仓位)
|
||
|
||
**用户指令序列**:
|
||
- "这个可以跟单了" (MSTR short 1x 信号,资金够但 advisor 报性价比低跳过)
|
||
- "按 8 成来开" → manual 1 张 MSTR short @5x (实际只占 17%,没到 8 成)
|
||
- "不是,只留 2 成的余额" → 再加 3 张 MSTR short → 占用 68% (≈7 成) ✓
|
||
|
||
**通用公式**:
|
||
```
|
||
可用USDT × 目标占比 = 目标占用保证金
|
||
目标占用保证金 / 单张保证金 = 目标张数
|
||
```
|
||
|
||
**OKX USDC 永续单张保证金** (实测本次 session):
|
||
| 币种 | 杠杆 | 单张保证金 | 名义/张 |
|
||
|---|---|---|---|
|
||
| MSTR-USDT-SWAP | 1x | $269.99 | $126.80 |
|
||
| MSTR-USDT-SWAP | 5x | $25.44 | $634.00 |
|
||
| BTC-USDT-SWAP | 5x | ~$13,300 | $66,000 (1张) |
|
||
| ETH-USDT-SWAP | 5x | ~$485 | $2,420 (1张) |
|
||
|
||
**手动 execute 模板** (复制此块到 `/tmp/open_X.py`):
|
||
```python
|
||
import json, time, hmac, hashlib, base64, requests
|
||
|
||
def okx_post(path, body, t=15):
|
||
creds = open('/home/openclaw/.bashrc').read()
|
||
k = s = pw = None
|
||
for l in creds.splitlines():
|
||
if l.startswith('export OKX_API_KEY='): k = l.split('=', 1)[1].strip().strip('"')
|
||
elif l.startswith('export OKX_SECRET='): s = l.split('=', 1)[1].strip().strip('"')
|
||
elif l.startswith('export OKX_PASSPHRASE='): pw = l.split('=', 1)[1].strip().strip('"')
|
||
ts = time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime())
|
||
method = 'POST' # ⚠ 必须是字符串, 不要写 method=POST (NameError)
|
||
body_str = json.dumps(body)
|
||
pre = ts + method + path + body_str
|
||
sig = base64.b64encode(hmac.new(s.encode(), pre.encode(), hashlib.sha256).digest()).decode()
|
||
h = {'OK-ACCESS-KEY': k, 'OK-ACCESS-SIGN': sig, 'OK-ACCESS-TIMESTAMP': ts,
|
||
'OK-ACCESS-PASSPHRASE': pw, 'Content-Type': 'application/json'}
|
||
r = requests.post('https://www.okx.com' + path, headers=h, data=body_str,
|
||
timeout=t, proxies={'http': 'http://127.0.0.1:7890',
|
||
'https': 'http://127.0.0.1:7890'})
|
||
return r.json()
|
||
|
||
# 示例: MSTR short 0.01 张 (最小变动单位, 先小试)
|
||
body = {"instId": "MSTR-USDT-SWAP", "tdMode": "cross", "side": "sell",
|
||
"posSide": "net", "ordType": "market", "sz": "0.01"}
|
||
print(json.dumps(okx_post('/api/v5/trade/order', body), ensure_ascii=False, indent=2))
|
||
```
|
||
|
||
**⚠ 注意 `name='POST'` 拼写** — 之前 1 次踩坑 (NameError: name 'POST' is not defined),method 应为字符串 `'POST'`。
|
||
|
||
**回查模板** (`scripts/check_account.py` 已封装, 直接调):
|
||
```bash
|
||
timeout 30 python3 ~/.hermes/skills/trading/okx-auto-position/scripts/check_account.py MSTR-USDT-SWAP
|
||
```
|
||
|
||
---
|
||
|
||
## 用户行为模式(本次新增)
|
||
|
||
1. **"X成来开"** → 留对应比例余额, 开对应比例仓位
|
||
- "8 成来开" = 留 2 成余额, 用 8 成余额开仓
|
||
- "7 层" / "7 成" 同义
|
||
- 实际执行: 我算的总和与字面不符时, **用户会纠正** ("不是,是只留 2 成")
|
||
2. **用户对小币种手动加仓有耐心** — MSTR 1x 信号 advisor 报"性价比低"跳过,用户主动说"跟单了"
|
||
3. **用户关心的是"是否真的下单", 不是 advisor 报了什么** — execute 后必查 check_account.py
|
||
|
||
---
|
||
|
||
## 本次净状态(白名单生效后)
|
||
|
||
- USDT $149.60 (无冻结)
|
||
- MSTR short 4.01张@5x (avgPx 126.04,浮亏-$0.21,占用 68% 仓位 = 7 成)
|
||
- 强平价 160.00 (距 $34, 安全)
|
||
- 白名单生效,只熬鹰资本触发 execute
|
||
- 其他 trader(矿工/予与/麻吉/风寻/狙击手)静默跳过
|
||
|
||
---
|
||
|
||
## 部署清单(下次 session 第一件事)
|
||
|
||
- [ ] parse_signal() 区分 modify (调杠杆) vs add (加仓), 不混进 dedup 记录
|
||
- [ ] recent_signals 表加 `action` 字段 (open/add/reduce/close/modify)
|
||
- [ ] okx_position_advisor.py execute 后 raw REST 反查, 实际 contracts 写入 advisor JSON
|
||
- [ ] process_signal 主流程加 `actual_contracts` 字段, 与 advisor JSON 对比 warn
|
||
- [ ] manual_order.py 模板沉淀到 scripts/ (避免每次重新写)
|
||
- [ ] add scripts/manual_position_sizing.py 算 7 成/8 成张数 |