Files
Hermes-Skills/okx-auto-position/references/v4.5.4-close-dedup-real-incident.md
T

3.6 KiB

v4.5.4 平仓信号 dedup 误跳 — 真实事件复现 + 用户视角教训

时间: 2026-07-08 事件: 熬鹰ETH short 减仓→平仓 信号链 触发用户反馈: "要是我没发现,就一直不推了吗?重试机制呢"


事件完整时间线

  1. 15:00 熬鹰 ETH short 1773张 减仓信号

    • process_signal 返回 ✅ 已推送 | ETH short 5x | 0.64张 | 性价比低
    • 用户持仓: ETH short 1.85张 @5x (avgPx 1759.78, 浮亏 -$3.52)
    • ⚠️ 这是"减仓信号",不是"新开仓" — 本应触发 advisor 加仓路径
  2. 15:01 熬鹰 ETH short 平仓信号 (跟单号:🚨 已平仓提醒, +11.23%)

    • process_signal 返回 ⏭️ 重复信号,跳过
    • BUG: 平仓信号走了2分钟窗口 dedup,没走 close 独立通道
    • ETH short 1.85张 未自动平仓
  3. 15:05 ETH 继续涨到 1795

    • 用户浮亏扩大到 -$6.58
    • 用户追问: "这个没推平仓信号"
  4. 15:06 agent 手动重跑同一平仓信号

    • process_signal 返回 ✅ 平仓处理: closed | ETH short
    • ETH short 1.85张 全平成功
    • USDT 回到 $106.34

根因

process_signal.py 主流程顺序错误:

# 错误顺序:
dedup_conn = init_dedup_db()
if is_duplicate(dedup_conn, text, symbol, trader):  # ← close 信号在这里被误跳
    return "⏭️ 重复信号,跳过"

signal_type = classify_signal(fields)

if signal_type == 'close':
    # 平仓逻辑,永远到不了这里
    ...

is_duplicate() 的2分钟窗口把"减仓+平仓"两个完全不同语义的信号合并去重了。


修复 (v4.5.4)

# 正确顺序:
signal_type = classify_signal(fields)  # ← 先分类

if signal_type == 'close':
    dedup_conn = init_dedup_db()
    msg_hash = hashlib.md5(text.encode()).hexdigest()
    # close 信号只看 raw_text hash 唯一性,不看2分钟窗口
    if dedup_conn.execute("SELECT 1 FROM processed WHERE msg_hash = ?", (msg_hash,)).fetchone():
        return "⏭️ 平仓信号完全重复跳过"
    # 走平仓独立路径
    close_result = close_position_raw(symbol_usdt, signal_side_en)
    ...

# 其他信号 (open/reduce) 才走2分钟窗口 dedup
dedup_conn = init_dedup_db()
if is_duplicate(dedup_conn, text, symbol, trader):
    return "⏭️ 重复信号,跳过"

关键设计原则:

  • is_duplicate() 永远不应用于 close 信号
  • close 信号 dedup 只能基于 raw_text hash (因为 text 内含最终收益额+标记价,天然唯一)
  • 平仓动作必须发生 — 用户可能不会逐条核对内部状态

用户视角的关键反馈 (2026-07-08)

  • 用户不会逐条核对 process_signal 返回值——他只看 QQ 有没有收到平仓结果
  • 一旦他认为"应该平但没平",他不会去查 process_signal 内部状态,而是怀疑系统坏了
  • 必须实现重试机制: 当平仓信号 dedup 命中时,不能简单 skip,必须至少推一条"⚠️ 平仓信号疑似跳过,请人工确认持仓"到 QQ

实测结果

修复后再次收到 ETH short 平仓信号 → 走独立通道 → 自动平仓成功

推送 git commit: v4.5.4: 平仓信号 dedup 误跳 bug 修复 — close 信号走独立通道 (2026-07-08 实测)


给未来 session 的提醒

  1. 不要相信 is_duplicate() 适用于所有信号类型 — 它是为 open/reduce 设计的
  2. close 信号是"必须执行"的命令,不能和 open/reduce 共用去重窗口
  3. 用户视角优先: 平仓失败=系统坏了,不是"按规则跳过了"
  4. process_signal 返回值 ≠ 实际行为: 返回"重复信号"不代表持仓已处理,必须查 raw REST 验证