如何采用 MQL5 创建用于 Telegram 的 bots(基础篇)
📘

如何采用 MQL5 创建用于 Telegram 的 bots(基础篇)

第 1/3 篇

用 MQL5 把 MT5 信号推到 Telegram

想在 MT5 上把行情或交易信号自动发到 Telegram,核心是先向 BotFather 申请一个 bot,拿到 token,再用 MQL5 的 WebRequest 把消息 POST 出去。这套机制不依赖任何第三方桥接软件,纯靠 MT5 终端联网即可,适合做轻量盯盘提醒。 根据社区公开记录,该思路的原文发布于 2016 年 6 月 30 日,累计浏览 5612 次、收藏 548 次,说明手动写 bot 推送在量化交易者里一直有稳定需求。外汇与贵金属波动快、杠杆高,实盘推送延迟或失败都可能错过风控点,接入前务必在模拟盘验证网络连通性。 MQL5 里最关键的是把 token 和 chat_id 拼进 URL,并用 JSON 封装 text 字段。下面这段是最低可用骨架,复制后把两处 XXX 换成你自己的值就能跑。

MQL5 / C++
class="type">class="kw">string token = "XXX:XXX";
class="type">class="kw">string chat_id = "XXX";
class="type">class="kw">string url = "https:class=class="str">"cmt">//api.telegram.org/bot" + token + "/sendMessage";
class="type">class="kw">string data = "chat_id=" + chat_id + "&text=Hello_from_MT5";
class="type">char post[], result[];
class="type">class="kw">string hdr = "Content-Type: application/x-www-form-urlencoded";
class="type">int timeout = class="num">5000;
WebRequest("POST", url, hdr, timeout, post, result);

「从聊天工具机器人说起」

  • 年 4 月 12 日旧金山 F8 大会上,Facebook 宣布把 Bot API 塞进即时通讯,同一天 Telegram 把 Bot 平台推到 2.0 版。ICQ 时代的老概念借开放接口和多媒体的能力重新活了过来。

所谓 bot,是 Telegram 里的特殊账户,本质用来交换消息。它在你的客户端跑,靠 Bot API 的特定命令和服务器对话。外汇和贵金属行情提醒类 bot 也属于这类,但需注意接口稳定性受平台政策影响,属低风险技术尝试、高风险依赖外部服务。 要跟着做,先装好 Telegram 并登录,注册绑手机号,也能用 @username 搜人。客户端里那个收纳所有 bots 的文件夹,就是后面我们放自己机器人的地方。

◍ 在 BotFather 里拉起一个可用 bot

Telegram 里所有自定义 bot 的增删改都由官方账号 @BotFather 管。搜到它、加进联系人,先发 /start,它会回一份指令清单,里面列了十来条可操作命令,这是后续配置的总入口。 真正建 bot 用 /newbot。它要你连续给两个名字:第一个是显示名,中文也行;第二个是用户名,必须纯拉丁字符且以“bot”结尾。提交后系统返回一个 token 字符串,这是 bot 调 API 的唯一凭证,泄露即失控制权。 有些设置能跳过,但内联模式建议开着,否则很多交互逻辑跑不起来。装饰性三项值得做:/setcommands 定义“/”触发时的提示列表;/setuserpic 给个头像,没图显得像僵尸号;/setdescription 写两句接入时的简介。做完这些,bot 就处于可工作状态,接下来才是决定它用哪种模式接消息。

Telegram bot 的三种通信路径

Telegram 给 bot 与用户之间留了三条交互通道,做信号分发前得先认清楚哪条适合自己。私聊是默认主战场:用户发消息给 bot,服务端只保留不超过 24 小时就清除,bot 必须在这窗口内拉取并回包,我们后续实例也主要跑在这种模式。 群聊靠 /setjoingroups 把 bot 拉进群,再用 /setprivacy 决定它是收全部消息还是只盯 “/” 开头的指令。实战里群模式价值有限,我更倾向只拿它做消息统计,为后面分析攒原始数据。 信道(Channel)是单向广播,不限订阅数、用户不能留言,只有管理员能发内容。把 bot 加进管理员列表,它就变成自动发信号的理想终端——后面我们会写个 bot,把标准 MACD 信号直接推到新建公共信道。建信道用客户端“新信道”菜单,记得从属性窗口把 bot 塞进管理员,这步漏了信号就发不出去。

「让 MT5 机器人接住 Telegram 消息流」

把消息处理从 bot 逻辑里剥离,最省事的办法是写一个基类把例行通信包掉。CCustomBot 就是干这个的:它用 WebRequest 发 POST 到 https://api.telegram.org/bot<TOKEN>/METHOD_NAME,TOKEN 是注册时拿到的令牌,METHOD_NAME 对应 Telegram 支持的方法名。服务器回的是 JSON,所以类里挂了一个本地 JSON 解析器,面板显示则借用了代码库里的 CComment。 目前类里已经封装了 GetMe、GetUpdates、SendMessage、SendPhoto、SendChatAction 这几个方法。GetMe 不干业务,只验证令牌可信度——建议在 EA 的 OnInit 里就跑一次,失败了直接面板告警。成功时返回 0,还能用 Name() 掏出 bot 用户名,例如 telegram.me/<botname> 这种网页入口可以当广告链接用。 真正读消息靠 GetUpdates,必须由定时器周期调用。实测定时器间隔别低于 1 秒,否则容易把 Telegram 服务器打过载被限流。每次调用会拉回未读消息数组,其中 chat[id] 是独占聊天标识——同一用户换设备进来会是不同 chat id,所以拿它当聊天列表的 key 最稳。消息处理完打上结束标志,bot 就能持续累加并刷新最后收到的内容。 自己写 bot 不用碰底层,继承 CCustomBot 然后重写 ProcessMessage 虚函数就行。按文档至少得响应 /start/help,下面这段就是最小可跑的令牌检查代码。 别把令牌当摆设 代码里 InpToken 写死了一个示例串,实盘前必须换成你自己的,且不要随 mq5 文件外发,否则别人能劫持你的 bot。

MQL5 / C++
class="type">int GetMe()
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                Telegram_GetMe.mq5 |
class=class="str">"cmt">//|                                         Copyright class="num">2014, MetaQuotes Software Corp. |
class=class="str">"cmt">//|                                                     [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2014, MetaQuotes Software Corp."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class="macro">#class="kw">property strict
class="macro">#include <Telegram.mqh>
input class="type">class="kw">string InpToken="class="num">177791741:AAH0yB3YV7ywm80af_-AGqb7hzTR_Ud9DhQ";class=class="str">"cmt">//令牌
CCustomBot bot;
class="type">int getme_result;
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|  OnInit                                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">//--- 设置令牌
   bot.Token(InpToken);
class=class="str">"cmt">//--- 检查令牌
   getme_result=bot.GetMe();
class=class="str">"cmt">//--- 返回定时器
   EventSetTimer(class="num">3);
   OnTimer();
class=class="str">"cmt">//--- 结束
   class="kw">return(INIT_SUCCEEDED);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|  OnDeinit                                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnDeinit(const class="type">int reason)
  {
   Comment("");
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|  OnTimer                                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTimer()
  {
class=class="str">"cmt">//--- 显示错误消息并退出

◍ 把 Telegram 回传的 JSON 落进 EA 逻辑

上面这段不是完整可编译的 EA,而是把机器人回调骨架和一份真实回传样例拼在一起看。先说错误处理:若 getme_result 不为 0,说明取机器人自身信息失败,直接在图表上打印「错误:」加描述并 return,避免后续空对象调用崩在半路。 紧接着用 Comment("机器人名字: ",bot.Name()) 把实例名刷到图表左上角,方便你确认当前跑的是哪个 token 对应的 bot;再往下 //---{ 在此插入您的代码 } 就是留给策略逻辑的真坑位。 回传 JSON 里有个具体样本:update_id 为 349778698、message_id 为 2、用户 id 198289825、chat type 为 private、date 时间戳 1459775817(即 2016-04-04 左右)、text 为 /start。你在 MT5 里接 Telegram.mqh 后,ProcessMessages 里解析这类结构,就能按 message.text 触发不同动作。 外汇与贵金属信号推送本身高风险,任何来自聊天的指令都应先做白名单校验再下单,别让私聊直接碰真实账户。

MQL5 / C++
if(getme_result!=class="num">0)
  {
    Comment("错误: ",GetErrorDescription(getme_result));
    class="kw">return;
  }
class=class="str">"cmt">//--- 显示机器人名字
  Comment("机器人名字: ",bot.Name());
class=class="str">"cmt">//---{ 在此插入您的代码 }
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int GetUpdate()
{
  "ok":true,
  "result":[
    {
      "update_id":class="num">349778698,
      "message":{
        "message_id":class="num">2,
        "from":{
          "id":class="num">198289825,
          "first_name":"Andriy",
          "last_name":"Voitenko",
          "username":"avaticks"
        },
        "chat":{
          "id":class="num">198289825,
          "first_name":"Andriy",
          "last_name":"Voitenko",
          "username":"avaticks",
          "type":"class="kw">private"
        },
        "date":class="num">1459775817,
        "text":"/start"
      }
    }
  ]
}

常见问题

先去 BotFather 建一个 bot 拿到 token,再用交易终端的 WebRequest 把报警文本 POST 到 Telegram 接口即可,贵金属波动大需注意推送延迟风险。
别人可伪造你的 bot 发消息或读取对话,应立即在 BotFather 里 Revoke 旧 token 并更换新令牌。
小布已内置多通道消息推送,打开对应品种页绑定聊天账号即可,不用手动接接口。
把 JSON 解析成键值对,提取如 "cmd":"buy" 字段,在 EA 的 OnTick 里做条件分支调用 OrderSend 倾向执行。
多数基础 bot 只做单向推送,要接住消息流需轮询 getUpdates 或设 Webhook,并在代码里处理入站文本。