Files
Hermes-Skills/okx-auto-position/references/v4.5.68-2026-08-30-phantom-execute-and-cross-leverage-lower-rejection.md
T

13 KiB

v4.5.68 (2026-08-30) Phantom Execute 加剧 + Cross 模式降杠杆被拒 + 调杠杆信号 "3→4" 解读

详细复现: 本次 session

三件新事件 (本次 session 续 v4.5.66 / v4.5.67)

1. Phantom Execute 加剧 — 几乎每个熬鹰信号都幽灵成交

症状: process_signal 报 ⏭️ 跳过: 信号源未知 | <X> <side> 或 ⏭️ 跳过: 性价比低 | <X> <side>,但 5 秒后 check_account.py 显示实际仓位出现。

本次复现的幽灵 execute:

信号 advisor 报 实际成交
SKHYNIX short 2x "跳过 信号源未知" 0.145 张@2x ✓
BTC long 5x "跳过 信号源未知" 0.63 张@5x ✓
HYPE long 2x "跳过 信号源未知" 26 张@2x ✓
HYPE long 2x (信号 2) "1张 性价比一般" 25 张@2x ✓ (vs advisor 25 张 OK, 但 signal 2 是 1 张信号)
TRUMP long 1x "137张 性价比高" 586 张@1x ✗ (4.3x 超额)
SKHYNIX long 1x (去低判断后) "0.065张 性价比低" 0.098 张@1x ✓
SKHYNIX long 2x 加仓 "0.039张 性价比低" 0.407 张@2x ✗

根因 (叠加 3 个):

  1. trader='未知' 闸没拦 execute 路径: process_signal() 在 classify_signal() 后加了闸,但 advisor 的 execute 路径 (okx_position_advisor.py --execute) 是独立脚本,直接读信号文本 + 直接调 ccxt.create_order, 完全不经过 process_signal 主流程
  2. advisor 的 contracts 字段不可信: advisor JSON 返回的 contracts 是基于可用 USDT ×45% / 每张保证金 计算,但实际 ccxt 下单时用了不同的 ctVal / 最小变动单位计算器
  3. "性价比低"判断在 advisor 内层: v4.5.66 移除外层判断,但 advisor JSON 仍带 rating_text: 性价比低 标签, 用户看到后误以为没跟单

实测新发现: 即使 process_signal 主流程加了 trader='未知'闸 + 白名单闸 + 调杠杆闸,advisor 的独立 execute 路径 仍会成交。这是 v4.5.54 / v4.5.57 的延伸, 但 v4.5.66 没堵上。

修复方向 (下次必修):

  • okx_position_advisor.py 加 trader 闸 + trader 白名单 (跟 process_signal 同步)
  • advisor execute 后强制调 check_account.py 反查实际仓位, 反查为空时推 QQ 失败
  • advisor JSON 的 contracts 字段改名为 suggested_contracts, 加 actual_contracts 字段(后置填充)
  • advisor 的 rating_text: 性价比低 字段移除 (用户已说"把性价比去掉")

临时 workaround (本次 session 实战):

执行任何 advisor 后 → 强制 sleep 5s + check_account.py 反查 → 有新增就记录, 无新增就推 QQ "实际未成交"

# 实战模板
python3 process_signal.py "signal" 
sleep 5
python3 check_account.py <X>-USDT-SWAP
# 对比 advisor JSON.contracts vs check_account.contracts

2. Cross 模式降杠杆被 OKX 拒绝 (Your account leverage is too low and has insufficient margins)

症状: SKHYNIX long 0.098 张@5x 持仓 → 熬鹰信号 修改了杠杆 5→2 → 调 set-leverage API → OKX 返回 code: 59108, msg: Your account leverage is too low and has insufficient margins. Please increase the leverage.

复现命令:

body = {'instId': 'SKHYNIX-USDT-SWAP', 'lever': '2', 'mgnMode': 'cross'}
resp = _okx_raw_request('POST', '/api/v5/account/set-leverage', body=body)
# → {"code":"59108","msg":"Your account leverage is too low and has insufficient margins..."}

根因: OKX cross 模式下, 杠杆下调会要求"按新杠杆计算所需初始保证金 ≥ 当前可用 USDT"。SKHYNIX 0.098 张@2x 需要 ≈$60 保证金, 但用户 USDT 主要压在 ETH/TRUMP 持仓上, SKHYNIX 分账户可用余额 < $60。

OKX API 文档事实 (硬):

  • 升杠杆: 总是允许 (只要新杠杆不超过币种上限)
  • 降杠杆: 必须满足 新杠杆所需初始保证金 ≤ 当前可用 USDT + 已冻结保证金, 否则拒
  • 用户当前持仓杠杆 ≥ 信号目标 → 降杠杆被拒
  • 用户当前持仓杠杆 < 信号目标 → 升杠杆, 正常

修复方向:

  • adjust_leverage_raw 失败时区分升 / 降:
    • 升杠杆失败 → 重试 (proxy 抽风)
    • 降杠杆失败 (59108) → 不重试, 推 QQ "OKX 拒绝降杠杆, 账户余额不足" + 触发"用户偏好"问询"要不要平仓释放 USDT 后再降"
  • 文档加 pitfall: "降杠杆在 cross 模式需要 USDT 支持, 升杠杆不需要"

实战应对 (本次 session):

  • 用户问 "正常操作是怎么降?" → 我列了 3 路径 (加仓满足/逐仓模式/平仓-降-重开)
  • 用户没让我强制平, 信号继续 (熬鹰后续还会发 modify 信号)
  • 实战教训: 调杠杆信号在 cross 模式下经常失败, 不要默认每次都能跟

3. 调杠杆信号 A→B 解读规则 (v4.5.68 强化 v4.5.65)

信号: 🔧 注意,大佬修改了杠杆 5→2 【币种】: SKHYNIX-USDT|永续|2x

正确解读:

  • 5→2 = 当前 5x → 改成 2x (目标值 2)
  • 信号文本 永续|2x 字段是目标值, 不是"现在杠杆 2x"
  • process_signal.parse_signal() 取 leverage 字段 → 2

代码已对:

new_lev = int(fields.get('leverage') or '10')
# leverage 字段在 `【币种】: <X>|永续|<LEV>x` 取到, 取 LEV = 2

用户误读防范:

  • ❌ "5→2 我手动调到 5x" (我本次 session 干过这傻事)
  • ✅ 永远取 永续|<LEV>x 的 LEV = 信号目标值
  • 验证: 信号文本里 永续|2x → 调 set-leverage lever=2

4. signal_tracker.acquire_lock 的 symbol 参数必须无后缀

实战发现: 用户手动 execute MSTR short 4.01 张@5x 后, 我手动跑 acquire_lock("MSTR-USDT-SWAP", ...), 结果 position_locks 出现 2 条:

MSTR|熬鹰资本|short|...|新信号自动锁|1
MSTR-USDT-SWAP|熬鹰资本|short|...|手动加锁|0

根因: process_signal.parse_signal() 提取 symbol 字段时不带 -USDT-SWAP 后缀, 而手动锁习惯性用 instId 完整形式。

正确:

from signal_tracker import acquire_lock
ok, msg = acquire_lock("MSTR", "熬鹰资本", "short", reason="手动加锁", auto=False)
# ✓ 无后缀
ok, msg = acquire_lock("MSTR-USDT-SWAP", "熬鹰资本", "short", ...)
# ✗ 永远锁不上

验证:

sqlite3 ~/.hermes/trading/signal_history.db "SELECT * FROM position_locks;"
# 应只见无后缀 symbol (MSTR / TRUMP / SKHYNIX / ETH / BTC)

跟 v4.5.63 的关系: v4.5.63 已记过这个坑, v4.5.68 实战再次踩到 (MSTR 锁不上 → 用户问 "交易员锁了吗, 我是转发的消息, 也要锁的")

修复方向:

  • acquire_lock 函数加注释强调"symbol 必须无 -USDT-SWAP 后缀"
  • 或 acquire_lock 内部自动剥离后缀 (defensive)

5. trader='未知' 闸的"幽灵 execute" vs 主流程"静默 skip" 并存

会话时间线:

时间 信号 process_signal 报 实际成交
T1 SKHYNIX short 2x "跳过 信号源未知" 0.145 张@2x (幽灵)
T2 BTC long 5x "跳过 信号源未知" 0.63 张@5x (幽灵)
T3 HYPE long 2x (1) "跳过 信号源未知" 26 张@2x (幽灵)
T4 HYPE long 2x (2) "1张 性价比一般" 25 张@2x (幽灵)
T5 白名单闸加好 "跳过 trader [未知] 不在白名单" (不再幽灵)
T6 TRUMP long 1x "137张 性价比高" 586 张@1x (超额幽灵)
T7 SKHYNIX long 1x "0.065张 性价比低" (v4.5.66 后) 0.098 张@1x
T8 SKHYNIX long 2x 加仓 "0.039张 性价比低" 0.407 张@2x (超额幽灵)

关键洞察:

  • T1~T4 在白名单闸前 → 闸没生效, advisor 独立 execute 路径成交
  • T5 加白名单闸后 → advisor 路径也没被拦住 (advisor 不读 process_signal 的闸)
  • T6~T8 都是在白名单生效后 → 仍有幽灵 execute

结论: process_signal 主流程闸 ≠ advisor execute 闸, 这是两个独立路径, 都要加固。

6. scripts/manual_order.py 已有, 本次 session 实战使用

实战模板 (本次 session 末段):

# /tmp/open_mstr2.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'
    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()

# 5x MSTR short market order
body = {'instId': 'MSTR-USDT-SWAP', 'tdMode': 'cross', 'side': 'sell',
        'posSide': 'net', 'ordType': 'market', 'sz': '1'}
print(okx_post('/api/v5/trade/order', body))

已知陷阱 (本次 session 实战遇到):

  1. POST body 必须 body=body keyword arg (v4.5.64 已修, 但每次新写脚本要警惕)
  2. reduceOnly 平仓: sz 必须严格等于持仓张数, 否则 OKX 报 51169
  3. proxy 必须保留: 私有 API 直连会被 OKX 拒绝
  4. acquire_lock 必须手动: 用户偏好不改代码 (v4.5.63)

7. 用户偏好 (本次 session 末段新增)

  • "调杠杆失败这个不能改吗" (用户原话, 2026-08-26) → 我列了 3 路径, 用户未选, 默认 不强制平仓, 等下一个调杠杆信号自然解决
  • "正常操作是怎么降" (用户原话, 2026-08-26) → 用户在寻求知识, 不在要我执行

实战时间线 (本次 session)

时刻 事件
2026-08-26 01:00 熬鹰 ETH 平仓 → close_position_raw 返回 None → process_signal 崩溃 → 加 null guard
2026-08-26 01:30 熬鹰 ETH 新开仓 → advisor 报 1.4 张 → execute 1.4 张@3x (OK)
2026-08-26 02:00 用户问"信号只到了 4" → 我误把 ETH 调到 5x → 手动改回 4x
2026-08-26 03:00 熬鹰 HYPE 平仓 → 手动 execute (proxy 抽风)
2026-08-26 04:00 熬鹰 TRUMP 新开仓 → advisor 137 张 → execute 586 张@1x (幽灵, 4.3x 超额)
2026-08-26 05:00 熬鹰 TRUMP 调杠杆 1→2x → 自动跟 → USDT 可用恢复 $2 → $81
2026-08-26 06:00 熬鹰 TRUMP 平仓 → 手动 execute (proxy 抽风)
2026-08-26 07:00 熬鹰 SKHYNIX 新开仓 1x → "性价比低" 跳过 (v4.5.66 前)
2026-08-26 08:00 用户 "把性价比去掉, 不要了" → 移除"性价比低"判断
2026-08-26 09:00 熬鹰 SKHYNIX 1x → execute 0.098 张 (OK)
2026-08-26 10:00 熬鹰 SKHYNIX 调杠杆 1→5x → execute set-leverage OK
2026-08-26 11:00 熬鹰 SKHYNIX 调杠杆 5→2x → OKX 59108 拒绝 (cross 模式余额不足)
2026-08-26 12:00 熬鹰 SKHYNIX 加仓 2x → advisor 0.039 → execute 0.407 张@2x (10x 超额幽灵)

累计已知 execute 失败/幽灵 清单 (v4.5.68 更新)

币种 模式 现象
SPCX-USDT-SWAP silent fail advisor 报"已推送", 实际无合约, 不下单
1000PEPE / PEPE-USDT-SWAP symbol normalize 必须 PEPE-USDT-SWAP, advisor 有路径问题
MU-USDT-SWAP 幽灵 advisor 报 X 张, execute X+1 张
XAU-USDT-SWAP 幽灵 advisor 报 X 张, execute X+N
HYPE-USDT-SWAP 幽灵 (本次) advisor 报 1 张, execute 25 张
TRUMP-USDT-SWAP 幽灵 (本次) advisor 报 137 张, execute 586 张
SKHYNIX-USDT-SWAP 幽灵 (本次) advisor 报 0.039 张, execute 0.407 张
NEIRO-USDT-SWAP silent fail OKX 无合约
ZAMA-USDT-SWAP silent fail OKX 无合约

通用规律: 所有合约都可能被幽灵 execute, 没有"安全"币种。每次 execute 后必须反查。

部署清单 (下次 session 第一件事)

  • okx_position_advisor.py 加 trader 闸 + 白名单 + trader='未知' 闸 (跟 process_signal 同步)
  • advisor execute 后强制 check_account.py 反查, 反查为空时推 QQ 失败
  • advisor JSON 加 actual_contracts 字段, 由 check_account 后置填充
  • adjust_leverage_raw 失败时区分升/降, 降杠杆 59108 推 QQ 用户问询
  • acquire_lock 函数加注释 "symbol 必须无 -USDT-SWAP 后缀"
  • 已知 silent_fail / 幽灵 execute 币种清单 (上表) 入 reference
  • X/Twitter 链接处理模板入 SKILL.md (v4.5.65 已记, 复用)

关联版本

v4.5.21 加"性价比低"判断 (兜底)
   ↓
v4.5.37 ~ v4.5.62 沿用 + silent_order 标识
   ↓
v4.5.65 silent_order 完整化
   ↓
v4.5.66 去掉"性价比低"判断, 跟所有熬鹰信号 (用户偏好反转)
   ↓
v4.5.67 用户口语"调杠杆" = 加仓 (不是 OKX set_leverage)
   ↓
v4.5.68 幽灵 execute 加剧 + cross 模式降杠杆被拒 + 调杠杆信号 "3→4" 解读

每次踩坑都在 OKX 跟单这条线上, 跟其他 skill 不重叠。