Connexus入门(第一部分):如何使用WebRequest函数?(基础篇)
📘

Connexus入门(第一部分):如何使用WebRequest函数?(基础篇)

第 1/3 篇

在MT5里用WebRequest拉外部数据

MT5 的 MQL5 提供了 WebRequest 函数,让 EA 或指标能直接向外部 HTTP 接口发请求,把网页端行情、信号或自定义 API 数据拉进终端做处理。对做价格行为结合外部因子的交易者来说,这是把「小布盯盘」类分析接进自动系统的底层入口。 函数原型要求先声明目标域名白名单,否则调用会被终端安全策略拦截。实测在 MetaTrader 5 build 4410 之后,未在「工具→选项→EA交易」里勾选「允许 WebRequest 向以下 URL 列表」并填好域名,函数会直接返回 false,错误码 5400。 下面这段示范如何向一个 JSON 接口取数据并落到变量里,注意头文件与异步标志位:

MQL5 / C++
class="macro">#include <Trade/Trade.mqh>
class="type">class="kw">string headers="";
class="type">char result[];
class="type">class="kw">string result_headers;
class="type">int timeout=class="num">5000;
class="type">class="kw">string url="https:class=class="str">"cmt">//api.example.com/quotes";
class="type">bool ok=WebRequest("GET",url,headers,timeout,result,result_headers);
if(!ok) Print("WebRequest failed, error ",GetLastError());
逐行拆解:第一行引交易辅助库(本例仅示意依赖);headers 置空表示不带自定义请求头;result 存响应字节流,result_headers 存响应头;timeout 设 5 秒防止卡死;url 须是白名单内域名;WebRequest 同步调用,返回 bool 指示成败;失败时用 GetLastError 打印具体错误码,便于排查 5400 类权限问题。 外汇与贵金属杠杆高、滑点大,接外部数据做自动决策前,务必在策略测试器用 2023—2024 年真实 tick 回测,确认延迟与失败分支不会让仓位失控。

MQL5 / C++
class="macro">#include <Trade/Trade.mqh>
class="type">class="kw">string headers="";
class="type">char result[];
class="type">class="kw">string result_headers;
class="type">int timeout=class="num">5000;
class="type">class="kw">string url="https:class=class="str">"cmt">//api.example.com/quotes";
class="type">bool ok=WebRequest("GET",url,headers,timeout,result,result_headers);
if(!ok) Print("WebRequest failed, error ",GetLastError());

「MT5 里 WebRequest 为什么不够用」

在 MT5 里做外部通信,WebRequest 是官方给的唯一原生函数。想让 EA 拉新闻 API、查交易所币种报价、把信号推到第三方服务,都得走它。 但实际用起来很快会卡壳:头部拼错、JSON 格式不对、响应解析异常,任何一处都能让请求静默失败。对新手来说,光搞清 HTTP 协议和系统间握手就够劝退,更别说还要在 EA 里兜底超时和报错。 我们这套系列要做的,是先把 WebRequest 的短板摊开,再逐步攒出一个叫 Connexus 的库,把底层网络细节封掉。目标很直接——你只写策略逻辑,不用再调头部和格式 bug。 后面几篇会碰 API 鉴权、大体积数据、并发请求和响应时间控制。外汇和贵金属本身高杠杆高风险,自动化拉外部数据若延迟或出错,可能放大滑点和错单,验证前务必在模拟盘跑通。

◍ WebRequest 的参数坑比你想的多

MQL5 里跟外部服务器打交道,核心就是 WebRequest。它支持 GET 和 POST 两种请求,能接几乎所有公开 API,但真写起来远没有文档开头那句「发送请求并接收响应」轻松。 函数有两种重载:带 headers 参数的版本把 cookie、referer 拆掉,改由 headers 数组统一传;不带 headers 的版本则保留 cookie 和 referer 独立入参。下面这段是原生声明,注意参数顺序差异。

MQL5 / C++
class="type">int  WebRequest(
  class="kw">const class="type">class="kw">string      method,       class=class="str">"cmt">// HTTP method 
  class="kw">const class="type">class="kw">string      url,          class=class="str">"cmt">// URL
  class="kw">const class="type">class="kw">string      cookie,       class=class="str">"cmt">// cookie
  class="kw">const class="type">class="kw">string      referer,      class=class="str">"cmt">// referer
  class="type">int               timeout,      class=class="str">"cmt">// timeout
  class="kw">const class="type">char       &data[],       class=class="str">"cmt">// the array of the HTTP message body
  class="type">int               data_size,    class=class="str">"cmt">// data[] array size in bytes
  class="type">char             &result[],     class=class="str">"cmt">// an array containing server response data
  class="type">class="kw">string           &result_headers class=class="str">"cmt">// headers of server response
  );
class="type">int  WebRequest(
  class="kw">const class="type">class="kw">string      method,       class=class="str">"cmt">// HTTP method
  class="kw">const class="type">class="kw">string      url,          class=class="str">"cmt">// URL
  class="kw">const class="type">class="kw">string      headers,      class=class="str">"cmt">// headers 
  class="type">int               timeout,      class=class="str">"cmt">// timeout
  class="kw">const class="type">char       &data[],       class=class="str">"cmt">// the array of the HTTP message body
  class="type">char             &result[],     class=class="str">"cmt">// an array containing server response data
  class="type">class="kw">string           &result_headers class=class="str">"cmt">// headers of server response
  );
逐行拆一下第一段声明:method 决定 GET 拉数据还是 POST 推数据;url 必须带 http/https 全址;cookie 和 referer 是独立字符串;timeout 单位是毫秒,设太小容易断、设太大 EA 可能卡死等响应;data 是 POST 正文,得先转成 char 字节数组;data_size 必须和 data 实际长度一致;result 收服务器返回的字节流,要自己解码;result_headers 拿响应头,常含 content-type 或鉴权状态。 第二段只是把 cookie、referer 合并进 headers 字符串,每个头用「键:值」写,之间以 \r\n 换行分隔。两种版本返回的都是 HTTP 状态码,非 200 系列基本意味着通信失败。 实际踩坑集中在三处:POST 的 data 不会自动序列化,JSON 要自己 StringToCharArray;timeout 建议 1000–5000 毫秒区间,外汇和贵金属行情接口在高波动时延迟可能翻倍;result 里的字节数组若不解码直接打印会是乱码。开 MT5 新建脚本跑一遍上面声明,改 url 指向一个返回纯文本的测试接口,就能直观看到哪一步最易错。

MQL5 / C++
class="type">int  WebRequest(
  class="kw">const class="type">class="kw">string      method,       class=class="str">"cmt">// HTTP method 
  class="kw">const class="type">class="kw">string      url,          class=class="str">"cmt">// URL
  class="kw">const class="type">class="kw">string      cookie,       class=class="str">"cmt">// cookie
  class="kw">const class="type">class="kw">string      referer,      class=class="str">"cmt">// referer
  class="type">int               timeout,      class=class="str">"cmt">// timeout
  class="kw">const class="type">char       &data[],       class=class="str">"cmt">// the array of the HTTP message body
  class="type">int               data_size,    class=class="str">"cmt">// data[] array size in bytes
  class="type">char             &result[],     class=class="str">"cmt">// an array containing server response data
  class="type">class="kw">string           &result_headers class=class="str">"cmt">// headers of server response
  );
class="type">int  WebRequest(
  class="kw">const class="type">class="kw">string      method,       class=class="str">"cmt">// HTTP method
  class="kw">const class="type">class="kw">string      url,          class=class="str">"cmt">// URL
  class="kw">const class="type">class="kw">string      headers,      class=class="str">"cmt">// headers 
  class="type">int               timeout,      class=class="str">"cmt">// timeout
  class="kw">const class="type">char       &data[],       class=class="str">"cmt">// the array of the HTTP message body
  class="type">char             &result[],     class=class="str">"cmt">// an array containing server response data
  class="type">class="kw">string           &result_headers class=class="str">"cmt">// headers of server response
  );

用 httpbin 跑通 WebRequest 的 POST 坑点

想在 MT5 里验证 WebRequest 到底怎么发请求,最省事的办法是拿 httpbin.org 当镜子——它开源免费,会把你发过去的内容原样返给你,适合检查头部、正文和状态码。先在终端「工具 → 选项 → 工具」里把 https://httpbin.org 加进允许 URL 列表,否则函数直接被拦。 第一步先发个 GET,状态码回 200 就说明链路通了;接着改 POST,把 JSON 正文丢进请求体。问题来了:httpbin 返回的「data」和「json」字段全是空的,因为没告诉服务器内容类型是 application/json,补上请求头部后才算入门。 真正的坑在 StringToCharArray——它会在末尾塞一个空终止符 \u0000。打印出来能看到字节数组比字符串多 1 位,最后值是 0 而不是 125(即「}」)。不处理掉,服务端就不认你发的 JSON。用 ArrayRemove() 砍掉末位,字符串和数组长度对齐,响应里「json」字段才正常回显。 这套动作暴露出 WebRequest 并不友好:一个终止符就能让 POST 失效。外汇与贵金属 EA 调用外部接口本就带网络与协议风险,实盘前务必在 demo 环境复现上述 200 与字段回显现象。Connexus 这类封装库的价值,就是替你挡住这种底层字节级麻烦。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                              WebRequest.mq5 |
class=class="str">"cmt">//|                   Copyright class="num">2023, MetaQuotes Ltd. |
class=class="str">"cmt">//|                                 [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2023, MetaQuotes Ltd."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                     |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">//---

class=class="str">"cmt">//---
   class="kw">return(INIT_SUCCEEDED);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert deinitialization function                                   |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnDeinit(class="kw">const class="type">int reason)
  {
class=class="str">"cmt">//---

  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert tick function                                               |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick()
  {
class=class="str">"cmt">//---

  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">//--- Defining variables

常见问题

先到客户端设置允许WebRequest访问对应URL白名单,再检查是否用了https且地址完全匹配,否则会被静默拦截。
它不支持重定向、部分TLS配置和复杂鉴权,遇到需要跳转或双向认证的接口基本跑不通,只能换外部程序中转。
可以,小布能根据你贴的代码和报错,指出URL白名单、header拼法、body编码这几类常见错误并给修改建议。
多半是Content-Type没设成application/json且body没按UTF-8字节流传,补header并重算数组长度再发一次。
timeout参数单位毫秒别超过平台上限,且它本质阻塞调用,高频场景建议移出主线程或用本地代理缓存。