# v4.5.54 (2026-08-20) trader='未知' 闸已部署但仍执行 + ghost close 不入库 ## 核心事件 本次 session 暴露了 v4.5.53 闸的两个延伸 bug,以及一个完全独立的新坑。 ### Bug 1: trader='未知' 闸虽触发,但 execute 已发生在前一道 **症状**: 熬鹰 SNDK 做空信号进来,process_signal 输出 `⏭️ 跳过: 信号源未知 | SNDK short`,但实际 5 秒后 check_account.py 显示已有 SNDK short 持仓(0.107张@2x)。 **根因(推测)**: v4.5.53 的闸插在 `is_signal_stale` 之前,但 `execute` 调用可能发生在更早的阶段(可能在 `parse_signal` → `_okx_raw_request` 一气呵成的旧路径上)。或者触发来自 `signal_queue.db` 中**之前已 enqueue 但未消费**的积压信号(本次就有 SKHYNIX short 0.145张 的残留)。 **复现路径**: ```python # SKHYNIX short 0.145张 + BTC long 0.63张 + HYPE long 26张 都是 trader='未知' 触发 # 三次都看到 "⏭️ 跳过: 信号源未知" 但 execute 成功 ``` **修复方向(下次必修)**: 1. 检查 `parse_signal()` 后第一行就设闸:`if trader == '未知': return 'skipped_unknown_source'` (现在可能在 classify_signal 之后才设) 2. signal_queue.db 旧积压消息必须清空,只保留已分类的信号 3. execute 路径前必须先 `if trader == '未知': abort` 二道闸 ### Bug 2: 平仓 ghost close — execute 成功但 confirmed_signals 无记录 **症状**: SNDK short 0.107张 在熬鹰 SNDK 平仓信号进来时,**信号被 process_signal 报"无持仓静默"**(因为 trader 锁不对),但 5 秒后实际持仓真的平了,USDT 从 $30.39 涨到 $109.67(+79.28 锁定)。 **根因**: 平仓可能由**信号触发器/交易所规则**(如 reduceOnly 强平)在后台自动平仓,未走 process_signal 主流程,所以 `confirmed_signals` 表无记录。 **复现**: ```bash sqlite3 ~/.hermes/trading/signal_history.db "SELECT * FROM confirmed_signals WHERE action LIKE '%close%' ORDER BY timestamp DESC LIMIT 5;" # 无 auto_executed_close 记录,但 USDT 确实增加了 ``` **用户视角**: 用户看到"无持仓静默"以为没事,其实已经平了——这不是 bug,是**逻辑断层**(主流程不知道后台平仓发生了)。 **修复方向**: 1. process_signal 主流程加"持仓变化检测"——对比前后 check_account.py,有消失就记录 `action=auto_ghost_close` 2. 或定期 reconcile:`cron 每 5 分钟`对比 position_locks 与实际持仓,不一致就报告 ### Bug 3 (新坑): SSL 抽风导致持仓查不到 → 误报无持仓 **症状**: 予与 BTC short 加仓信号进来 → check_account.py 返回**空 positions** → 我回复"无BTC持仓" → 用户纠正"你查了持仓再来看" → 重查 → **BTC short 1.47张@10x, avgPx 63198, 浮盈+$2.62**。 **根因**: SSL EOF(curl/echo/clash 抽风)返回空 dict,agent 没识别"空响应 = proxy 抽风 = 不要相信"。 **修复方向**: 1. check_account.py 加 retry + sanity check:`if positions == [] and availBal > 0: maybe_ssl_fail=True` → 返回 `{"positions": [], "warning": "ssl_maybe_failed"}` 2. agent 收到 `warning: "ssl_maybe_failed"` 时不报"无持仓",改报"持仓查询失败,稍后重试" 3. 30 秒后自动重试一次 ## 锁追溯方法 (本次验证有效) 本次 session 用这个套路找到了 BTC short 1.47张的真正来源: ```bash # 1. position_locks 确认是哪个 trader 锁了 sqlite3 ~/.hermes/trading/signal_history.db "SELECT * FROM position_locks;" # → BTC|予与实盘|short|2026-08-15T18:47:00|新信号自动锁 # 2. confirmed_signals 确认哪条信号触发了 execute sqlite3 ~/.hermes/trading/signal_history.db "SELECT * FROM confirmed_signals WHERE symbol='BTC' ORDER BY timestamp DESC LIMIT 5;" # → ID 129|予与实盘|BTC|short|10|0.0|0.0|0.0||||auto_executed_add # 3. recent_signals 确认原始信号内容 sqlite3 ~/.hermes/trading/signal_dedup.db "SELECT * FROM recent_signals WHERE symbol='BTC' ORDER BY timestamp DESC LIMIT 3;" ``` 这个套路 v4.5.51 已记录,本次确认在 trader='未知' 也能定位(只要 confirmed_signals 里有记录)。 ## 本次净状态变化 | 时间点 | USDT | 持仓 | 备注 | |---|---|---|---| | 会话开始 | $62.80 | MU short 0.61张 | (待补) | | 会话结束 | $109.67 / $110.71 | 无 | 净 +$47 / +12% | | 关键盈利 | BTC long 0.63张 → 67,860 平 | +$17.50 | | | | HYPE short 75张 → 平 | -$2.25 | | | | SNDK long 0.126张 → 平 | +$5.54 | | | | SKHYNIX short 0.145张 → 平 | +$1.10 | | ## 实战教训 (跨 skill 元教训) 1. **闸要插在最早的环节** — v4.5.53 trader='未知' 闸插太靠后,execute 路径绕过 2. **空返回值可能是错不是真相** — SSL 抽风返回空 dict ≠ 真无持仓 3. **后台平仓不留痕是隐患** — reduceOnly / 风控自动平仓不走主流程 → 状态同步断层 4. **不要复用旧数据** — 上一条信号查的,不代表下一条还是这样 ## 部署清单 (下次 session) - [ ] 检查 process_signal.py trader='未知' 闸位置,改为 parse_signal 后第一行 - [ ] 清空 signal_queue.db 中已知 trader='未知' 的积压消息 - [ ] check_account.py 加 `ssl_maybe_failed` warning 字段 - [ ] agent 收到 `ssl_maybe_failed` 改报"持仓查询失败"而不是"无持仓" - [ ] process_signal 加持仓变化检测(对比前后,有消失就 ghost_close 记录) - [ ] signal_tracker.py 已知 trader 名单增加"矿工Jasonleo"(本次 session 新增信号源) ## 相关 - v4.5.53 (trader='未知' 闸 — 本次发现闸虽设但 execute 已绕过) - v4.5.51 (第9次违规 — 未查持仓就报无持仓,本次以更隐蔽形式再犯) - v4.5.38 (第8次违规 — 偷懒复用前次数据) - v4.5.45 (lock_status 推送 + 72h 自动解锁 — 锁追溯路径稳定) - v4.5.49 (SSL 抽风期间 execute 可能成功 — 本次以"持仓查不到"反向触发)