Files
Hermes-Skills/okx-auto-position/references/v4.5.62-2026-08-23-dedup-manual-clear-and-raw-rest-position-sizing.md
T

7.4 KiB
Raw Blame History

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):

# 通用: 清特定币种的所有 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):

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 已封装, 直接调):

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 成张数