| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740 |
- //+------------------------------------------------------------------+
- //| blTelegramToMT4.mq4 |
- //| Copyright 2025, MQL Development |
- //| https://www.mqldevelopment.com/ |
- //+------------------------------------------------------------------+
- #property copyright "Copyright 2025, MQL Development"
- #property link "https://www.mqldevelopment.com/"
- #property version "1.1"
- #property strict
- #define buy "buy"
- #define sell "sell"
- #define MaxOrders 10000
- struct msgDetails
- {
- int msgid;
- ulong tickt;
- msgDetails()
- {
- msgid = -1;
- tickt = -1;
- }
- };
- msgDetails od[MaxOrders];
- input string Settings = " ------------- General Settings ------------- "; //_
- input int magic_no = 333; // Magic no
- input string symbolMatch = "GOLD:XAUUSD,BitCoin:BTCUSD"; // Symbol Mapping (Telegram:MT4)
- input string suffix = ""; // Account Suffix
- input string prefix = ""; // Account Prefix
- input double lotSize = 0.1; // Lot Size
- input double partialClose = 20; // Partial Closing %
- //+------------------------------------------------------------------+
- //| Expert initialization function |
- //+------------------------------------------------------------------+
- // Global Variables
- string url1 = "http://127.0.0.1"; // "http://myapp.local";
- string header = "Content-Type: application/json\r\nAccept: application/json\r\n";
- string symbolChart[];
- string symbolSnd[];
- string symbolsListUserInput[];
- uchar sym1[];
- uchar sym2[];
- int last_message_id = INT_MIN;
- int OnInit()
- {
- //--- create timer
- ushort u_sep = StringGetCharacter(",",0);
- StringSplit(symbolMatch,u_sep,symbolsListUserInput);
- ArrayResize(symbolChart,0);
- ArrayResize(symbolSnd,0);
- for(int i = 0; i < ArraySize(symbolsListUserInput); i++)
- {
- string str = symbolsListUserInput[i];
- int index = StringFind(str,":");
- int index2 = StringLen(str);
- ArrayResize(sym1,0);
- ArrayResize(sym2,0);
- for(int j = 0; j < index; j++)
- {
- ArrayResize(sym1,ArraySize(sym1)+1);
- sym1[j] = uchar(str[j]);
- }
- int k = 0;
- for(int j = index + 1 ; j < index2; j++)
- {
- ArrayResize(sym2,ArraySize(sym2)+1);
- sym2[k] = uchar(str[j]);
- k++;
- }
- ArrayResize(symbolChart,ArraySize(symbolChart)+1);
- ArrayResize(symbolSnd,ArraySize(symbolSnd)+1);
- symbolChart[i] = CharArrayToString(sym1);
- symbolSnd[i] = CharArrayToString(sym2);
- }
- string jsonString = GET_function(url1 + "/get-latest-message-id", header);
- StringReplace(jsonString,"},", "*");
- last_message_id = (int)getJsonStringValue(jsonString, "id") != 0 ? (int)getJsonStringValue(jsonString, "id") : INT_MIN;
- string message = getJsonStringValue(jsonString, "message");
- if(last_message_id != INT_MIN)
- {
- Print(" latest_message_id = ",last_message_id);
- Print(" result found against get-latest-message-id = ",message);
- }
- EventSetTimer(1);
- //---
- return(INIT_SUCCEEDED);
- }
- //+------------------------------------------------------------------+
- //| Expert deinitialization function |
- //+------------------------------------------------------------------+
- void OnDeinit(const int reason)
- {
- //--- destroy timer
- EventKillTimer();
- }
- //+------------------------------------------------------------------+
- //| Expert tick function |
- //+------------------------------------------------------------------+
- void OnTick()
- {
- //---
- }
- //+------------------------------------------------------------------+
- //| Timer function |
- //+------------------------------------------------------------------+
- void OnTimer()
- {
- //---
- if(last_message_id == INT_MIN)
- {
- string jsonString = GET_function(url1 + "/get-latest-message-id", header);
- StringReplace(jsonString,"},", "*");
- last_message_id = (int)getJsonStringValue(jsonString, "id") != 0 ? (int)getJsonStringValue(jsonString, "id") : INT_MIN;
- if(last_message_id != INT_MIN)
- {
- string message = getJsonStringValue(jsonString, "message");
- if(last_message_id != INT_MIN)
- {
- Print(" latest_message_id = ",last_message_id);
- Print(" result found against get-latest-message-id = ",message);
- }
- execute_functionality_on_new_message(last_message_id);
- }
- }
- else
- {
- string jsonString = GET_function(url1 + "/get-latest-message-id", header);
- StringReplace(jsonString,"},", "*");
- int latest_message_id = (int)getJsonStringValue(jsonString, "id") != 0 ? (int)getJsonStringValue(jsonString, "id") : INT_MIN;
- if(last_message_id != latest_message_id)
- {
- for(int i = latest_message_id; i > last_message_id; i--)
- {
- execute_functionality_on_new_message(i);
- }
- last_message_id = latest_message_id;
- }
- }
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- string GET_function(string url,string headers)
- {
- string result_string = NULL;
- int timeout = 10; // Set the timeout value in seconds
- char result[],data[];
- string resultHeaders;
- int res = WebRequest("GET",url,headers,timeout,data,result,resultHeaders);
- if(res == 200)
- {
- result_string = CharArrayToString(result);
- }
- else
- {
- Print("content GETT: ", result_string," Error: ",GetLastError(), " res: ",res);
- }
- return result_string;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- bool checkExistingTrade(int message_id)
- {
- for(int i=0; i < MaxOrders; i++)
- {
- if(od[i].msgid == message_id)
- {
- return true;
- }
- }
- return false;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- string getJsonStringValue(string json,string key,int addUp,string endSign)
- {
- int indexStart = StringFind(json,key)+StringLen(key)+addUp;
- int indexEnd = StringFind(json,endSign,indexStart);
- return StringSubstr(json,indexStart,indexEnd-indexStart);
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- string getJsonStringValue(string json, string key)
- {
- int start = StringFind(json, "\""+key+"\"");
- if(start == -1)
- return "";
- // Find colon after key
- int colon = StringFind(json, ":", start);
- if(colon == -1)
- return "";
- // Find next comma or closing brace
- int endComma = StringFind(json, ",", colon);
- int endBrace = StringFind(json, "}", colon);
- int end = (endComma != -1 && (endComma < endBrace || endBrace == -1)) ? endComma : endBrace;
- if(end == -1)
- end = StringLen(json);
- string value = trim(StringSubstr(json, colon+1, end-colon-1));
- // remove quotes if exist
- StringReplace(value, "\"", "");
- return value;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- string trim(string text)
- {
- StringTrimLeft(text);
- StringTrimRight(text);
- return text;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- void execute_functionality_on_new_message(int i)
- {
- string url = url1 + "/get-message/" + IntegerToString(i);
- string jsonString = GET_function(url, header);
- StringReplace(jsonString,"},", "*");
- string message = getJsonStringValue(jsonString,"message",4,"\"");
- int group_message_id = (int)getJsonStringValue(jsonString, "message_id");
- StringToLower(message);
- StringReplace(message,"~","#");
- if(checkExistingTrade(group_message_id) == false)
- {
- string isReplyValue = getJsonStringValue(jsonString, "is_reply");
- StringReplace(isReplyValue," ","");
- if(isReplyValue == "True")
- {
- int reply_to_msg_id = (int)getJsonStringValue(jsonString, "reply_to_msg_id");
- message = getJsonStringValue(jsonString, "message");
- StringToLower(message);
- Print(" ================ Replied Message found of message_id ================ ",reply_to_msg_id);
- Print(" ================ Message: ================ ",message);
- int ticket = getTicket(reply_to_msg_id);
- if(ticket != -1)
- {
- if(StringFind(message,"set") != -1 && StringFind(message,"stop") != -1 && StringFind(message,"loss") != -1 && StringFind(message,"entry") != -1)
- {
- if(OrderSelect(ticket,SELECT_BY_TICKET))
- {
- bool result = OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice(),OrderTakeProfit(),0,clrNONE);
- if(result)
- {
- Print("Order Sl Modify to Open Price ", ticket);
- }
- else
- {
- Print("Error in Modify order SL : ", GetLastError()," Setting SL at: ",OrderOpenPrice()," price: ",OrderClosePrice());
- }
- }
- }
- if(StringFind(message,"take") != -1 && StringFind(message,"some") != -1 && StringFind(message,"partial") != -1 && StringFind(message,"profit") != -1)
- {
- if(OrderSelect(ticket,SELECT_BY_TICKET))
- {
- double lot = NormalizeDouble(OrderLots()*(partialClose/100),2);
- bool result = OrderClose(ticket,lot,OrderClosePrice(),10, clrNONE);
- if(result)
- {
- Print("Partially closed ", lot, " lots from order ", ticket);
- for(int j = OrdersTotal()-1; j>=0; j--)
- {
- if(OrderSelect(j, SELECT_BY_POS))
- {
- if(OrderComment() != "")
- {
- string ticketToBeReplace = OrderComment();
- StringReplace(ticketToBeReplace,"from #","");
- if(int(ticketToBeReplace) == ticket)
- {
- findAndreplaceTicketFromStructure(OrderTicket(),reply_to_msg_id);
- }
- }
- }
- }
- }
- else
- {
- Print("Error closing partial order: ", GetLastError()," lot = ",lot," OrderLots() = ",OrderLots());
- }
- }
- }
- }
- }
- else
- {
- if(checkExistingTrade(group_message_id) == false)
- {
- Print(" --------------- New Trade Message Found ----------------- ", " Message Id: ", group_message_id);
- StringReplace(message,"~","#");
- StringReplace(message,"##", "#");
- StringToLower(message);
- message = removeExtraSpaces(message);
- Print("Message is ",message);
- string result[];
- string tempResult[];
- int indexTemp = 0;
- StringSplit(message,'#',tempResult);
- for(int j=0; j<ArraySize(tempResult); j++)
- {
- //result[i] = StringTrimLeft(result[i]);
- //result[i] = StringTrimRight(result[i]);
- //Print("Temp Result : ", tempResult[i], " index is: ", i);
- if(HasAlphanumeric(tempResult[j]))
- {
- //Print(" contains alphanumeric characters.");
- ArrayResize(result,ArraySize(result)+1);
- result[indexTemp] = tempResult[j];
- indexTemp++;
- }
- else
- {
- //Print(" does not contain alphanumeric characters.");
- //ArrayResize(indexToDelete,ArraySize(indexToDelete)+1);
- //indexToDelete[indexTemp] = i;
- //indexTemp++;
- }
- }
- int ticket = -1;
- message(result,message,group_message_id,ticket);
- addtoMessageStructure(group_message_id,message,ticket);
- }
- }
- }
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- void findAndreplaceTicketFromStructure(int ticketToBeReplace,int reply_to_msg_id)
- {
- for(int i=0; i < MaxOrders; i++)
- {
- if(od[i].msgid == reply_to_msg_id)
- {
- od[i].tickt = ticketToBeReplace;
- Print("codeOrder is partially closed so update Ticket ",ticketToBeReplace);
- break;
- }
- }
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- int getTicket(int reply_to_msg_id)
- {
- for(int i=0; i < MaxOrders; i++)
- {
- if(od[i].msgid == reply_to_msg_id)
- {
- return int(od[i].tickt);
- }
- }
- return -1;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- void message(string &result[], string message, int message_id,int & tickt)
- {
- string lineOne[]; // = result[0];
- int lineIndex = 0;
- string direction = "";
- int direction_index = -1;
- string symbol = "";
- if(ArraySize(result) >= 1)
- {
- StringSplit(result[0], ' ', lineOne);
- if(((StringFind(result[0], "buy", 0) != -1) || (StringFind(result[0], "sell", 0) != -1)))
- {
- for(int i=0; i<ArraySize(lineOne); i++)
- {
- if(HasAlphanumeric(lineOne[i]))
- {
- ArrayResize(lineOne,ArraySize(lineOne)+1);
- lineOne[lineIndex] = lineOne[i];
- Print("Direction and Symbol: ", lineOne[lineIndex], " index is: ", lineIndex);
- if(lineOne[lineIndex] == buy || lineOne[lineIndex] == sell)
- {
- direction = lineOne[lineIndex];
- direction_index = lineIndex;
- //Print(" Direction is: ", direction, " Direction Index: ", direction_index);
- }
- lineIndex++;
- }
- }
- if(ArraySize(lineOne) >= 2)
- {
- if(direction_index == 0)
- {
- symbol = lineOne[1];
- StringToUpper(symbol);
- //Print(" This is Message format One (1). Where Direction is: ", direction, " Symbol: ", symbol);
- }
- else
- if(direction_index > 0)
- {
- symbol = lineOne[0];
- StringToUpper(symbol);
- //Print(" This is Message format One (1). Where Direction is: ", direction, " Symbol: ", symbol);
- }
- }
- symbol = symbolMapping(symbol);
- double sl = 0;
- double tp = 0; // = result[0];
- for(int i=0 ; i < ArraySize(result); i++)
- {
- // result[i] = StringTrimLeft(result[i]);
- // result[i] = StringTrimRight(result[i]);
- // Print("Result : ", result[i], " index is: ", i);
- if((StringFind(result[i], "sl", 0) != -1))
- {
- string tempSl[];
- StringReplace(result[i],":", " ");
- result[i] = trimString(result[i]);
- result[i] = spaceRemove(result[i]);
- //Print(" Sl String: ", result[i]);
- StringSplit(result[i], ' ', tempSl);
- if(ArraySize(tempSl) >= 2)
- sl = (double) tempSl[1];
- Print("Sl : ", sl);
- }
- if((StringFind(result[i], "tp", 0) != -1))
- {
- Print("Tp : ", result[i], " index is: ", i);
- string tempTp[];
- StringReplace(result[i],":", " ");
- result[i] = trimString(result[i]);
- result[i] = spaceRemove(result[i]);
- Print("Tp After String Replace : ", result[i], " index is: ", i);
- StringSplit(result[i], ' ', tempTp);
- //double tp = (double) tempTp[1];
- for(int j=0 ; j < ArraySize(tempTp); j++)
- {
- Print(" Data is: ", tempTp[j]);
- }
- if(ArraySize(tempTp) >= 2)
- tp = (double) tempTp[1];
- Print("Tp : ", tp);
- }
- }
- Print("Side:", direction, " Symbol: ", symbol, " Tp: ", tp, " Sl: ", sl, " Message Id: ", message_id);
- if(direction == buy)
- {
- tickt = placeBuyTrade(symbol, tp, sl, message_id, lotSize);
- }
- if(direction == sell)
- {
- tickt = placeSellTrade(symbol, tp, sl, message_id, lotSize);
- }
- }
- }
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- int placeBuyTrade(string symbol,double tp,double sl, int messageId, double lot_size)
- {
- double ask = SymbolInfoDouble(symbol,SYMBOL_ASK);
- double bid = SymbolInfoDouble(symbol,SYMBOL_BID);
- double buySl = sl;
- double buyTp = tp;
- int ticket = OrderSend(symbol, OP_BUY, lot_size, ask, 3, buySl, buyTp, "Buy Trade Placed.", magic_no, 0, clrBlue);
- Print("Buy order Print: Stop Loss: ", buySl, " Take profit: ", buyTp);
- if(ticket < 0)
- {
- Print("Buy Order Failed ", GetLastError());
- }
- else
- {
- Print(" Buy Order Is Placed Sucessfully ");
- }
- return ticket;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- int placeSellTrade(string symbol,double tp,double sl, int messageId, double lot_size)
- {
- double ask = SymbolInfoDouble(symbol,SYMBOL_ASK);
- double bid = SymbolInfoDouble(symbol,SYMBOL_BID);
- double sellSl = sl;
- double sellTp = tp;
- int ticket = OrderSend(symbol, OP_SELL, lot_size, bid, 3, sellSl, sellTp, "Sell Trade Placed.", magic_no, 0, clrRed);
- if(ticket < 0)
- {
- Print("Sell Order Failed ", GetLastError());
- }
- else
- {
- Print(" Sell Order Is Placed Sucessfully ");
- }
- return ticket;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- void addtoMessageStructure(int message_id,string message,ulong ticket)
- {
- for(int i=0; i < MaxOrders; i++)
- {
- if(od[i].msgid == -1)
- {
- od[i].msgid = message_id;
- od[i].tickt = ticket;
- StringToLower(message);
- Print(" Message ID ",message_id," of Message = ",message," Having Ticket ",ticket," is added To Structure :: ");
- break;
- }
- }
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- string trimString(string inputt)
- {
- // Remove spaces from the left and right sides
- int startt = 0;
- int end = StringLen(inputt) - 1;
- // Find the first non-space character
- while(startt <= end && StringGetCharacter(inputt, startt) == ' ')
- startt++;
- // Find the last non-space character
- while(end >= startt && StringGetCharacter(inputt, end) == ' ')
- end--;
- // Extract the substring without leading or trailing spaces
- return StringSubstr(inputt, startt, end - startt + 1);
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- string spaceRemove(string inputt)
- {
- int len = StringLen(inputt);
- string out = "";
- bool inSpace = false;
- for(int i = 0; i < len; i++)
- {
- ushort ch = StringGetCharacter(inputt, i);
- // treat space, tab, CR, LF as whitespace
- bool isSpace = (ch == 32 || ch == 9 || ch == 10 || ch == 13);
- if(isSpace)
- {
- // mark that we are inside a whitespace run, but don't append yet
- inSpace = true;
- continue;
- }
- // when we hit a non-space after whitespace, add a single space (if out not empty)
- if(inSpace && StringLen(out) > 0)
- out += " ";
- // append the non-space character (use substr to preserve unicode chars)
- out += StringSubstr(inputt, i, 1);
- inSpace = false;
- }
- return(out);
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- string removeExtraSpaces(string str)
- {
- string result = "";
- int len = StringLen(str);
- bool lastWasSpace = false;
- for(int i = 0; i < len; i++)
- {
- string currentChar = StringSubstr(str, i, 1);
- if(currentChar == " ")
- {
- // Skip adding this space if the last character was also a space
- if(lastWasSpace)
- continue;
- lastWasSpace = true;
- }
- else
- {
- lastWasSpace = false;
- }
- result += currentChar;
- }
- return result;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- bool HasAlphanumeric(string str)
- {
- //Print("String Length: ", StringLen(str));
- for(int i = 0; i <= StringLen(str); i++)
- {
- //Print("Here ", StringLen(str));
- if(IsAlphanumeric((char)str[i]))
- {
- return true;
- break;
- }
- }
- return false;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- bool IsAlphanumeric(char c)
- {
- if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
- return true;
- return false;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- string symbolMapping(string symbol)
- {
- for(int k = 0; k < ArraySize(symbolChart); k++)
- {
- StringToUpper(symbolChart[k]);
- if(symbol == symbolChart[k])
- {
- symbol = symbolSnd[k];
- }
- }
- symbol = prefix + symbol + suffix;
- return symbol;
- }
- //+------------------------------------------------------------------+
- //| |
- //+------------------------------------------------------------------+
- //+------------------------------------------------------------------+
- //+------------------------------------------------------------------+
|