# v4.5.116 — Leverage 字段正则 fallback + 频道切换 4 步验证 + 用户情绪识别 (2026-09-26) ## 1. 杠杆字段解析 bug **症状**: 信号原文 `【币种】:ONDOUSDT 永续 | 全仓 | 2x` 进 `process_signal.py`, advisor 默认报 10x leverage, 实际信号是 2x。 **根因** (`process_signal.py:79`): ```python extractors = { 'leverage': r'【杠杆】\s*[::]?\s*(\d+)', # 只匹配独立【杠杆】标签 } ``` 信号里杠杆在币种标签内 (`ONDOUSDT 永续 | 全仓 | 2x`), 没有独立 `【杠杆】` 标签, 正则匹配失败, 默认 10x。 **代价**: 你的仓位杠杆 = advisor 报量 × 默认 10x。如果熬鹰实际 1.95x, 你的风险敞口是他 5.13 倍。满仓时 12% 跌幅爆, 熬鹰 88% 跌幅才爆。 **修复** (已 patch): ```python extractors = { # 独立【杠杆】标签 OR 行内|全仓|Nx 两种 fallback 'leverage': r'(?:【杠杆】\s*[::]?\s*(\d+)|(?:永续|全仓)\s*\|\s*全仓\s*\|\s*(\d+)\s*[xX]?)', } # 提取时优先取 group(1), fallback group(2) for key, pattern in extractors.items(): m = re.search(pattern, text) if m: v = m.group(1) or m.group(2) or '' if v: fields[key] = v.replace(',', '') if key != 'unit' else v ``` **测试用例**: ```python # 旧格式 (有【杠杆】N) text1 = '''【币种】BTCUSDT|永续|10x 【方向】做多 【杠杆】5 【仓位】1000''' assert parse_signal(text1)['leverage'] == '5' # ✓ group(1) # 新格式 (币种标签内|全仓|2x, 无独立【杠杆】) text2 = '''【币种】:ONDOUSDT 永续 | 全仓 | 2x 【方向】:做多 🟩''' assert parse_signal(text2)['leverage'] == '2' # ✓ group(2) # 旧格式混合 (标签+行内) text3 = '''【币种】BTCUSDT 永续 | 全仓 | 3x 【方向】做多 【杠杆】3''' assert parse_signal(text3)['leverage'] == '3' # group(1) 优先 ``` **触发场景**: 任何"币种标签内|永续|全仓|Nx"格式信号 — 常见于 2026-08 后的新版熬鹰币安实盘/熬鹰FOMO合约实盘 模板。 **用户原话** (2026-09-26): "ONDO 一直是 2 倍, 你是不是改成 10 倍了" — 是默认 10x 的结果, 不是显式调杠杆。但效果等价于"无形调了杠杆"。 --- ## 2. 频道切换 4 步端到端验证链 — 用户情绪信号 **用户原话** (按情绪递进): 1. "需要把监听的频道更新一下" — 中性 2. "换到新频道, 其他的配置不动" — 中性 3. "现在用的是哪个频道" — 中性 4. "C, 是一个群吗, 还是之前配置过 但启用的不对" — 轻微疑惑 5. "现在交易信号都没转发了吗" — 轻微失落 6. "那现在查信号为什么没进来啊, 转发器在正常工作的? 我对你十分失望" — **明确失望** 7. "现在把监听频道改回到 https://t.me/jiankongshipan" — 明确放弃新频道, 回切 **关键教训**: 用户说"我对你十分失望"时, **不要继续诊断新频道**, 立即承认失败并执行"回切到旧频道"操作。Agent 不能无限制地诊断/优化 — 用户给的是"立即恢复"的命令。 **反向验证 (anti-pattern)**: Agent 在用户失望后继续问"确认是新频道吗? 那查一下 OKX 实际是不是有信号流入?" — 这是继续在错误的频道上诊断, **不解决用户痛点**。 **正解**: 用户说失望时, 立即回切并确认 — "已切回 jiankongshipan, 当前 source=1, 查 forwarder logs 看到 NewMessage 事件正常触发, 等下一条信号验证"。 --- ## 3. 频道切换"伪成功"陷阱 — 用户没说"换好了",就还在诊断 **症状**: Agent 把 `forward_rules.source_chat_id` 改成新频道, `docker restart` 转发器, 然后告诉用户"已切换"。但实际上: 1. forwarder 的 chat_id 提取还是用 `abs(chat.id)` — TG channel 是 `-100xxx`, abs 剥成 `xxx`, 跟 DB 存的 `-100xxx` 字符串匹配不上 2. user_client 虽然订阅了 channel (`Got difference for channel XXX updates`), 但 `NewMessage` 事件不触发 3. 用户发了一条"汇总播报"试探, 没看到转发 4. 用户下一句:"现在交易信号都没转发了吗" **正解 — 4 步验证** (任何一步不通过, 都不能宣告成功): 1. DB 配置: `forward_rules.source_chat_id` 改到新 chats.id, forwarder 重启 2. **看 forwarder logs 出现 `[处理规则|新消息|命中黑名单]` 日志** — 仅有 `Got difference for channel ... updates` 不够, 说明 message_handler 没匹配上 (chat_id 提取 bug) 3. **真信号触达**: 用 telethon `iter_messages('username', limit=10)` 验证 (容器内需 `cp session /tmp/` 解锁) 4. **执行闭环**: 用户转发一条真实信号到新频道, 看 QQ 推送 + OKX execute + check_account 仓位变动 **只改 db 不验证后续 = 假成功**, 等到新信号来了才发现"漏发"就晚了 (本 session ONDO 漏发就是这个原因)。 --- ## 4. token 纪律补充: 蚂蚁式减仓双层过滤 + 用户情绪触发合并输出 用户原话 (按情绪递进): 1. "调整一下, 只有加仓, 减仓, 开仓, 平仓这些字段的消息才处理" — 主动优化 2. "蚂蚁减仓尽量减少token的消耗" — 明确 token 关注 3. "我真服了" — 失望 (蚂蚁减仓 spam 不止, signal 也没进来) **结论**: § 65 已部署 classify 严格模式 + 1% min 减仓过滤 + 同类输出合并, 2026-09-26 实测生效。本 session 蚂蚁减仓从 50+ 条 spam 收敛到"蚂蚁减仓no-op(0.X%<1%); USDT $576" 重复 1 行。但**用户信号断了**(forwarder chat_id bug), 这才是 1+2 实际 loss of progress。 **执行优先级**: token 优化只是减少噪音, 不解决"信号没进来"的核心问题。Agent 应该在用户说"信号没来"时优先诊断 forwarder 链路, 而不是继续优化 process_signal。 --- ## 5. forwarder 模板名 disambiguation **用户原话** (2026-09-26): "转发器转发内容时, 你再加一条转发时间" **意图**: 让转发消息能区分"原信号时间"vs"转发动作发生时间"。 **当前状态**: - `forward_rules.time_template` 默认 `⏱信号时间: {time}` — 但代码层 `{time}` 实际是 hook 接收时刻 (转发时), 不是原信号时间 - `forward_rules.is_original_time` 控制是否附加这条时间戳 **修复** (用户选项 A 已执行 2026-09-26): - `time_template` 改名 `⏱转发时间: {time}` (语义准确) - 用户接受 A 方案 (简洁), 不加额外"原信号时间"行 **未做**: 加`forward_time_template`双时间字段 (方案 B) — 需要改 forwarder 代码层, 改动大, 用户选择不改。 --- ## 6. 调试顺序参考 当用户说"信号没来/没处理/没转发"时, 按这个顺序查: 1. **forwarder logs** (`docker logs telegram-forwarder --since 24h`) - 有 `[处理规则|新消息]` 日志? → step 2 - 只有 `Got difference for channel ... updates`? → **chat_id 提取 bug** (event.chat_id vs abs(chat.id)) - 有 `[黑名单]` 日志? → 硬编码黑名单误杀 (USDT/老师/带单) - 完全没有消息日志? → **user client 没真正 join channel** 或 **forwarder 完全停摆** 2. **DB 配置** (`docker exec telegram-forwarder python3 sqlite3 ...`) - `forward_rules.source_chat_id` 是不是用户说的新频道? - `chats.telegram_chat_id` 是不是 `-100xxxxxxxx` 格式 (负数 + 100 前缀)? - `forward_rules.enable_rule` 是不是 1? 3. **真信号触达** (telethon iter_messages) - 频道是不是真有最近 24h 信号? 是不是被管理员删了? - 信号的字段格式是新版(行内|全仓|Nx)还是旧版(独立【杠杆】N)? 4. **process_signal 链** - classify 是不是 unknown? → 检查信号格式是否太严格 - 白名单闸是不是拦了? → `forward_rules` 的 trader 白名单是不是过期 - advisor 是不是 BadSymbol? → 1000xxx 币种 OKX 上不存在 - 推送是不是失败? → **推送失败 ≠ execute 失败**, 必查 check_account 5. **用户情绪反应** - 用户说"我对你失望/真服了" → 立即承认失败, 执行用户要的恢复命令 (回切/暂停诊断) - 不要在用户情绪爆发后继续在错误的频道上诊断