5.7 KiB
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张 的残留)。
复现路径:
# SKHYNIX short 0.145张 + BTC long 0.63张 + HYPE long 26张 都是 trader='未知' 触发
# 三次都看到 "⏭️ 跳过: 信号源未知" 但 execute 成功
修复方向(下次必修):
- 检查
parse_signal()后第一行就设闸:if trader == '未知': return 'skipped_unknown_source'(现在可能在 classify_signal 之后才设) - signal_queue.db 旧积压消息必须清空,只保留已分类的信号
- 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 表无记录。
复现:
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,是逻辑断层(主流程不知道后台平仓发生了)。
修复方向:
- process_signal 主流程加"持仓变化检测"——对比前后 check_account.py,有消失就记录
action=auto_ghost_close - 或定期 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 抽风 = 不要相信"。
修复方向:
- check_account.py 加 retry + sanity check:
if positions == [] and availBal > 0: maybe_ssl_fail=True→ 返回{"positions": [], "warning": "ssl_maybe_failed"} - agent 收到
warning: "ssl_maybe_failed"时不报"无持仓",改报"持仓查询失败,稍后重试" - 30 秒后自动重试一次
锁追溯方法 (本次验证有效)
本次 session 用这个套路找到了 BTC short 1.47张的真正来源:
# 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 元教训)
- 闸要插在最早的环节 — v4.5.53 trader='未知' 闸插太靠后,execute 路径绕过
- 空返回值可能是错不是真相 — SSL 抽风返回空 dict ≠ 真无持仓
- 后台平仓不留痕是隐患 — reduceOnly / 风控自动平仓不走主流程 → 状态同步断层
- 不要复用旧数据 — 上一条信号查的,不代表下一条还是这样
部署清单 (下次 session)
- 检查 process_signal.py trader='未知' 闸位置,改为 parse_signal 后第一行
- 清空 signal_queue.db 中已知 trader='未知' 的积压消息
- check_account.py 加
ssl_maybe_failedwarning 字段 - 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 可能成功 — 本次以"持仓查不到"反向触发)