# 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 '%%';" # 实战示例: 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 成张数