首页 / 交易学院 / 让 MT5 给 MT4 发信号:用 TCP 套接字做跨平台跟单
让 MT5 给 MT4 发信号:用 TCP 套接字做跨平台跟单
🔗

让 MT5 给 MT4 发信号:用 TCP 套接字做跨平台跟单

跨平台 难度 · 高阶 2011 14 分钟阅读
MT5MT4信号TCP套接字

很多人已经用 MQL5 写出好策略,却只能在真实账户跑 MT4;也有人想实时跟随锦标赛领先者。文章给出一套方案:让 MetaTrader 5 当“信号源”,通过 TCP 套接字把每笔交易广播给任意数量的 MT4“跟随端”,且转发在后台线程进行,不拖慢 MT5 本身。

一、为什么要让 MT5 给 MT4 发信号

三个典型动机:其一,MT5 已发布很久,但常用经纪商还没在真实账户放开,有人用 MQL5 写好策略想实盘跑;其二,锦标赛里大家都想跟随领先者,但官网数据每 5 分钟才更新,容易错失买卖点;其三,有人有好策略想共享给朋友,需要支持多连接且实时不降效。这套方案正对这三个痛点。

MT5 的“只读”模式(禁止交易)能访问每个锦标赛账户的仓位、订单、交易信息。作者正是利用这点,在只读权限下也能实时抓取选手的每笔交易活动——这是整个跟随系统的入口。

二、跟随什么:仓位 / 订单 / 交易

要转发信息,得先决定跟什么粒度。单纯跟“仓位”不够全面,除非每单号或每秒都比对状态;挂单信息在“订单”里有但“交易”里缺进场类型(DEAL_ENTRY)。最佳折中是“交易+订单”结合:既有挂单信息,又能跟随账户的交易行为。文章在速度(挂单)和效果(交易)间选了效果,跟“交易”也能执行挂单,只是有微小网络延迟。

// 交易字符串格式示例(用尖括号分隔多笔)
// <EURUSD;BUY;IN;0.01;1.37294>
// <EURUSD;SELL;OUT;0.01;1.37310>
// <EURUSD;SELL;IN;0.01;1.37320>
// <EURUSD;BUY;INOUT;0.02;1.37294>
// 字段:品种;买卖;进场类型;手数;价格

三、传输通道:TCP 套接字

作者比较了几种通信方式:MQL5 没直接 API 做这事,WinInet 类文章不能满足需求。因为客户端很可能在别的机器上,最终选 TCP 连接。服务端用 C# 写(SocketServer.dll),最多支持 500 并发客户端,后台独立线程运行,不阻塞 MT5。MT4 端则借用 MQL4 代码库的 WinSock.mqh 做客户端。

// MT5 端 #import C# 写的 SocketServer.dll
#import "SocketServer.dll"
string About();          // 关于信息
int    SendToAll(string msg);  // 广播给所有客户端
bool   Stop();           // 停止服务器
bool   StartListen(int port);  // 启动监听(最多500客户端)
string ReadLogLine();    // 读服务器日志
#import

四、MT5 端:信号服务器 EA

MT5 端是个 EA(挂哪个货币图都行)。OnInit 里启动监听线程;它不关心连了谁,每次有交易就用 OnTrade() 从最近 24 小时历史里找新交易,构建交易字符串并 SendToAll 广播。即使没人连也照发。OnTimer 每秒打印服务器日志,方便排错。

// OnTrade:发现新交易就广播
void OnTrade() {
  datetime dtStart=TimeCurrent()-60*60*24, dtEnd=TimeCurrent()+60*60*24;
  if(HistorySelect(dtStart,dtEnd)){
    for(int i=0;i<HistoryDealsTotal();i++){
      ulong ticket=HistoryDealGetTicket(i);
      if(HistoryDealGetInteger(ticket,DEAL_ENTRY)!=DEAL_ENTRY_STATE){
        if(HistoryDealGetInteger(ticket,DEAL_TIME)>g_dtLastDealTime){
          int cnt=SendToAll(sBuildDealString(ticket));
          if(cnt>=0) g_dtLastDealTime=(datetime)HistoryDealGetInteger(ticket,DEAL_TIME);
        }
      }
    }
  }
}

五、MT4 端:信号接收脚本

MT4 端用脚本而非 EA,因为它要持续维护与 MT5 的套接字连接、不断接收。作者直接复用 MQL4 代码库的 WinSock.mqh(轻量、测试稳定),连上 MT5 的 SocketServer,解析收到的交易字符串并在本地下单。这样 MT4 端就像“镜像”了 MT5 的信号源账户。

六、数据处理与自定义交易类型

为应对 TCP 可能一次收到多笔、以及部分平仓等边界,作者定义了自定义交易类型 DEAL_ENTRY_OUTALL:当 MT5 端某品种仓位已平完,广播 OUTALL 而非普通 OUT,确保 MT4 端不会留下“幽灵订单”。同时按品种启用/禁用机制,避免把禁用品种的信号误执行。手数映射上,INOUT 只取 IN 部分手数,减少跨端微小手数差异。

跨经纪商点差、最小手数、合约大小不同,MT4 端跟单必须做手数缩放和品种映射,不能直接照搬字符串里的手数。生产环境还要加“断线重连”和“启动类型(CLEAR/CONTINUE)”处理,避免重启后重复或漏单。

七、小结

让 MT5 给 MT4 发信号,本质是用 TCP 把“交易事件”从信号源实时广播给跟随端:MT5 端 C# SocketServer 后台监听、OnTrade 广播;MT4 端 WinSock 接收并执行。它解决了“好策略在 MT5、实盘在 MT4”和“跟随锦标赛”两类刚需。上线前务必处理好手数映射、断线重连和自定义 OUTALL 类型——跨平台跟单的细节全在边界情况里。

常见问题

不能直接,但可间接:MQL5 没有跨平台 API,文章用 TCP 套接字搭桥——MT5 端跑一个 C# SocketServer(后台线程、最多 500 客户端),每次 OnTrade 有新交易就广播交易字符串;MT4 端用 WinSock.mqh 连接并解析执行。本质是“MT5 广播、MT4 镜像”。
因为跟随端很可能在另一台机器上,需要长连接、双向、低延迟的实时通道。WinInet 类文章多用于终端间偶发数据交换,不适合“持续推送多客户端”。TCP 套接字能稳定维持连接并并发广播,更适合信号转发。
延迟主要来自网络。文章在“速度(挂单)和效果(交易)”间选了效果,跟“交易”也能执行挂单,只是有微小网络延迟。同一局域网内延迟极低;跨公网取决于带宽和距服务器的跳数。对秒级进出敏感的策略要实测延迟再决定。
作者定义了自定义交易类型 DEAL_ENTRY_OUTALL:当 MT5 端某品种仓位已平完,广播 OUTALL 而非普通 OUT,确保 MT4 端不会留下未平的“幽灵订单”。INOUT 类型则只取 IN 部分手数,减小跨端手数差异。这些边界类型是保证两端仓位一致的关键。
文章里的 C# SocketServer 设计上限是 500 个并发客户端,且用异步线程处理连接,不会因客户端数量拖慢 MT5 或交易策略。实际能撑多少还取决于服务器带宽和每笔广播的数据量。