Files
Hermes-Skills/okx-auto-position/references/v4.5.63-2026-08-26-manual-position-lock-and-symbol-mismatch.md

7.0 KiB

v4.5.63 (2026-08-26) 手动下单必须手动锁 + symbol 不匹配陷阱 + ETH long 完整周期

本次 session 在 v4.5.61 (trader 白名单) + v4.5.62 (dedup 手动清 + 手动加仓) 基础上的 3 个新教训


教训 1: 手动 execute 的仓位必须手动 acquire_lock

用户原话: "用手动锁就行,不要改代码了。"

症状: 用户让 agent 手动 raw REST 下单(比如 MSTR short 4.01张),下单成功了,但 position_locks 表里没有这条记录。后续熬鹰 MSTR 平仓信号进来时,check_signal_lock(MSTR) 返回 None → acquire_lock 创建新锁 → 但同时 process_signal 主流程里平仓信号被"无持仓静默"短路,不会真平仓。

根因: acquire_lock() 只在 process_signal 主流程的 check_signal_lock 里被调用,手动 execute (raw REST) 完全绕开 process_signal → 没有锁记录。

SOP (硬规则, v4.5.63 起执行):

# 手动 execute 后, 立即手动锁 (用户偏好: 不要改代码, 用脚本)
import sys
sys.path.insert(0, '/home/openclaw/.hermes/skills/trading/okx-auto-position/scripts')
from signal_tracker import acquire_lock

# ⚠ symbol 必须与 process_signal 用的 symbol 一致 (无 '-USDT-SWAP' 后缀)
ok, msg = acquire_lock("MSTR", "熬鹰资本", "short", reason="手动加锁", auto=False)
print(f"ok={ok}, msg={msg}")

手动锁模板 (/tmp/lock_<SYMBOL>.py):

import sys
sys.path.insert(0, '/home/openclaw/.hermes/skills/trading/okx-auto-position/scripts')
from signal_tracker import acquire_lock
ok, msg = acquire_lock("<SYMBOL>", "<TRADER>", "<side>", reason="手动加锁", auto=False)
print(f"ok={ok}, msg={msg}")

实战 (本次 session): 用户说"用手动锁就行" → 我手动锁 MSTR → 后续熬鹰 ETH / HYPE 信号正常走流程。


教训 2: acquire_lock 的 symbol 必须与 process_signal 一致 (无后缀)

陷阱: 用户手动 execute MSTR-USDT-SWAP 时, 习惯性把 instId 直接传给 acquire_lock,变成 acquire_lock("MSTR-USDT-SWAP", ...),但 process_signal 用的是 fields.get('symbol', '?'),extract 出来的 symbol 不带 -USDT-SWAP 后缀(例如 "MSTR")。

结果: position_locks 表里出现两条记录:

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

后续 get_lock("MSTR") 查到第一条(自动锁), get_lock("MSTR-USDT-SWAP") 查到第二条。手动锁的那条永远不被命中,失去意义。

正确做法:

# ✅ 对
acquire_lock("MSTR", "熬鹰资本", "short", ...)
acquire_lock("ETH", "熬鹰资本", "long", ...)
acquire_lock("HYPE", "熬鹰资本", "long", ...)

# ❌ 错
acquire_lock("MSTR-USDT-SWAP", "熬鹰资本", "short", ...)  # 永远查不到
acquire_lock("ETH-USDT-SWAP", "熬鹰资本", "long", ...)

验证脚本:

sqlite3 ~/.hermes/trading/signal_history.db "SELECT * FROM position_locks;"
# 应该看到 <SYMBOL> 不带 -USDT-SWAP

教训 3: ETH long 完整周期: 开仓 → 调杠杆 → 后续 + 自动平仓 (ghost close)

完整时间线 (本次 session):

  1. 熬鹰 ETH long 2x 信号 → process_signal execute → ETH long 1.4张@3x (avgPx 2486.74)
  2. 熬鹰 ETH 调杠杆 3→4x → process_signal 推"性价比低"无 execute
  3. 熬鹰 ETH long 5x (新一轮信号) → process_signal 推但未 execute(用户资金不够再开新仓)
  4. 熬鹰 ETH 平仓信号 → process_signal 报"⏭️ 平仓信号无持仓静默"
  5. 用户质问: "你的 ETH long 怎么平了?"
  6. 实际查 check_account.py: ETH long 已自动平仓,USDT $149.60

关键问题: 平仓信号被"无持仓静默",但实际平仓确实发生了 —— ghost close (v4.5.54 已记录的同类型 bug)。

实际平仓价: markPx 2457.34 → 平仓时 markPx (查不到但 USDT 从 $30.39 → $149.60 跨度太大, 不止 ETH 一笔)。USDT 增加 $0.06 几乎可忽略,说明 ETH 平仓价 ≈ avgPx 2486.74,盈亏接近 0。

教训 (v4.5.63 强化):

  • 任何"无持仓静默"信号 → 必跑 check_account.py 确认
  • 平仓 ghost close 实际可能发生了,USDT 变化能反向验证
  • 不要假设 process_signal 报"无持仓"就是真无持仓,这是 v4.5.51 第9次违规的延伸

教训 4: v4.5.61 trader 白名单闸 + v4.5.62 dedup 手动清 实战组合

实战:

  • 白名单闸: 矿工Jasonleo 20+ reduce 信号全部 ⏭️ 跳过: trader [矿工Jasonleo] 不在白名单,完全静默,不推QQ
  • dedup 手动清: 熬鹰连续 add+modify 触发 ⏭️ 重复信号,跳过 → 我用 sqlite3 清 recent_signals 解锁

白名单 + dedup 清库 组合执行模板 (本次 session 实跑 5 次):

# 1. 删 recent_signals (解锁)
sqlite3 ~/.hermes/trading/signal_dedup.db "DELETE FROM recent_signals WHERE symbol LIKE '%HYPE%' AND trader='熬鹰资本';"

# 2. 重新跑 process_signal
python3 ~/.hermes/skills/trading/okx-auto-position/scripts/process_signal.py << 'EOF'
【熬鹰资本】
📈 注意, 大佬加仓了
【币种】: HYPEUSDT|永续|2x
【方向】: 做多 🟩
【仓位】: 5881.62 HYPE
【开仓价】: 79.93753
【当前价】: 80.03194
【保证金】: 235,358.72 USDT(全仓)
【收益额】: +555.26 USDT(+0.24%)
EOF

部署清单 (下次必修):

  • parse_signal() 区分 modify (调杠杆) vs add (加仓), 不混进 dedup 记录
  • recent_signals 表加 action 字段 (open/add/reduce/close/modify)
  • process_signal 主流程"无持仓静默"后必须 check_account.py 反查
  • acquire_lock 必须能在手动 execute 路径触发 (或者用户手动跑 acquire_lock)
  • 文档明确"手动锁 symbol 必须与 process_signal 一致"

本次 session 净状态 (2026-08-26 收)

项 值
USDT 可用 $149.60
权益 $149.60 (无冻结)
ETH long 已自动平仓 (盈亏 ≈ 0)
MSTR short 4.01张@5x, avgPx 126.04, 浮亏-$0.21
占用 68% (≈7 成)
强平价 MSTR 160.00 (距 $34, 安全)
白名单闸 ✅ 只跟熬鹰资本
MSTR 锁 ✅ 已加熬鹰资本 short (手动)
ETH 锁 ✅ 已加熬鹰资本 long (手动)

用户偏好强化 (本次新增)

  1. "用手动锁就行, 不要改代码了" — 修改 signal_tracker.py 加自动锁不是用户想要的
  2. "按 X 成来开" / "只留 X 成" — 同义, 都表示余额占比而非仓位占比 (用户原话: "不是, 是只留 2 成的余额" 纠正了我)
  3. "这个可以跟单了" — 即使 advisor 报"性价比低", 用户主动要求 manual execute
  4. "不是 X 几层, 是只留 X 成余额" — 用户在意最终占用 vs 余额比例, 不在意绝对张数

跨 session 索引

  • v4.5.51 (lock trace): 持仓来源追溯三步
  • v4.5.54 (trader='未知' 闸 + ghost close): 同根问题
  • v4.5.60 (BTC 来源误归属): 锁追溯必查 position_locks
  • v4.5.61 (trader 白名单): 当前生效
  • v4.5.62 (dedup 手动清 + 手动加仓): 已沉淀 manual_order.py
  • v4.5.63 (本次): 手动锁 + symbol 一致性 + ETH ghost close + 用户"留 X 成余额"偏好