架构分析 · Webhook

TradingView Webhook 到 Telegram
一个 alert 只吃一个 URL,你要在哪一层 fan-out

2026-08-14·12 分钟

你在 TradingView 上把 alert 设置好了,webhook(也就是把信号 HTTP POST 到你指定 URL 的那条通道)那格填的是自己交易所的 bot;接着发现只能填一个 URL——你想顺便在 Telegram 收一则「进场了、成交价多少」的通知,却找不到第二格可以填。

这件事没有人先跟你讲:TradingView 的 alert 一次只吃一个 webhook URL。想「TradingView Webhook 同时打进 Telegram 与交易所」就得在中间加一层——不管是你自己写个 proxy、把 alert 直接指到 Telegram bot(不下单),还是走一个中间服务把两件事一起做掉。而中间层要不要真的下单,就牵涉到 API key(也就是授权下单/查询用的一组凭证)该由谁来保管。这篇不比较哪个做法比较好,也不评论你的策略。给你三件事:三种 fan-out 位置的取舍顺序与去重会踩到什么坑,以及只推 Telegram、不真下单的观察期怎么设。

先讲结论:
「TradingView 一次能发到两个地方」这件事不成立。Fan-out 一定发生在中间层——不是你的服务器就是别人的服务器。顺序有机制上的正确答案(先确认交易所回单、再发 Telegram),不是凭口味挑;去重要靠中间层做,因为 TradingView 在 5xx 情境会自己重发最多 3 次。

为什么「同时打到 Telegram 与交易所」不是 TradingView 该做的事

TradingView 的 alert 面板长这样:条件、名称、有效期限、通知管道(App、Email、Webhook)。Webhook 那格是一个文本输入框,不是列表——你只能填一个 URL、一份 payload。这是产品设计,不是 bug。TradingView 选择把「发到哪」交给你自己决定的一个端点,之后那个端点要怎么展开,跟它没关系。

所以「下单同时通知我」这件事,得在 webhook URL 那一头自己接。消息里的「进场了、成交价多少、有没有失败」这些字段,都要等到交易所回单之后才存在——alert 刚触发那一刻它们还没有值。fan-out 因此不是「TradingView 一次发两份」的问题,而是「你在 webhook 收到信号之后,怎么在同一段流程里把下单结果同时送到 Telegram」的问题。这个框错了,后面的顺序、去重、rate limit 都会跟着设错。

1
TradingView alert 一次能填的 webhook URL 数
3 种
常见的 fan-out 位置(自写 proxy/直发 TG/中间服务)
3 秒
TradingView 对 webhook 的超时上限

三个可以放 fan-out 的位置,各自优化什么

同样是「下单同时通知我」,中间那层放哪里差很多。这张表是给你比对用的,不用背——挑一个之后回头看那一列的取舍就好。

自己写 proxyTradingView 直发 Telegram bot(不下单)走中间服务同时做两件事
谁握你的交易所 API key你自己的服务器没人握(只发消息,不下单)中间服务
谁扛 uptime你自己Telegram + 你的 bot server中间服务
去重谁做要自己写(记住 dedup key)没下单所以不会重复下,但消息会来两则中间服务内建
顺序保证要自己写(先下单再通知)不下单,没有顺序问题中间服务内建(下单结果为准)
适合谁会写后端、想全掌握只想看信号、还在观察期要真下单但不想维运

第二种「TradingView 直发 Telegram bot」是最被低估的一种——你把 alert 的 webhook URL 直接指向https://api.telegram.org/bot<TOKEN>/sendMessage,在 alert message 里把消息内容写成 chat_idtext 两个 JSON 字段,就会收到消息但完全不下单。适合还在观察策略准不准、还不敢真下单的阶段;缺点是 TradingView 在 5xx 时会重发、你会收到重复消息(Telegram 的 sendMessage 没有 idempotency key)。

顺序踩雷:先发 Telegram 才下单,就等于误报成功

这是最容易写坏的一段。假设你的中间层写成「先发 Telegram 告诉用户已收到、再去交易所下单」。消息会这样:「已收到信号 BTCUSDT buy 0.01」。然后你的下单撞到余额不足、min notional、或 API key(授权下单/查询用的一组凭证)没开合约权限——任何一个都会让下单根本没发生,但用户已经以为「进场了」。

正确顺序是把 Telegram 通知绑到「下单流程的最后一步」——先跑完 pre-checks、送去交易所 API、拿到 fill 或明确的错误消息之后才推 Telegram。这个顺序是机制上的正确答案,不是凭口味挑:因为 Telegram 消息里的每个字段都需要下单后才存在(成交价、实际数量、剩余余额、失败原因)。「举例来说」,TVSBot 执行端的通知就是在 process_signal 跑完之后才进 _send_notificationbackend/app/services/orders.py),消息里的成交价、per-key ✓/✗ 结果、失败时具体错误都是从交易所回单后才有的数据。

顺序这件事有个例外
「Telegram 收到就代表已下单」这句只在你把消息绑在下单成功后才成立。若你自己写的 proxy 选择先发一则「已收到、处理中」再发第二则「成交结果」,那也可以——只要你在第一则明讲「仅代表 alert 收到」。真正错的是「一则就报完成」但那则其实不知道下单有没有成功。

去重踩雷:TradingView 会在 5xx 时重发,Telegram 会来两则

TradingView 的官方 webhook 送达规格是接收端 3 秒内没响应就取消、不重试;4xx 也不重试;只有 5xx 会等 5 秒后重发,最多 3 次(见我们的另一篇:TradingView Webhook 延迟有多严重?官方规格、常见原因与能修复的地方)。这代表:若你的中间层在下单当下遇到交易所短暂回 5xx,又把 5xx 直接透传回 TradingView,同一个 alert 会被送 2 到 4 次。结果 Telegram 收到 2 到 4 则「成交」消息,但实际仓位只开了 1 个——其他次可能因为交易所自身的 idempotency 或 dedup 而 no-op。

解法是中间层自己做 dedup,不要把重发往下游传。可用的键至少要包含 strategysymbolactionqty,最好加上时间窗(60 秒内同 hash 直接 skip)。同一份设计 TVSBot 执行端在 backend/app/routers/webhook.py 的第 4 步是这样写的:payload hash user_id|strategy|symbol|action|qty,60 秒内重复直接不执行。

3 秒
TradingView webhook 超时上限(超过就取消、不重试)
最多 3 次
5xx 才会重发的次数(总共可能收到 4 份)
60 秒
TVSBot 中间层采用的 dedup 窗口长度

Rate limit 踩雷:Telegram Bot API 有秒级上限

Telegram Bot API 对 sendMessage 有秒级的速率限制——单一 chat 大约 1 条/秒,跨 chat 累计还有另一个上限,超过会回 429 并附 retry_after(实际数字请去 Telegram Bot API 官方 FAQ 那页查证,他们保留随时调整的权利)。单人自用大概撞不到,但如果你在跑「一策略多账户 fan-out」或「同时通知社群 100 个订阅者」,就会在某次高频 alert 上一次撞爆。

这件事会安静地坏掉:Telegram 只回 429、不会补发,你不主动去看就不会知道有消息丢了。可行的做法:在中间层加一个消息队列,超过秒级上限就往后排、记录丢过几则。或更务实地:把 Telegram 通知从「每笔订单一则」改成「每小时汇总一则」,散户自用完全够。

只推 Telegram、不真下单的观察期:dry-run 是给这件事用的

一个常被忽略的用法:把 Telegram 当「策略试跑板」。你想看新策略在真实市场上会发多少信号、什么时间、方向对不对——但还不敢接真钱。这时候你不是要「同时通知 + 下单」,你要的是「只通知,不下单」。

两种做法都行。第一种:TradingView alert 直接指向 Telegram Bot API 的 sendMessage,中间不放任何下单逻辑。缺点如上一节写的——重发与 rate limit 都由你自己扛,而且消息里没有「这个信号真的能被交易所吃吗」的验证(min notional、杠杆设置、可用余额都没查)。第二种:走中间服务但设成 dry-run。「举例来说」,TVSBot 的每个策略有 dry_run 开关,开了之后信号会走完整个 pre-check + 假下单流程、把「这笔理论上会下 0.03 BTC,模拟成交价 65,432」写进 Telegram 通知,但完全不打到交易所——订阅守门也会放行让没付费的用户也能试(backend/app/services/orders.pyforce_dry_run 与策略层的 dry_run 两处都指向同一段逻辑)。

1
你想「同时打到 Telegram 与交易所」的真正目的是什么?
还在观察策略,还不敢下真钱alert 直发 Telegram bot(不下单)或中间服务开 dry-run,两种都不会动到交易所
已经想接真钱,只是要有通知把通知放在下单流程的最后一步,顺序才对;去重与 rate limit 交给中间层
策略是要卖给订阅者、要一次发很多人Telegram Bot API 的秒级上限一定会撞到,需要队列或汇总;一次通知很多人跟一次通知你自己是不同架构

你不用真的自己写 proxy——只要看得懂它在做哪四件事

你要不要自己写这个中间层是取舍题。看清楚它在做什么、再决定要不要接手就好。任何做「TradingView → Telegram + 交易所」fan-out 的中间层都会处理下面这四层。列出来给你当检查清单——你自己写、还是选中间服务,都是看它有没有把这四件事处理完。

  • 验身份。Webhook URL 全世界都能打,一定要在 URL 或 payload 带一组长 token 验证。用 hmac.compare_digest 这种常数时间比对——直接 == 会被 timing attack 逐字符反推。
  • 限流。per-token 与 per-IP 各一个上限,攻击者知道你的 URL 也不能把中间层打挂。
  • 去重。strategy + symbol + action + qty 算 hash,60 秒窗口内重复的信号直接 skip。这一步挡掉 TradingView 5xx 重发与人为 replay。
  • 先下单、后通知。Telegram 消息一定绑在下单流程的最后一步——这样消息里的成交价、失败原因才会是真的,而不是「我以为」。

诚实的一段:Telegram 不能当你的 kill switch

这一段是我们自己做过会后悔的:把 Telegram 当唯一的通知管道。Telegram 不保证即时、不保证送达、你也不会收到「这则消息丢了」的通知——Telegram 没有这个机制。任何自动化交易架构都保证不了 100% 送达——包括我们自己。如果你打算靠 Telegram 通知在下单失败时「赶快去补救」,那条依赖是脆的:你可能因为手机没信号、Telegram 通知被系统批量静音、或消息本身在中间层 rate-limit 掉,就错过整整一次事件。

真的要有可以在半夜叫醒你的通知,走 SMS 或电话轮询(PagerDuty、Opsgenie 这类),不要押在 IM 上。Telegram 适合「事后对账」与「例行通知」,不适合「异常必须被看到」的用途。反过来,这也代表 kill switch 这种真的要能立刻停单的按钮不能只放在 Telegram bot 里——它一定要有一个 web dashboard 版本,你手机 App 或朋友的电脑都能点得到。

常见问题

为什么还要 fan-out?TradingView alert 不能一次送到多个地方吗?
TradingView 的 alert 一次只吃一个 webhook URL,那格是文本输入框、不是列表, 你能填的就是一个 URL、一份 payload。 要在同一次信号里把消息送到 Telegram、也送到交易所, 只能由 webhook 那头的中间层完成——这篇整个都在讲那一层怎么设计。
把 TradingView alert 的 webhook URL 直接指到 Telegram Bot API,这样算作弊吗?
完全不算,这是很多人第一步就这样做的用法。 唯一要注意的是:TradingView 对 5xx 会重发最多 3 次, Telegram sendMessage 若在你重发期间偶尔回 5xx,你会收到 2 到 4 则相同消息。 单人自用可以忍,要通知很多人就得在中间加一个能去重的 proxy。
如果我先发 Telegram「已收到信号」再下单,会怎样?
Telegram 消息会误报成功。用户收到「已收到」之后假设「成交了」, 但你的下单可能撞到余额不足、min notional、API key 权限不对,其中任何一个都会让下单根本没发生。正确做法是把 Telegram 绑在下单流程的最后一步—— 拿到交易所回单或明确错误消息之后才推。或明讲「仅代表 alert 收到」, 但那就是两则消息的架构了。
Telegram Bot API 的 rate limit 我怎么知道自己会不会撞到?
单人自用(一策略一账户)基本上不会撞到;会撞的是「一策略多订阅者」或「同时通知一个社群」的场景, 高频 alert 一次会爆。 在中间层加消息队列或改成「每小时汇总一则」都可以, 具体秒级上限请以 Telegram Bot API 官方 FAQ 当下版本为准——这个数字他们保留随时调整。
我要用 TVSBot 的话,Telegram 通知还要自己设吗?
不用。你在 dashboard 拿一组绑定 code,到 Telegram 对 bot 发/start <code>就绑好, 之后下单结果会自动推。也支持 /balance/positions/status三个查询指令(见backend/app/services/telegram.py)。 Kill switch 还是要在 web dashboard 上按, 不是靠 Telegram——这是上一节那段诚实话的落地。

Get started

想把今天学到的东西自动化跑起来?

把 TradingView alert 指过来,下单同时把成交结果推到你的 Telegram——TVSBot 用你自己的 API key、内建 60 秒去重、先下单再通知、支持 dry-run 观察期。

免费开始使用