开发具有 RestAPI 集成的 MQL5 强化学习代理(第 2 部分):用于与井字游戏 RestAPI 进行 HTTP 交互的 MQL5 函数(基础篇)
📘

开发具有 RestAPI 集成的 MQL5 强化学习代理(第 2 部分):用于与井字游戏 RestAPI 进行 HTTP 交互的 MQL5 函数(基础篇)

第 1/2 篇

用 MQL5 打通井字棋 RestAPI 的 HTTP 通道

在 MT5 里做强化学习代理,第一步不是写模型,而是先让 EA 能跟外部 RestAPI 对话。MQL5 自带的 WebRequest 是唯一正路,但它默认被终端沙箱拦着,必须在「选项-Expert Advisors」里勾选「允许 WebRequest 访问」并手动加入目标 URL,否则代码跑起来只返回 5200 错误码。 下面这段是把落子动作 POST 给井字棋服务器的最小可用函数。注意 Content-Type 必须显式写成 application/json,否则 Flask 类后端会直接丢 400。 真实联调时,单次 WebRequest 在本地回环地址平均耗时 8~15 ms,走公网 RestAPI 可能跳到 80~200 ms;强化学习若每步都同步等待,一局 9 手就能吃掉近 2 秒,回测速度会被严重拖垮。

MQL5 / C++
class="type">bool PostMove(class="type">int cell, class="type">class="kw">string &response)
{
   class="type">char post[];
   class="type">class="kw">string data = "{\"cell\":" + (class="type">class="kw">string)cell + "}";
   class="type">int len = StringToCharArray(data, post, class="num">0, WHOLE_ARRAY, CP_UTF8);
   ArrayResize(post, len-class="num">1); class=class="str">"cmt">// 去掉末尾\class="num">0
   class="type">char result[]; class="type">class="kw">string hdr = "Content-Type: application/json\r\n";
   class="type">int timeout = class="num">1000;
   class="type">int ret = WebRequest("POST", "http:class=class="str">"cmt">//class="num">127.0.class="num">0.1:class="num">5000/move", hdr, timeout, post, result);
   if(ret == class="num">200) { response = CharArrayToString(result, class="num">0, WHOLE_ARRAY, CP_UTF8); class="kw">return true; }
   class="kw">return false;
}

「从 RestAPI 概念落到 MQL5 与 Python 的桥接」

前一篇聊过 API 与 RestAPI 的演化,Roy Fielding 的约束让 REST 用更轻的方式替掉 SOAP 之类的老协议。本篇不重复理论,直接把这套东西塞进一个可跑的例子:用 MQL5 发 HTTP 请求,去驱动一个 Python 写的井字游戏。 核心思路是在 MQL5 侧写一组处理 HTTP 调用与响应的函数,它们充当 MT5 终端和外部环境的通信桥。外部环境这边选 FastAPI 扛接口层,原因很实际——异步支持强、写端点快、和现代工具链合得来,能撑住 MQL5 高频轮询而不卡。 全文拆四块:背景回顾、MQL5 的 HTTP 函数开发、FastAPI 给井字游戏做 API、最后用测试脚本把两边接通。重点在第四块,脚本跑起来才算验证前面说的都不是空话。 交互顺序很直白:MQL5 脚本发起落子请求 → 外部 API 接住 → 调 Python 游戏逻辑 → 走 HTTP 回传结果。下面这段是 Python 端落子方法的片段,决定了空格才允许下子、并切换行棋方。 别把异步当万能 FastAPI 的异步只解决接口吞吐,MQL5 侧 WebRequest 仍受 MT5 主线程节奏限制;实盘外接服务若延迟抖动,井字游戏这类 demo 能忍,交易指令链路就得单独加超时与重试。

MQL5 / C++
    def make_move(self, row, col):
        if self.board[row][col] == &class="macro">#x27; &class="macro">#x27;:
            if self.player_turn:
                self.board[row][col] = &class="macro">#x27;X&class="macro">#x27;
            else:
                self.board[row][col] = &class="macro">#x27;O&class="macro">#x27;
            self.player_turn = not self.player_turn
        else:
            print("Invalid game. Try again.")

◍ 从 SOAP 到 RestAPI:金融接口的底层换血

把时间拨回世纪之交,RestAPI 靠着比 SOAP 轻太多的身段快速吃掉了企业级接口市场。SOAP 基于 XML,做个基础查询都要塞进厚厚的信封里传,而 RestAPI 用 URL 加方法就能对话,这在当时就是降维打击。 金融系统是这套架构迁移的典型受益者。RestAPI 在几乎所有编程语言里都能几行代码接上,MT5 终端外的报价中转、账户网关,多半走的就是它而不是老式协议。 它活下来的根本原因不是‘简单’两个字,而是对 JSON 和 XML 两种格式通吃,再加令牌验证和传输层加密。对外汇、贵金属这类碰敏感持仓和资金数据的场景,接口层一旦裸奔,风险直接顺着网线进账户。 第一篇文章只负责把接口的功能、类型和骨架讲清,后面才会碰具体调用和实战封装。

MT5 里跑通 HTTP 调用与 JSON 解析的底层函数

在 MT5 里做外部数据接入,核心是先有一组能直接发 HTTP 请求的函数。下面这三个声明就是基础骨架:SendGetRequest 负责取数,SendPostRequest 负责推数据,Request 则是统一入口,用 method 参数在 GET/POST 之间切换,省得每处都重写底层逻辑。 状态码是判断请求成败的唯一依据。200 到 204 之间算成功区间,函数会把返回体按 UTF-8 解码写进 out 引用变量;404 代表资源不存在,其他非 2xx 则意味着调用方得自己兜底。当前错误处理只是雏形,实盘前建议加重试与日志。 JSON 是这套机制的数据载体。向外发通常把 payload 拼成 JSON,回收的响应也大多是 JSON。为了不依赖外部 DLL,直接用原生 MQL5 写的 JAson 库做解析最干净:它把对象、数组的读写封装成直观方法,嵌套结构也能一行取到,代码可读性比手搓字符处理高出一个档次。 超时参数默认 5000 毫秒,高频策略若连境外 API 延迟偏大,可先调到 8000~10000 做对比。外汇与贵金属行情受消息面冲击剧烈,接外部信号务必用小仓验证,接口抖动可能引发误单。

MQL5 / C++
class="type">int SendGetRequest(const class="type">class="kw">string url, const class="type">class="kw">string query_param, class="type">class="kw">string &out, class="type">class="kw">string headers = "", const class="type">int timeout = class="num">5000)
class="type">int SendPostRequest(const class="type">class="kw">string url, const class="type">class="kw">string payload, class="type">class="kw">string &out, class="type">class="kw">string headers = "", const class="type">int timeout = class="num">5000)
class="type">int Request(class="type">class="kw">string method,
              class="type">class="kw">string &out,
              const class="type">class="kw">string url,
              const class="type">class="kw">string payload = "",
              const class="type">class="kw">string query_param = "",
              class="type">class="kw">string headers = "",
              const class="type">int timeout = class="num">5000)

常见问题

用WebRequest函数发GET/POST,配合StringToCharArray和CharToString处理收发,返回体多为JSON需手动解析字段。
WebRequest倒数第二个参数填超时毫秒数(如1000),并在调用前用ResetLastError查网络错误码定位卡点。
可以,小布能按你贴的MQL5函数逻辑做静态诊断,标出可能阻塞主线程的同步调用并给改写建议。
删掉XML封装改用JSON,把POST体改成轻量字符串,解析从XMLNode换为字符查找或第三方JSON库。
用StringFind定位键名,StringSubstr截取值区间,再StringToInteger转数字,注意转义引号。