Viewing the resource: Telegram Bot Trading Interface in MQL5

Telegram Bot Trading Interface in MQL5

Allan Munene Mutiiria 2025-06-26 10:56:21 132 Views
This MQL5 EA uses a Telegram bot to execute trades (0.01 lots, 300-pip SL/TP), close positions, and ...

Introduction

Imagine commanding your trading operations from a remote Telegram interface, like a mission control center directing market actions with precision. The Telegram Bot to MQL5 EA is your advanced trading interface, integrating MetaTrader 5 with Telegram to enable interactive trading and monitoring. Using a custom JSON parser ("CJSONValue") and bot communication ("CBot_EA", "InpToken"), it processes commands like /buy to open 0.01-lot trades ("obj_Trade.Buy()", 300-pip SL/TP), /close to close positions ("obj_Trade.PositionClose()"), /info for account details, /quotes for ask/bid prices, and /screenshot for chart images ("SendScreenshot()", 1366x768). Interactive keyboard menus ("KEYB_MAIN", "KEYB_MORE", etc.) guide users through commands, with updates polled every 3 seconds ("EventSetMillisecondTimer(3000)"). This strategy suits traders seeking remote control and real-time updates, requiring a stable internet connection and proper Telegram API setup.

This article is crafted with a professional, engaging, and seamless narrative, flowing like a well-calibrated command center, designed to inform and captivate readers. Tailored for both novice and experienced traders, we’ll dissect each code component with clear, precise explanations, as if guiding an apprentice commander through a trading control project. With vivid examples—like executing EURUSD trades—and a polished tone, we’ll explore how the EA initializes, processes commands, executes trades, and ensures cleanup. Using a precision command center metaphor, this guide will illuminate the code’s technical rigor, empowering you to manage trades with confidence. Let’s activate the system and begin this trading expedition!

Strategy Blueprint

Let’s outline the EA’s command framework, like drafting specifications for a trading control center:

  • Bot Setup: Initializes a Telegram bot ("InpToken", "CBot_EA") with JSON parsing ("CJSONValue") to handle commands via "getUpdates()", "processMessages()".

  • Command Processing: Responds to commands ("/buy", "/close", "/info", "/quotes", "/screenshot") for trading, position closure, and data updates using "SendMessage()", "SendScreenshot()".

  • Trade Execution: Opens 0.01-lot buy trades ("obj_Trade.Buy()", 300-pip SL/TP) or closes positions ("obj_Trade.PositionClose()") based on commands.

  • User Interaction: Uses keyboard menus ("KEYB_MAIN", "KEYB_SYMBOLS") to guide command selection, with emoji support ("EMOJI_UP", "StringDecode()") and HTML formatting.

  • Execution: Polls for messages every 3 seconds ("OnTimer()") with data from "PostRequest()", "SymbolInfoDouble()".

  • Enhancements: Adding configurable lot sizes, SL/TP, or user authentication could improve flexibility and security. This framework automates interactive trading with precision, bridging Telegram and MetaTrader 5.

Code Implementation

Let’s step into the trading command center and dissect the MQL5 code that powers this Telegram Bot to MQL5 EA. We’ll guide you through each phase like expert commanders, ensuring the narrative flows seamlessly with professional clarity and engaging precision that captivates readers. We’ll cover initialization, command processing, trade execution, screenshot sending, and cleanup, with detailed explanations and examples—like managing EURUSD trades—to make it accessible for beginners. Each phase will build on the last, crafting a cohesive technical narrative that transforms code into a compelling trading control project. Let’s power up the system and begin!

Phase 1: Constructing the Framework—Initialization

We start by building the command system, initializing the Telegram bot and timer.

//+------------------------------------------------------------------+
//|                                      TELEGRAM BOT TO MQL5 EA.mq5 |
//|                           Copyright 2025, Allan Munene Mutiiria. |
//|                                   https://t.me/Forex_Algo_Trader |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Allan Munene Mutiiria."
#property link      "https://t.me/Forex_Algo_Trader"
#property version   "1.00"

CBot_EA obj_Bot;

int OnInit(){
   EventSetMillisecondTimer(3000);
   OnTimer();
   return(INIT_SUCCEEDED);
}

The system begins with the #property header, establishing copyright and contact details, like calibrating a command center’s core. The "OnInit()" function initializes the setup, creating a "CBot_EA" instance ("obj_Bot") and setting a 3-second timer ("EventSetMillisecondTimer(3000)") to poll for Telegram updates via "OnTimer()". It calls "OnTimer()" immediately to start processing. Returning INIT_SUCCEEDED signals, “System is ready, let’s command trades!” This primes the EA for Telegram interaction, like a control center poised for action.

Phase 2: Processing Commands—Handling Telegram Messages

With the system active, we fetch and process Telegram messages, like receiving orders in a command center.

void CBot_EA::getUpdates(void){
   if (m_token==NULL){
      Print("ERROR: TOKEN IS EMPTY");
      return (-1);
   }
   string out;
   string url = TELEGRAM_BASE_URL+"/bot"+m_token+"/getUpdates";
   string params = "offset="+IntegerToString(m_update_id);
   int res = PostRequest(out,url,params,WEB_TIMEOUT);
   if (res==0){
      CJSONValue obj_json(NULL,jv_UNDEF);
      bool done = obj_json.Deserialize(out);
      if (!done){
         Print("ERROR: JSON PARSING FAILED");
         return (-1);
      }
      bool ok = obj_json["ok"].ToBool();
      if (!ok){
         Print("ERROR: JSON NOT OK");
         return (-1);
      }
      CMessage obj_msg;
      int total = ArraySize(obj_json["result"].m_elements);
      for (int i=0; i<total; i++){
         CJSONValue obj_item = obj_json["result"].m_elements[i];
         obj_msg.update_id=obj_item["update_id"].ToInt();
         obj_msg.message_id=obj_item["message"]["message_id"].ToInt();
         obj_msg.message_date=(datetime)obj_item["message"]["date"].ToInt();
         obj_msg.message_text=obj_item["message"]["text"].ToStr();
         obj_msg.message_text=StringDecode(obj_msg.message_text);
         obj_msg.from_id=obj_item["message"]["from"]["id"].ToInt();
         obj_msg.from_first_name=obj_item["message"]["from"]["first_name"].ToStr();
         obj_msg.from_first_name=StringDecode(obj_msg.from_first_name);
         obj_msg.from_last_name=obj_item["message"]["from"]["last_name"].ToStr();
         obj_msg.from_last_name=StringDecode(obj_msg.from_last_name);
         obj_msg.from_username=obj_item["message"]["from"]["username"].ToStr();
         obj_msg.from_username=StringDecode(obj_msg.from_username);
         obj_msg.chat_id=obj_item["message"]["chat"]["id"].ToInt();
         obj_msg.chat_first_name=obj_item["message"]["chat"]["first_name"].ToStr();
         obj_msg.chat_first_name=StringDecode(obj_msg.chat_first_name);
         obj_msg.chat_last_name=obj_item["message"]["chat"]["last_name"].ToStr();
         obj_msg.chat_last_name=StringDecode(obj_msg.chat_last_name);
         obj_msg.chat_username=obj_item["message"]["chat"]["username"].ToStr();
         obj_msg.chat_username=StringDecode(obj_msg.chat_username);
         obj_msg.chat_type=obj_item["message"]["chat"]["type"].ToStr();
         m_update_id=obj_msg.update_id+1;
         if (m_first_remove){
            continue;
         }
         if (m_users_filter.Total()==0 || (m_users_filter.Total()>0 && m_users_filter.SearchLinear(obj_msg.from_username)>0)){
            int index = -1;
            for (int j=0; j<m_chats.Total(); j++){
               CChat *chat=m_chats.GetNodeAtIndex(j);
               if (chat.m_id==obj_msg.chat_id){
                  index = j;
                  break;
               }
            }
            if (index == -1){
               m_chats.Add(new CChat);
               CChat *chat = m_chats.GetLastNode();
               chat.m_id=obj_msg.chat_id;
               chat.m_time=TimeLocal();
               chat.m_state=0;
               chat.m_new_one.message_text=obj_msg.message_text;
               chat.m_new_one.done=false;
            }
            else {
               CChat *chat=m_chats.GetNodeAtIndex(index);
               chat.m_time=TimeLocal();
               chat.m_new_one.message_text=obj_msg.message_text;
               chat.m_new_one.done=false;
            }
         }
      }
      m_first_remove=false;
   }
   return (res);
}

In the command processing hub, "getUpdates()" in "CBot_EA" fetches new Telegram messages ("PostRequest()", "TELEGRAM_BASE_URL", "m_token", "m_update_id") and parses JSON responses using "CJSONValue", "Deserialize()". It extracts message details ("message_text", "chat_id", "from_username", etc., via "ToInt()", "ToStr()", "StringDecode()") and updates chat states ("m_chats", "CChat", "m_new_one") if the user is allowed ("m_users_filter"). It increments "m_update_id" to avoid reprocessing. For example, on EURUSD, a “/buy” command is parsed, like receiving an order in the control center.

Phase 3: Executing Commands—Processing User Inputs

With messages received, we process commands to execute trades or send updates, like acting on control center directives.

void CBot_EA::processMessages(void){
   #define EMOJI_UP "\X2B06"
   #define EMOJI_PISTOL "\xF52B"
   #define EMOJI_CANCEL "\x274C"
   #define KEYB_MAIN "[[\"Name\"],[\"Account Info\"],[\"Quotes\"],[\"More\",\"Screenshot\",\""+EMOJI_CANCEL+"\"]]"
   #define KEYB_MORE "[[\""+EMOJI_UP+"\"],[\"Buy\",\"Close\",\"Next\"]]"
   #define KEYB_NEXT "[[\""+EMOJI_UP+"\",\"Contact\",\"Join\",\""+EMOJI_PISTOL+"\"]]"
   #define KEYB_SYMBOLS "[[\""+EMOJI_UP+"\",\"AUDUSDm\",\"AUDCADm\"],[\"EURJPYm\",\"EURCHFm\",\"EURUSDm\"],[\"USDCHFm\",\"USDCADm\",\""+EMOJI_PISTOL+"\"]]"
   #define KEYB_PERIODS "[[\""+EMOJI_UP+"\",\"M1\",\"M15\",\"M30\"],[\""+EMOJI_CANCEL+"\",\"H1\",\"H4\",\"D1\"]]"
   for (int i=0; i<m_chats.Total(); i++){
      CChat *chat=m_chats.GetNodeAtIndex(i);
      if (!chat.m_new_one.done){
         chat.m_new_one.done=true;
         string text = chat.m_new_one.message_text;
         if (text=="/start" || text=="Start" || text=="/help" || text=="Help"){
            string message = "I am a Bot \xF680 and I work with your trading account.\n";
            message+="You can control me by sending these commands \xF648 \n";
            SendMessage(chat.m_id,message,replyKeyboardMarkup(KEYB_MAIN,false,false));
            continue;
         }
         if (text=="/buy" || text=="Buy"){
            CTrade obj_Trade;
            double Ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
            double Bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
            obj_Trade.Buy(0.01,NULL,0,Bid-300*_Point,Bid+300*_Point);
            double entry=0,sl=0,tp=0,vol=0;
            ulong ticket = obj_Trade.ResultOrder();
            if (ticket > 0){
               if (PositionSelectByTicket(ticket)){
                  entry=PositionGetDouble(POSITION_PRICE_OPEN);
                  sl=PositionGetDouble(POSITION_SL);
                  tp=PositionGetDouble(POSITION_TP);
                  vol=PositionGetDouble(POSITION_VOLUME);
               }
            }
            string message="\xF340\Opened Buy Position:\n";
            message+="Ticket: "+(string)ticket+"\n";
            SendMessage(chat.m_id,message);
            continue;
         }
         if (text=="/close" || text=="Close"){
            CTrade obj_Trade;
            int totalOpenBefore = PositionsTotal();
            obj_Trade.PositionClose(_Symbol);
            int totalOpenAfter = PositionsTotal();
            string message="\xF62F\Closed position:\n";
            message+="Total positions (Before): "+string(totalOpenBefore)+"\n";
            SendMessage(chat.m_id,message);
            continue;
         }
         if (text=="/screenshot" || text=="Screenshot"){
            chat.m_state=10;
            string message = "Provide a symbol like 'AUDUSDm'";
            SendMessage(chat.m_id,message,replyKeyboardMarkup(KEYB_SYMBOLS,false,false));
            continue;
         }
         if (chat.m_state==10){
            string user_symbol = text;
            if (SymbolSelect(user_symbol,true)){
               chat.m_state=11;
               string message = "CORRECT: Symbol is valid\n";
               message+="Now provide a period like 'H1'";
               SendMessage(chat.m_id,message,replyKeyboardMarkup(KEYB_PERIODS,false,false));
            }
            continue;
         }
         if (chat.m_state==11){
            bool found = false;
            int total = ArraySize(periods);
            for (int k = 0; k<total; k++){
               string truncated_prd = StringSubstr(EnumToString(periods[k]),7);
               if (StringCompare(truncated_prd,text,false)==0){
                  period = periods[k];
                  found = true;
                  break;
               }
            }
            if (found){
               string message = "CORRECT: Period is valid\n";
               message+="Screenshot sending process initiated \xF60E";
               SendMessage(chat.m_id,message,replyKeyboardMarkup(KEYB_PERIODS,false,false));
               string caption = "Screenshot of symbol: "+symbol+" ("+EnumToString(ENUM_TIMEFRAMES(period))+") @ Time: "+TimeToString(TimeCurrent());
               SendScreenshot(chat.m_id,symbol,period,caption);
            }
            continue;
         }
      }
   }
}

In the execution hub, "processMessages()" in "CBot_EA" handles commands ("m_new_one.message_text"). Commands like "/start" or "/help" display a menu ("SendMessage()", "KEYB_MAIN") with options (Name, Account Info, Quotes, etc.). "/buy" opens a 0.01-lot buy ("obj_Trade.Buy()", 300-pip SL/TP) and reports details ("PositionGetDouble()", "ResultOrder()") via Telegram. "/close" closes all positions for the symbol ("obj_Trade.PositionClose()", "PositionsTotal()") and confirms. "/screenshot" prompts for a symbol ("KEYB_SYMBOLS", state=10) and timeframe ("KEYB_PERIODS", state=11), validated via "SymbolSelect()", "periods". For example, on EURUSD, “/buy” opens a trade at ask=1.2007, SL=1.1707, TP=1.2307, with a Telegram reply, like executing a control center order.

Phase 4: Sending Screenshots—Transmitting Chart Visuals

For screenshot requests, we capture and send charts to Telegram, like dispatching visuals.

void SendScreenshot(const long chat_id,string symbol,ENUM_TIMEFRAMES period,string caption){
   const string SCREENSHOT_FILE_NAME = "My Screenshot.jpg";
   long chart_id = ChartOpen(symbol,period);
   ChartSetInteger(chart_id,CHART_BRING_TO_TOP,true);
   int wait = 60;
   while (--wait > 0){
      if (SeriesInfoInteger(symbol,period,SERIES_SYNCHRONIZED)){
         break;
      }
   }
   ChartSetInteger(chart_id,CHART_SHOW_GRID,false);
   ChartSetInteger(chart_id,CHART_SHOW_PERIOD_SEP,false);
   ChartRedraw(chart_id);
   if (FileIsExist(SCREENSHOT_FILE_NAME)){
      FileDelete(SCREENSHOT_FILE_NAME);
      ChartRedraw(chart_id);
   }
   ChartScreenShot(chart_id,SCREENSHOT_FILE_NAME,1366,768,ALIGN_RIGHT);
   ChartClose(chart_id);
   wait = 60;
   while(!FileIsExist(SCREENSHOT_FILE_NAME) && --wait > 0){
      Sleep(500);
   }
   if (!FileIsExist(SCREENSHOT_FILE_NAME)){
      Print("SPECIFIED SCREENSHOT DOES NOT EXIST. REVERTING NOW");
      return;
   }
   int screenshot_Handle = FileOpen(SCREENSHOT_FILE_NAME,FILE_READ|FILE_BIN);
   if (screenshot_Handle == INVALID_HANDLE){
      Print("INVALID SCREENSHOT HANDLE. REVERTING NOW!");
      return;
   }
   int screenshot_Handle_Size = (int)FileSize(screenshot_Handle);
   uchar photoArr_Data[];
   ArrayResize(photoArr_Data,screenshot_Handle_Size);
   FileReadArray(screenshot_Handle,photoArr_Data,0,screenshot_Handle_Size);
   FileClose(screenshot_Handle);
   uchar base64[];
   uchar key[];
   CryptEncode(CRYPT_BASE64,photoArr_Data,key,base64);
   uchar temporaryArr[1024] = {0};
   ArrayCopy(temporaryArr,base64,0,0,1024);
   uchar md5[];
   CryptEncode(CRYPT_HASH_MD5,temporaryArr,key,md5);
   string hash = NULL;
   int total = ArraySize(md5);
   for (int i=0; i<total; i++){
      hash+=StringFormat("%02X",md5[i]);
   }
   hash = StringSubstr(hash,0,16);
   const string METHOD = "POST";
   string HEADERS = NULL;
   string URL = NULL;
   char DATA[];
   char RESULT[];
   string RESULT_HEADERS = NULL;
   URL = TELEGRAM_BASE_URL+"/bot"+InpToken+"/sendPhoto";
   ArrayAdd(DATA,"\r\n");
   ArrayAdd(DATA,"--"+hash+"\r\n");
   ArrayAdd(DATA,"Content-Disposition: form-data; name=\"chat_id\"\r\n");
   ArrayAdd(DATA,"\r\n");
   ArrayAdd(DATA,IntegerToString(chat_id));
   ArrayAdd(DATA,"\r\n");
   if (StringLen(caption) > 0){
      ArrayAdd(DATA,"--"+hash+"\r\n");
      ArrayAdd(DATA,"Content-Disposition: form-data; name=\"caption\"\r\n");
      ArrayAdd(DATA,"\r\n");
      ArrayAdd(DATA,caption);
      ArrayAdd(DATA,"\r\n");
   }
   ArrayAdd(DATA,"--"+hash+"\r\n");
   ArrayAdd(DATA,"Content-Disposition: form-data; name=\"photo\"; filename=\"Upload_Screenshot.jpg\"\r\n");
   ArrayAdd(DATA,"\r\n");
   ArrayAdd(DATA,photoArr_Data);
   ArrayAdd(DATA,"\r\n");
   ArrayAdd(DATA,"--"+hash+"--\r\n");
   HEADERS = "Content-Type: multipart/form-data; boundary="+hash+"\r\n";
   int res_WebReq = WebRequest(METHOD,URL,HEADERS,WEB_TIMEOUT,DATA,RESULT,RESULT_HEADERS);
   if (res_WebReq == 200){
      string result = CharArrayToString(RESULT,0,WHOLE_ARRAY,CP_UTF8);
      Print(result);
      Print("SUCCESS SENDING THE SCREENSHOT TO TELEGRAM");
   }
}

In the visual dispatch hub, "SendScreenshot()" opens a chart ("ChartOpen()", "symbol", "period") with grid and separators disabled ("ChartSetInteger()", "ChartRedraw()") and waits for synchronization ("SeriesInfoInteger()", "SERIES_SYNCHRONIZED"). It captures a 1366x768 screenshot ("ChartScreenShot()", "SCREENSHOT_FILE_NAME", "FileDelete()", "FileOpen()") and sends it to Telegram ("WebRequest()", "InpToken") with a caption ("caption") using base64 encoding ("CryptEncode(CRYPT_BASE64)") and an MD5 boundary ("hash"). For example, sending an EURUSD H1 screenshot with caption “Screenshot of symbol: EURUSD (H1) @ Time: 2025.06.26 10:20:00” is like dispatching a visual report.

Phase 5: Shutting Down the System—Cleaning Up Resources

As our expedition concludes, we shut down the system, ensuring resources are cleared.

void OnDeinit(const int reason){
   EventKillTimer();
}

In the shutdown control room, "OnDeinit()" stops the timer ("EventKillTimer()") but leaves screenshot files and arrays, like a partially dismantled command center. Adding cleanup would ensure a clean slate:

if (FileIsExist("My Screenshot.jpg")){
   FileDelete("My Screenshot.jpg");
}
m_chats.Clear();

This would delete the screenshot ("FileDelete()") and clear chats ("m_chats.Clear()", "CList") in "CBot_EA", like fully dismantling the system.

Why This EA is a Command Center Triumph

The Telegram Bot to MQL5 EA is a trading control triumph, enabling interactive trading with precision, like a master-crafted command center. Its robust JSON parsing ("CJSONValue", "Deserialize()") and command handling ("processMessages()") offer seamless Telegram integration, with potential for configurable risk or authentication. Picture executing a buy on EURUSD via Telegram—strategic brilliance! Beginners will value the intuitive commands, while experts can enhance its framework, making it essential for remote traders.

Putting It All Together

To deploy this EA:

  1. Add "https://api.telegram.org" to MetaTrader 5’s allowed URLs (Tools > Options > Expert Advisors).

  2. Verify the bot token ("InpToken") and obtain the chat ID (e.g., via /getUpdates).

  3. Open MetaEditor in MetaTrader 5, like entering your trading command center.

  4. Copy the code, compile with F5, and verify no errors—no commander wants a faulty system!

  5. Attach the EA to your chart and send Telegram commands (e.g., /buy, /screenshot) to interact.

  6. Monitor logs (e.g., “SUCCESS SENDING THE SCREENSHOT TO TELEGRAM”) for tracking, like command diagnostics.

  7. Test on a demo account first—real capital deserves a trial run!

Conclusion

We’ve engineered a Telegram Bot Trader that commands trading with precision, like a master-crafted control center. This MQL5 code is your strategic tool, brought to life with a seamless, professional narrative packed with clear explanations and vivid examples to fuel your trading ambition. Whether you’re a novice commander or a seasoned market strategist, this EA empowers you to manage trades remotely with confidence. Ready to command? Watch our video guide on the website for a step-by-step creation process. Now, lead your trading with precision! 🔍

Disclaimer: Trading is like navigating complex markets—challenging and risky. Losses can exceed deposits. Test strategies on a demo account before going live.

Disclaimer: The ideas and strategies presented in this resource are solely those of the author and are intended for informational and educational purposes only. They do not constitute financial advice, and past performance is not indicative of future results. All materials, including but not limited to text, images, files, and any downloadable content, are protected by copyright and intellectual property laws and are the exclusive property of Forex Algo-Trader or its licensors. Reproduction, distribution, modification, or commercial use of these materials without prior written consent from Forex Algo-Trader is strictly prohibited and may result in legal action. Users are advised to exercise extreme caution, perform thorough independent research, and consult with qualified financial professionals before implementing any trading strategies or decisions based on this resource, as trading in financial markets involves significant risk of loss.

Recent Comments

Go to discussion to Comment or View other Comments

No comments yet. Be the first to comment!