📘

「用 WinInet 在 MT5 终端间传数据」

「用 WinInet 在 MT5 终端间传数据」

MT5 借助 wininet.dll 可以直接发起 HTTP 请求,把终端变成能互发数据的节点。比起单纯拉一个网页,更有用的是让服务器端 PHP 接收并暂存数据,再转发给别的终端——这样多个 MT5 之间就能双向交换报价或消息。 核心只依赖 7 个 WinInet 函数:InternetAttemptConnect 探连、InternetOpenW 初始化库、InternetConnectW 开连接、HttpOpenRequestW 建请求描述符、HttpSendRequest 发请求、InternetReadFile 读回数据、InternetCloseHandle 释放句柄。会话和连接描述符在 OnInit 里建一次即可,千万别在 OnTimer 里反复初始化,否则频繁建结构体只会拖慢终端。 一个可验证的现象:MQL5 代码库里 ErrorDescription.mqh 的真实路径是 [MQL5官方文档] p.mql5.com、请求 /data/18/79/5/ErrorDescription.mqh、文件名 ErrorDescription.mqh——ParseURL 就是按这种线性拆分干的。 实盘外汇/贵金属走这套机制有高风险:很多站点防爬,机器批量下载若触发封 IP 就断服务;跨经纪商报价也只是「可能」反映真实价差,需自行过滤模拟服务器噪声。

MQL5 / C++
class="macro">#class="kw">import "wininet.dll"
class="type">int InternetAttemptConnect(class="type">int x);
class="type">int InternetOpenW(class="type">class="kw">string &sAgent,class="type">int lAccessType,class="type">class="kw">string &sProxyName,class="type">class="kw">string &sProxyBypass,class="type">int lFlags);
class="type">int InternetConnectW(class="type">int hInternet,class="type">class="kw">string &szServerName,class="type">int nServerPort,class="type">class="kw">string &lpszUsername,class="type">class="kw">string &lpszPassword,class="type">int dwService,class="type">int dwFlags,class="type">int dwContext);
class="type">int HttpOpenRequestW(class="type">int hConnect,class="type">class="kw">string &Verb,class="type">class="kw">string &ObjectName,class="type">class="kw">string &Version,class="type">class="kw">string &Referer,class="type">class="kw">string &AcceptTypes,class="type">uint dwFlags,class="type">int dwContext);

◍ 在 MT5 里用 WinINet 拉起 HTTP 会话

想在 MT5 里直接抓外部行情或接口数据,靠的是对系统 wininet.dll 的封装调用。上面这组函数声明把 HttpSendRequestW、HttpQueryInfoW、InternetReadFile、InternetCloseHandle 全部 import 进来,相当于把 Windows 原生的 HTTP 客户端能力接到了 MQL5 侧。 常量定义里几个十六进制值值得记一下:FLAG_KEEP_CONNECTION 是 0x00400000,FLAG_PRAGMA_NOCACHE 是 0x00000100,FLAG_RELOAD 是 0x80000000。它们直接控制连接是否保活、是否避开本地缓存,写错一位都可能拿到旧数据。 MqlNet::Open 这段是建立会话的主入口。它先判空主机名,再用 TerminalInfoInteger(TERMINAL_DLLS_ALLOWED) 确认终端放行了 DLL——很多自己写的 EA 在默认设置下跑不起来,就是卡在这一关。 随后 InternetAttemptConnect(0) 探一下网络通不通,过了才用 InternetOpenW 开 Session,再用 InternetConnectW 连到指定 Host 和 Port(SERVICE_HTTP 写死为 3)。任一环节返回描述符 ≤0 就打印错误并 Close 收尾。开 MT5 后把这段代码塞进类里,改个 Host 就能验证你的 broker 环境是否允许出网。

MQL5 / C++
class="type">int HttpSendRequestW(class="type">int hRequest,class="type">class="kw">string &lpszHeaders,class="type">int dwHeadersLength,class="type">uchar &lpOptional[],class="type">int dwOptionalLength);
class="type">int HttpQueryInfoW(class="type">int hRequest,class="type">int dwInfoLevel,class="type">int &lpvBuffer[],class="type">int &lpdwBufferLength,class="type">int &lpdwIndex);
class="type">int InternetReadFile(class="type">int hFile,class="type">uchar &sBuffer[],class="type">int lNumBytesToRead,class="type">int &lNumberOfBytesRead);
class="type">int InternetCloseHandle(class="type">int hInet);
class="macro">#class="kw">import
class=class="str">"cmt">//为了清晰起见,我们将使用wininet.h中的常量名
class="macro">#define OPEN_TYPE_PRECONFIG     class="num">0         class=class="str">"cmt">// 使用默认配置
class="macro">#define FLAG_KEEP_CONNECTION    0x00400000 class=class="str">"cmt">// 保持连接
class="macro">#define FLAG_PRAGMA_NOCACHE     0x00000100 class=class="str">"cmt">// 页面不缓存
class="macro">#define FLAG_RELOAD             0x80000000 class=class="str">"cmt">// 当连接时从服务器接收页面
class="macro">#define SERVICE_HTTP            class="num">3          class=class="str">"cmt">// 所需的协议
   class="type">class="kw">string          Host;     class=class="str">"cmt">// 主机名
   class="type">int             Port;     class=class="str">"cmt">// 端口
   class="type">int             Session;  class=class="str">"cmt">// 会话描述符
   class="type">int             Connect;  class=class="str">"cmt">// 连接描述符
class="type">bool MqlNet::Open(class="type">class="kw">string aHost,class="type">int aPort)
  {
   if(aHost=="")
     {
      Print("-Host is not specified");
      class="kw">return(false);
     }
   class=class="str">"cmt">// 检查终端是否允许使用DLL
   if(!TerminalInfoInteger(TERMINAL_DLLS_ALLOWED))
     {
      Print("-DLL is not allowed");
      class="kw">return(false);
     }
   class=class="str">"cmt">// 如果会话已经存在,关闭
   if(Session>class="num">0 || Connect>class="num">0) Close();
   class=class="str">"cmt">// 记录尝试打开的日志
   Print("+Open Inet...");
   class=class="str">"cmt">// 如果我们没能检查到网络连接的存在,那么退出
   if(InternetAttemptConnect(class="num">0)!=class="num">0)
     {
      Print("-Err AttemptConnect");
      class="kw">return(false);
     }
   class="type">class="kw">string UserAgent="Mozilla"; class="type">class="kw">string nill="";
   class=class="str">"cmt">// 打开一个会话
   Session=InternetOpenW(UserAgent,OPEN_TYPE_PRECONFIG,nill,nill,class="num">0);
   class=class="str">"cmt">// 如果我们没能打开会话,则退出
   if(Session<=class="num">0)
     {
      Print("-Err create Session");
      Close();
      class="kw">return(false);
     }
   Connect=InternetConnectW(Session,aHost,aPort,nill,nill,SERVICE_HTTP,class="num">0,class="num">0);
   if(Connect<=class="num">0)
     {
      Print("-Err create Connect");
      Close();
      class="kw">return(false);
     }
   Host=aHost; Port=aPort;
   class=class="str">"cmt">// 否则所有尝试都成功了
   class="kw">return(true);
  }

用 MQL5 直接发 HTTP 请求抓数据

在 MT5 里做价格行为分析时,常需要把外部信号(比如 AIGC 生成的支撑阻力评分)拉进 EA。下面这段封装好的网络请求方法,能让你在 MQL5 里直接走 HTTP/1.1 协议取页面或写文件,不用借助 DLL。

Request() 先判断会话句柄是否还活着,Session 或 Connect 小于等于 0 就自动 Close() 再 Open(Host,Port) 重连;创建请求时写死用 FLAG_KEEP_CONNECTIONFLAG_RELOADFLAG_PRAGMA_NOCACHE,等于强制服务端别拿缓存糊弄你。

发送体头部固定为 Content-Type: application/x-www-form-urlencoded,数据来源分两条路:fromFile 为真就从文件读进 uchar 数组,否则把字符串转字符数组。注意 HttpSendRequestW 传的是 ArraySize(data)-1,把结尾的 \0 截掉,不然服务端可能收脏数据。 ReadPage() 用 100 字节的小缓冲循环 InternetReadFile,一段段拼成字符串;toFile 为真就二进制模式写盘。外汇和贵金属行情接口调用存在断连、超时风险,实盘前务必在策略测试器用模拟 host 跑通再上。

MQL5 / C++
class="type">void MqlNet::CloseInet()
  {
   Print("-Close Inet...");
   if(Session>class="num">0) InternetCloseHandle(Session); Session=-class="num">1;
   if(Connect>class="num">0) InternetCloseHandle(Connect); Connect=-class="num">1;
   }
class="type">bool MqlNet::Request(class="type">class="kw">string Verb,class="type">class="kw">string Object,class="type">class="kw">string &Out,class="type">bool toFile=false,class="type">class="kw">string addData="",class="type">bool fromFile=false)
  {
   if(toFile && Out=="")
     {
       Print("-File is not specified ");
       class="kw">return(false);
     }
   class="type">uchar data[];
   class="type">int hRequest,hSend,h;
   class="type">class="kw">string Vers="HTTP/class="num">1.1";
   class="type">class="kw">string nill="";
   if(fromFile)
     {
       if(FileToArray(addData,data)<class="num">0)
         {
           Print("-Err reading file "+addData);
           class="kw">return(false);
         }
     } class=class="str">"cmt">// 读取数组中的文件内容
   else StringToCharArray(addData,data);
   if(Session<=class="num">0 || Connect<=class="num">0)
     {
       Close();
       if(!Open(Host,Port))
         {
           Print("-Err Connect");
           Close();
           class="kw">return(false);
         }
     }
   class=class="str">"cmt">// 创建一个请求描述符
   hRequest=HttpOpenRequestW(Connect,Verb,Object,Vers,nill,nill,FLAG_KEEP_CONNECTION|FLAG_RELOAD|FLAG_PRAGMA_NOCACHE,class="num">0);
   if(hRequest<=class="num">0)
     {
       Print("-Err OpenRequest");
       InternetCloseHandle(Connect);
       class="kw">return(false);
     }
   class=class="str">"cmt">// 发送请求
   class=class="str">"cmt">// 请求的标题
   class="type">class="kw">string head="Content-Type: application/x-www-form-urlencoded";
   class=class="str">"cmt">// 发送文件
   hSend=HttpSendRequestW(hRequest,head,StringLen(head),data,ArraySize(data)-class="num">1);
   if(hSend<=class="num">0)
     {
       Print("-Err SendRequest");
       InternetCloseHandle(hRequest);
       Close();
     }
   class=class="str">"cmt">// 读取页面 
   ReadPage(hRequest,Out,toFile);
   class=class="str">"cmt">// 关闭所有句柄
   InternetCloseHandle(hRequest);
InternetCloseHandle(hSend);
   class="kw">return(true);
   }
class="type">void MqlNet::ReadPage(class="type">int hRequest,class="type">class="kw">string &Out,class="type">bool toFile)
  {
   class=class="str">"cmt">// 读取页面 
   class="type">uchar ch[class="num">100];
   class="type">class="kw">string toStr="";
   class="type">int dwBytes,h;
   while(InternetReadFile(hRequest,ch,class="num">100,dwBytes))
     {
       if(dwBytes<=class="num">0) break;
       toStr=toStr+CharArrayToString(ch,class="num">0,dwBytes);
     }
   if(toFile)
     {
       h=FileOpen(Out,FILE_BIN|FILE_WRITE);
       FileWriteString(h,toStr);
       FileClose(h);
     }

「用类封装 HTTP 会话与 URL 拆解」

在 MT5 里做网页抓取或外联 API,先把网络会话包成一个类最省事。下面这段 MqlNet 类定义了主机、端口、会话与连接四个私有成员,对外只暴露 Open、Close、Request、OpenURL 等几个方法,调用方不必关心 socket 细节。 ParseURL 函数负责把一个完整 http 链接拆成 host、request 和 filename 三段。它先跳过前 7 个字符(即 'http://'),再用 StringFind 找第一个斜杠切出主机与请求路径;随后从字符串末尾反向扫描拿到末级文件名。注意它假设链接一定带 http:// 前缀,否则 StringSubstr(URL,7) 会直接截掉正常字符。 类里还 import 了 Kernel32.dll 的 MoveFileExW,用来在下载完成后做文件重命名或移动。外汇与贵金属行情接口若走这套抓取逻辑,需意识到网络延迟与连接失败属高风险,回测外数据可能随时中断。

MQL5 / C++
 else Out=toStr;
}
class MqlNet
  {
   class="type">class="kw">string               Host;     class=class="str">"cmt">// 主机名
   class="type">int                  Port;     class=class="str">"cmt">// 端口
   class="type">int                  Session;  class=class="str">"cmt">// 会话描述符
   class="type">int                  Connect;  class=class="str">"cmt">// 连接描述符
class="kw">public:
                       MqlNet(); class=class="str">"cmt">// 类的构造函数
                      ~MqlNet(); class=class="str">"cmt">// 析构函数
   class="type">bool                Open(class="type">class="kw">string aHost,class="type">int aPort); class=class="str">"cmt">// 创建一个会话并打开连接
   class="type">void                Close();   class=class="str">"cmt">// 关闭会话和连接
   class="type">bool                Request(class="type">class="kw">string Verb,class="type">class="kw">string Request,class="type">class="kw">string &Out,class="type">bool toFile=false,class="type">class="kw">string addData="",class="type">bool fromFile=false); class=class="str">"cmt">// 发送请求
   class="type">bool                OpenURL(class="type">class="kw">string URL,class="type">class="kw">string &Out,class="type">bool toFile); class=class="str">"cmt">// 读取页面到文件或变量中
   class="type">void                ReadPage(class="type">int hRequest,class="type">class="kw">string &Out,class="type">bool toFile); class=class="str">"cmt">// 读取页面
   class="type">int                 FileToArray(class="type">class="kw">string FileName,class="type">uchar &data[]); class=class="str">"cmt">// 将文件复制到数组中用于发送
  };
class="macro">#class="kw">import "Kernel32.dll"
class="type">bool MoveFileExW(class="type">class="kw">string &lpExistingFileName, class="type">class="kw">string &lpNewFileName, class="type">int dwFlags);
class="macro">#class="kw">import "Kernel32.dll"
class="type">void ParseURL(class="type">class="kw">string path,class="type">class="kw">string &host,class="type">class="kw">string &request,class="type">class="kw">string &filename)
  {
   host=StringSubstr(URL,class="num">7);
   class=class="str">"cmt">// 移除
   class="type">int i=StringFind(host,"/");
   request=StringSubstr(host,i);
   host=StringSubstr(host,class="num">0,i);
   class="type">class="kw">string file="";
   for(i=StringLen(URL)-class="num">1; i>=class="num">0; i--)
    if(StringSubstr(URL,i,class="num">1)=="/")
      {
       file=StringSubstr(URL,i+class="num">1);
       break;
      }
   if(file!="") filename=file;
  }

◍ 用脚本从网络拉取并归位 MQ5 文件

MT5 脚本可以直接从指定 URL 把 .mq5 文件抓回终端,并按目录类型自动挪到 Experts、Indicators、Scripts 等位置。核心依赖是自定义的 InternetLib.mqh 里的 MqlNet 类,以及 Windows 的 Kernel32.dll 导出的 MoveFileExW。 代码里先通过 ParseURL 拆出主机名和请求路径,默认用 80 端口开会话;若 Open(Host,80) 失败直接退出,成功才打印「+Copy」日志。下载落盘文件名被硬编码为 Recieve_ 加 TimeToString(TimeCurrent()) 再加 .mq5,也就是说同一秒多次运行会覆盖同名文件,这点调试时要注意。 FolderType 枚举把目标目录映射成 0~7 的数字,Files 类型(值 5)是个特例:下载完不移动,直接留在 MQL5\Files 下返回。其余类型会拼出 from(Files 目录源路径)和 to(对应 MQL5 子目录或 Templates/TesterSet 根路径),调用 MoveFileExW 并带 MOVEFILE_REPLACE_EXISTING 标记强制替换。 外汇与贵金属交易终端跑这类自动下载脚本存在较高安全风险,远程 URL 内容不可控,可能引入恶意代码;实盘环境使用前建议在离线或模拟账户终端验证。

MQL5 / C++
class="macro">#class="kw">property copyright "www.fxmaster.de  © class="num">2010"
class="macro">#class="kw">property link      "www.fxmaster.de"
class="macro">#class="kw">property version               "class="num">1.00"
class="macro">#class="kw">property description "Download files from internet"
class="macro">#class="kw">property script_show_inputs
class="macro">#include <InternetLib.mqh>
class="macro">#class="kw">import "Kernel32.dll"
class="type">bool MoveFileExW(class="type">class="kw">string &lpExistingFileName,class="type">class="kw">string &lpNewFileName,class="type">int dwFlags);
class="macro">#class="kw">import
class="macro">#define MOVEFILE_REPLACE_EXISTING 0x1
enum _FolderType
  {
   Experts=class="num">0,
   Indicators=class="num">1,
   Scripts=class="num">2,
   Include=class="num">3,
   Libraries=class="num">4,
   Files=class="num">5,
   Templates=class="num">6,
   TesterSet=class="num">7
  };
input class="type">class="kw">string URL="";
input _FolderType FolderType=class="num">0;
class=class="str">"cmt">//------------------------------------------------------------------ OnStart
class="type">int OnStart()
  {
   MqlNet INet; class=class="str">"cmt">// 在因特网中执行操作的变量
   class="type">class="kw">string Host,Request,FileName="Recieve_"+TimeToString(TimeCurrent())+".mq5";
   class=class="str">"cmt">// 解析url
   ParseURL(URL,Host,Request,FileName);
   class=class="str">"cmt">// 打开会话
   if(!INet.Open(Host,class="num">80)) class="kw">return(class="num">0);
   Print("+Copy "+FileName+" from  http:class=class="str">"cmt">//"+Host+" to "+GetFolder(FolderType));
   class=class="str">"cmt">// 获取文件
   if(!INet.Request("GET",Request,FileName,true))
     {
       Print("-Err download "+URL);
       class="kw">return(class="num">0);
     }
   Print("+Ok download "+FileName);
   class=class="str">"cmt">// 移动到目标文件夹
   class="type">class="kw">string to,from,dir;
   class=class="str">"cmt">// 如果没有必要移动到其他地方
   if(FolderType==Files) class="kw">return(class="num">0);
   class=class="str">"cmt">// 来自
   from=TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\"+FileName;
   class=class="str">"cmt">// 去到
   to=TerminalInfoString(TERMINAL_DATA_PATH)+"\\";
   if(FolderType!=Templates && FolderType!=TesterSet) to+="MQL5\\";
   to+=GetFolder(FolderType)+"\\"+FileName;
   class=class="str">"cmt">// 移动文件 
   if(!MoveFileExW(from,to,MOVEFILE_REPLACE_EXISTING))
     {
       Print("-Err move to "+to);
       class="kw">return(class="num">0);
     }
   Print("+Ok move "+FileName+" to "+GetFolder(FolderType));
   class="kw">return(class="num">0);
  }
class=class="str">"cmt">//------------------------------------------------------------------ GetFolder
class="type">class="kw">string GetFolder(_FolderType foldertype)
  {
   if(foldertype==Experts) class="kw">return("Experts");
   if(foldertype==Indicators) class="kw">return("Indicators");
   if(foldertype==Scripts) class="kw">return("Scripts");
   if(foldertype==Include) class="kw">return("Include");
   if(foldertype==Libraries) class="kw">return("Libraries");

从 URL 里抠出主机名和文件名

做 MT5 下的网页拉取类 EA 时,经常要把一个完整 URL 拆成 host、请求路径和落地文件名三块。上面这段 ParseURL 就是干这个活的:它先从 URL 第 7 个字符起截掉「http://」前缀,再用首个斜杠把主机和请求串切开。 后面那段反向遍历很有用——从字符串末尾往前找第一个「/」,它后面的部分就是远端文件名。像 www.fxmaster.de/metaarbitr.php?server=Metaquotes&pair=EURUSD&bid=1.4512&time=13286794 这种地址,能稳定解析出 host=f xmaster.de、request=/metaarbitr.php?...、filename=metaarbitr.php。 注意原代码里 host 赋值写的是 StringSubstr(URL,7),若你实际传的是带 https 的链接,偏移量得改成 8,否则会把「s」带进主机名。外汇与贵金属接口调用涉及实时报价,网络异常和 broker 限制都是高风险点,解析逻辑先在脚本里跑通再进 EA。

MQL5 / C++
if(foldertype==Files) class="kw">return("Files");
 if(foldertype==Templates) class="kw">return("Profiles\\Templates");
 if(foldertype==TesterSet) class="kw">return("Tester");
 class="kw">return("");
 }
class=class="str">"cmt">//------------------------------------------------------------------ ParseURL
class="type">void ParseURL(class="type">class="kw">string path,class="type">class="kw">string &host,class="type">class="kw">string &request,class="type">class="kw">string &filename)
 {
 host=StringSubstr(URL,class="num">7);
 class=class="str">"cmt">// 移除
 class="type">int i=StringFind(host,"/");
 request=StringSubstr(host,i);
 host=StringSubstr(host,class="num">0,i);
 class="type">class="kw">string file="";
 for(i=StringLen(URL)-class="num">1; i>=class="num">0; i--)
 if(StringSubstr(URL,i,class="num">1)=="/")
 {
 file=StringSubstr(URL,i+class="num">1);
 break;
 }
 if(file!="") filename=file;
 }
class=class="str">"cmt">//+------------------------------------------------------------------+
www.fxmaster.de/metaarbitr.php?server=Metaquotes&pair=EURUSD&bid=class="num">1.4512&time=class="num">13286794

「把工具请下神坛」

GET 请求在 MT5 里已经能跑通网络收发,但别把它当万能钥匙。直接把新闻喂给 EA、远程控单、自动更新指标、跨终端复制信号——这些方向都只是潜在扩展点,实际落地前要自己压测。 本文示例全程用 GET 拿文件或发少量参数,够用在多数轻量场景;下一阶段该看 POST,尤其是传文件和服务端双向同步。 有个真实崩溃样本值得记:2021.12.26 01:06:05 在 EURUSD H1 上 metaarbitrage 打日志 '+Open Inet...',3 秒后 wininet.dll 抛出 Access violation read to 0xFFFFFFFFFFFFFFFF,栈顶停在 cmp word [rcx+rax*2+0x2], 0x0。说明网络库句柄未就绪就进循环,外盘贵金属和外汇这种高波动品种更容易撞上,实盘前务必在策略测试器多跑几轮。 网络功能只是 EA 的辅助手脚,不是印钞插件。开 MT5 把 internetlib.mqh 拖进 include,先复现上面那段日志,确认你的环境不会在 Open Inet 后三秒内崩,再谈别的。

MQL5 / C++
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">05.840 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +Open Inet...
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.537 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Access violation at 0x00007FF93AAE2740 read to 0xFFFFFFFFFFFFFFFF in &class="macro">#x27;wininet.dll&class="macro">#x27;
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;crash --&gt;&nbsp;&nbsp;00007FF93AAE2740 66837C410200&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;word [rcx+rax*class="num">2+0x2], 0x0
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00007FF93AAE2746 488D4001&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lea&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rax, [rax+0x1]
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00007FF93AAE274A 75F4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jnz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0x7ff93aae2740
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00007FF93AAE274C 488B0D8D5D3D00&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rcx, [rip+0x3d5d8d]
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00007FF93AAE2753 8D044502000000&nbsp;&nbsp;&nbsp;&nbsp;lea&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eax, [rax*class="num">2+0x2]
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00007FF93AAE275A 448BC0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r8d, eax
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 00007FF93AAE275D 33D2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xor&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;edx, edx
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="num">00: 0x00007FF93AAE2740
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="num">01: 0x000002C546534171
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="num">02: 0x0000000000CC0038
class="num">2021.12.class="num">26 class="num">01:class="num">06:class="num">08.539 metaarbitrage(EURUSD,H1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="num">03: 0x000002C500000000

常见问题

可用 WinInet 在终端间建 HTTP 会话,一端发请求一端收数据,避免手动导出导入。
用 MQL5 直接发 HTTP 请求拉取数据,注意目标地址需允许跨域且返回纯文本或 JSON。
小布可定时巡检各品种的数据会话状态,异常时推送提醒,你只需看告警不用自己写轮询。
用类封装 URL 拆解,按协议、主机、路径分段截取,主机名取双斜杠后到下一个斜杠,文件名取末级路径。
拉取后按终端数据文件夹规则归位到 MQL5/Scripts 或对应子目录,重启或刷新导航树即可调用。