You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MT4交易订单推送Telegram代码报错求助

MT4交易信息推送Telegram的MQL4代码错误排查与修复

问题描述

编写了一段MQL4代码,用于将MT4的交易订单、订单修改及平仓信息推送至Telegram,但在MetaEditor中持续报错。需要实现:

  • 下单时推送含交易详情+截图的消息
  • 订单更新时推送修改通知
  • 平仓时推送平仓信息

代码中的核心错误点

  • WebRequest参数问题:
    1. 发送消息时text参数未做URL编码,特殊字符会导致请求失败
    2. 发送截图用POST请求时,参数格式错误——Telegram的sendPhoto接口需要用multipart/form-data格式上传文件,不能直接拼接参数
    3. 未初始化的char post[]数组传递给WebRequest,会引发内存异常
  • 事件逻辑混乱:
    1. OnTrade/OnTradeModification/OnTradeClose是MT4内置事件函数,不需要在start()中手动调用,手动调用会导致重复触发
    2. 遍历所有订单会重复推送历史订单,而非仅触发事件的目标订单
  • 截图路径错误:
    WindowScreenShot默认保存到MT4的MQL4\Files目录,但直接传文件名给接口时,WebRequest无法正确读取文件;且未处理截图失败的情况
  • 冗余库引用:WinUser32.mqh、stderror.mqh在代码中未使用,可移除

修正后的代码

// Include necessary libraries
#include <stdlib.mqh>

// 配置Telegram机器人信息
string botToken = "7241390163:AAF_2395NQiPGXbWsXEI5a9nMvn_OccCCZQ";
string chatID = "1233229081";

// URL编码函数,处理特殊字符避免请求失败
string URLEncode(string text) {
   string encoded = "";
   for(int i=0; i<StringLen(text); i++) {
      char c = StringGetChar(text, i);
      if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~') {
         encoded += c;
      } else {
         encoded += "%" + IntegerToString(c, 16);
      }
   }
   return encoded;
}

// 发送文本消息到Telegram
void SendTelegramMessage(string message) {
   string encodedText = URLEncode(message);
   string url = "https://api.telegram.org/bot" + botToken + "/sendMessage?chat_id=" + chatID + "&text=" + encodedText;
   int timeout = 5000;
   char post[] = ""; // 初始化空数组避免内存问题
   int res = WebRequest("GET", url, "", 0, post, timeout);
   if(res != 200) {
      Print("发送消息错误: ", GetLastError());
   }
}

// 发送截图到Telegram(采用multipart/form-data格式)
void SendTelegramScreenshot(string filePath) {
   string boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW";
   string url = "https://api.telegram.org/bot" + botToken + "/sendPhoto";
   int timeout = 10000;

   // 构建请求头和表单数据
   string postData = "--" + boundary + "\r\n";
   postData += "Content-Disposition: form-data; name=\"chat_id\"\r\n\r\n";
   postData += chatID + "\r\n";
   postData += "--" + boundary + "\r\n";
   postData += "Content-Disposition: form-data; name=\"photo\"; filename=\"" + StringSubstr(filePath, StringFind(filePath, "\\")+1) + "\"\r\n";
   postData += "Content-Type: image/png\r\n\r\n";

   // 读取本地截图文件
   int fileHandle = FileOpen(filePath, FILE_BIN | FILE_READ);
   if(fileHandle == INVALID_HANDLE) {
      Print("打开截图文件失败: ", GetLastError());
      return;
   }
   int fileSize = FileSize(fileHandle);
   char fileData[];
   ArrayResize(fileData, fileSize);
   FileReadArray(fileHandle, fileData, 0, fileSize);
   FileClose(fileHandle);

   // 拼接完整请求体
   char post[];
   int postLen = StringLen(postData);
   ArrayResize(post, postLen + fileSize + StringLen("\r\n--" + boundary + "--\r\n"));
   StringToCharArray(postData, post, 0, postLen);
   ArrayCopy(post, fileData, postLen, 0, fileSize);
   StringToCharArray("\r\n--" + boundary + "--\r\n", post, postLen + fileSize);

   string headers = "Content-Type: multipart/form-data; boundary=" + boundary;
   int res = WebRequest("POST", url, headers, 0, post, timeout);
   if(res != 200) {
      Print("发送截图错误: ", GetLastError());
   }
}

// 捕获MT4窗口截图,返回绝对路径
bool CaptureScreenshot(string &filePath) {
   // 保存到MT4的Files目录,生成唯一文件名
   filePath = TerminalInfoString(TERMINAL_DATA_PATH) + "\\MQL4\\Files\\screenshot_" + IntegerToString(GetTickCount()) + ".png";
   bool success = WindowScreenShot(0, 0, 800, 600, filePath);
   if(!success) {
      Print("截图失败: ", GetLastError());
   }
   return success;
}

// 新订单创建事件:仅推送刚创建的订单
void OnTrade() {
   if(OrderSelect(OrdersTotal()-1, SELECT_BY_POS, MODE_TRADES)) {
      string message = "订单创建通知:\n";
      message += "订单ID: " + IntegerToString(OrderTicket()) + "\n";
      message += "方向: " + (OrderType() == OP_BUY ? "做多" : "做空") + "\n";
      message += "品种: " + OrderSymbol() + "\n";
      message += "开仓价: " + DoubleToString(OrderOpenPrice(), Digits) + "\n";
      message += "止损: " + (OrderStopLoss() > 0 ? DoubleToString(OrderStopLoss(), Digits) : "无") + "\n";
      message += "止盈: " + (OrderTakeProfit() > 0 ? DoubleToString(OrderTakeProfit(), Digits) : "无");
      
      SendTelegramMessage(message);
      
      string screenshotPath;
      if(CaptureScreenshot(screenshotPath)) {
         SendTelegramScreenshot(screenshotPath);
         FileDelete(screenshotPath); // 发送后删除本地文件
      }
   }
}

// 订单修改事件:推送修改后的订单信息
void OnTradeModification() {
   if(OrderSelect(OrderTicket(), SELECT_BY_TICKET, MODE_TRADES)) {
      string message = "订单修改通知:\n";
      message += "订单ID: " + IntegerToString(OrderTicket()) + "\n";
      message += "方向: " + (OrderType() == OP_BUY ? "做多" : "做空") + "\n";
      message += "品种: " + OrderSymbol() + "\n";
      message += "开仓价: " + DoubleToString(OrderOpenPrice(), Digits) + "\n";
      message += "新止损: " + (OrderStopLoss() > 0 ? DoubleToString(OrderStopLoss(), Digits) : "无") + "\n";
      message += "新止盈: " + (OrderTakeProfit() > 0 ? DoubleToString(OrderTakeProfit(), Digits) : "无");
      
      SendTelegramMessage(message);
      
      string screenshotPath;
      if(CaptureScreenshot(screenshotPath)) {
         SendTelegramScreenshot(screenshotPath);
         FileDelete(screenshotPath);
      }
   }
}

// 订单平仓事件:推送平仓信息
void OnTradeClose() {
   if(OrderSelect(OrdersHistoryTotal()-1, SELECT_BY_POS, MODE_HISTORY)) {
      string message = "订单平仓通知:\n";
      message += "订单ID: " + IntegerToString(OrderTicket()) + "\n";
      message += "方向: " + (OrderType() == OP_BUY ? "做多" : "做空") + "\n";
      message += "品种: " + OrderSymbol() + "\n";
      message += "平仓价: " + DoubleToString(OrderClosePrice(), Digits) + "\n";
      message += "盈亏: " + DoubleToString(OrderProfit(), 2) + " " + AccountCurrency();
      
      SendTelegramMessage(message);
      
      string screenshotPath;
      if(CaptureScreenshot(screenshotPath)) {
         SendTelegramScreenshot(screenshotPath);
         FileDelete(screenshotPath);
      }
   }
}

// 注意:移除了start()函数,MT4会自动触发OnTrade等内置事件

额外注意事项

  1. MT4权限设置:在MT4的工具->选项->EA交易中,勾选允许WebRequest用于下列URL,并添加https://api.telegram.org
  2. Bot权限:确保Telegram机器人已加入目标聊天,且拥有发送消息和图片的权限
  3. 日志排查:通过MT4的工具->专家日志查看具体错误信息,辅助定位问题

内容的提问来源于stack exchange,提问作者Under IT Guy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 08:52:04