Нема описа

blTelegramToMT4.mq4 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. //+------------------------------------------------------------------+
  2. //| blTelegramToMT4.mq4 |
  3. //| Copyright 2025, MQL Development |
  4. //| https://www.mqldevelopment.com/ |
  5. //+------------------------------------------------------------------+
  6. #property copyright "Copyright 2025, MQL Development"
  7. #property link "https://www.mqldevelopment.com/"
  8. #property version "1.00"
  9. #property strict
  10. #define buy "buy"
  11. #define sell "sell"
  12. #define MaxOrders 10000
  13. struct msgDetails
  14. {
  15. int msgid;
  16. msgDetails()
  17. {
  18. msgid = -1;
  19. }
  20. };
  21. msgDetails od[MaxOrders];
  22. input string Settings = " ------------- General Settings ------------- "; //_
  23. input int magic_no = 333; // Magic no
  24. input string symbolMatch = "GOLD:XAUUSD,BitCoin:BTCUSD"; // Symbol Mapping (Telegram:MT5)
  25. input string suffix = ""; // Account Suffix
  26. input string prefix = ""; // Account Prefix
  27. input double lotSize = 0.1; // Lot Size
  28. //+------------------------------------------------------------------+
  29. //| Expert initialization function |
  30. //+------------------------------------------------------------------+
  31. // Global Variables
  32. string url1 = "http://127.0.0.1";
  33. string header = "Content-Type: application/json\r\nAccept: application/json\r\n";
  34. string symbolChart[];
  35. string symbolSnd[];
  36. string symbolsListUserInput[];
  37. uchar sym1[];
  38. uchar sym2[];
  39. int last_message_id = INT_MIN;
  40. int OnInit()
  41. {
  42. //--- create timer
  43. ushort u_sep = StringGetCharacter(",",0);
  44. StringSplit(symbolMatch,u_sep,symbolsListUserInput);
  45. ArrayResize(symbolChart,0);
  46. ArrayResize(symbolSnd,0);
  47. for(int i = 0; i < ArraySize(symbolsListUserInput); i++)
  48. {
  49. string str = symbolsListUserInput[i];
  50. int index = StringFind(str,":");
  51. int index2 = StringLen(str);
  52. ArrayResize(sym1,0);
  53. ArrayResize(sym2,0);
  54. for(int j = 0; j < index; j++)
  55. {
  56. ArrayResize(sym1,ArraySize(sym1)+1);
  57. sym1[j] = uchar(str[j]);
  58. }
  59. int k = 0;
  60. for(int j = index + 1 ; j < index2; j++)
  61. {
  62. ArrayResize(sym2,ArraySize(sym2)+1);
  63. sym2[k] = uchar(str[j]);
  64. k++;
  65. }
  66. ArrayResize(symbolChart,ArraySize(symbolChart)+1);
  67. ArrayResize(symbolSnd,ArraySize(symbolSnd)+1);
  68. symbolChart[i] = CharArrayToString(sym1);
  69. symbolSnd[i] = CharArrayToString(sym2);
  70. }
  71. string jsonString = GET_function(url1 + "/get-latest-message-id", header);
  72. StringReplace(jsonString,"},", "*");
  73. last_message_id = (int)getJsonStringValue(jsonString, "id") != 0 ? (int)getJsonStringValue(jsonString, "id") : INT_MIN;
  74. string message = getJsonStringValue(jsonString, "message");
  75. if(last_message_id != INT_MIN)
  76. {
  77. Print(" latest_message_id = ",last_message_id);
  78. Print(" result found against get-latest-message-id = ",message);
  79. }
  80. EventSetTimer(1);
  81. //---
  82. return(INIT_SUCCEEDED);
  83. }
  84. //+------------------------------------------------------------------+
  85. //| Expert deinitialization function |
  86. //+------------------------------------------------------------------+
  87. void OnDeinit(const int reason)
  88. {
  89. //--- destroy timer
  90. EventKillTimer();
  91. }
  92. //+------------------------------------------------------------------+
  93. //| Expert tick function |
  94. //+------------------------------------------------------------------+
  95. void OnTick()
  96. {
  97. //---
  98. }
  99. //+------------------------------------------------------------------+
  100. //| Timer function |
  101. //+------------------------------------------------------------------+
  102. void OnTimer()
  103. {
  104. //---
  105. if(last_message_id == INT_MIN)
  106. {
  107. string jsonString = GET_function(url1 + "/get-latest-message-id", header);
  108. StringReplace(jsonString,"},", "*");
  109. last_message_id = (int)getJsonStringValue(jsonString, "id") != 0 ? (int)getJsonStringValue(jsonString, "id") : INT_MIN;
  110. if(last_message_id != INT_MIN)
  111. {
  112. string message = getJsonStringValue(jsonString, "message");
  113. if(last_message_id != INT_MIN)
  114. {
  115. Print(" latest_message_id = ",last_message_id);
  116. Print(" result found against get-latest-message-id = ",message);
  117. }
  118. execute_functionality_on_new_message(last_message_id);
  119. }
  120. }
  121. else
  122. {
  123. string jsonString = GET_function(url1 + "/get-latest-message-id", header);
  124. StringReplace(jsonString,"},", "*");
  125. int latest_message_id = (int)getJsonStringValue(jsonString, "id") != 0 ? (int)getJsonStringValue(jsonString, "id") : INT_MIN;
  126. if(last_message_id != latest_message_id)
  127. {
  128. for(int i = latest_message_id; i > last_message_id; i--)
  129. {
  130. execute_functionality_on_new_message(i);
  131. }
  132. last_message_id = latest_message_id;
  133. }
  134. }
  135. }
  136. //+------------------------------------------------------------------+
  137. //| |
  138. //+------------------------------------------------------------------+
  139. string GET_function(string url,string headers)
  140. {
  141. string result_string = NULL;
  142. int timeout = 10; // Set the timeout value in seconds
  143. char result[],data[];
  144. string resultHeaders;
  145. int res = WebRequest("GET",url,headers,timeout,data,result,resultHeaders);
  146. if(res == 200)
  147. {
  148. result_string = CharArrayToString(result);
  149. }
  150. else
  151. {
  152. Print("content GETT: ", result_string," Error: ",GetLastError(), " res: ",res);
  153. }
  154. return result_string;
  155. }
  156. //+------------------------------------------------------------------+
  157. //| |
  158. //+------------------------------------------------------------------+
  159. bool checkExistingTrade(int message_id)
  160. {
  161. for(int i=0; i < MaxOrders; i++)
  162. {
  163. if(od[i].msgid == message_id)
  164. {
  165. return true;
  166. }
  167. }
  168. return false;
  169. }
  170. //+------------------------------------------------------------------+
  171. //| |
  172. //+------------------------------------------------------------------+
  173. string getJsonStringValue(string json,string key,int addUp,string endSign)
  174. {
  175. int indexStart = StringFind(json,key)+StringLen(key)+addUp;
  176. int indexEnd = StringFind(json,endSign,indexStart);
  177. return StringSubstr(json,indexStart,indexEnd-indexStart);
  178. }
  179. //+------------------------------------------------------------------+
  180. //| |
  181. //+------------------------------------------------------------------+
  182. string getJsonStringValue(string json, string key)
  183. {
  184. int start = StringFind(json, "\""+key+"\"");
  185. if(start == -1)
  186. return "";
  187. // Find colon after key
  188. int colon = StringFind(json, ":", start);
  189. if(colon == -1)
  190. return "";
  191. // Find next comma or closing brace
  192. int endComma = StringFind(json, ",", colon);
  193. int endBrace = StringFind(json, "}", colon);
  194. int end = (endComma != -1 && (endComma < endBrace || endBrace == -1)) ? endComma : endBrace;
  195. if(end == -1)
  196. end = StringLen(json);
  197. string value = trim(StringSubstr(json, colon+1, end-colon-1));
  198. // remove quotes if exist
  199. StringReplace(value, "\"", "");
  200. return value;
  201. }
  202. //+------------------------------------------------------------------+
  203. //| |
  204. //+------------------------------------------------------------------+
  205. string trim(string text)
  206. {
  207. StringTrimLeft(text);
  208. StringTrimRight(text);
  209. return text;
  210. }
  211. //+------------------------------------------------------------------+
  212. //| |
  213. //+------------------------------------------------------------------+
  214. void execute_functionality_on_new_message(int i)
  215. {
  216. string url = url1 + "/get-message/" + IntegerToString(i);
  217. string jsonString = GET_function(url, header);
  218. StringReplace(jsonString,"},", "*");
  219. string message = getJsonStringValue(jsonString,"message",4,"\"");
  220. int group_message_id = (int)getJsonStringValue(jsonString, "message_id");
  221. StringToLower(message);
  222. StringReplace(message,"~","#");
  223. if(checkExistingTrade(group_message_id) == false)
  224. {
  225. string isReplyValue = getJsonStringValue(jsonString, "is_reply");
  226. if(isReplyValue == "True")
  227. {
  228. int reply_to_msg_id = (int)getJsonStringValue(jsonString, "reply_to_msg_id");
  229. message = getJsonStringValue(jsonString, "message");
  230. StringToLower(message);
  231. Print(" ================ Replied Message found of message_id ================ ",reply_to_msg_id);
  232. Print(" ================ Message: ================ ",message);
  233. }
  234. else
  235. {
  236. if(checkExistingTrade(group_message_id) == false)
  237. {
  238. Print(" --------------- New Trade Message Found ----------------- ", " Message Id: ", group_message_id);
  239. StringReplace(message,"~","#");
  240. StringReplace(message,"##", "#");
  241. StringToLower(message);
  242. message = removeExtraSpaces(message);
  243. Print("Message is ",message);
  244. string result[];
  245. string tempResult[];
  246. int indexTemp = 0;
  247. StringSplit(message,'#',tempResult);
  248. for(int j=0; j<ArraySize(tempResult); j++)
  249. {
  250. //result[i] = StringTrimLeft(result[i]);
  251. //result[i] = StringTrimRight(result[i]);
  252. //Print("Temp Result : ", tempResult[i], " index is: ", i);
  253. if(HasAlphanumeric(tempResult[j]))
  254. {
  255. //Print(" contains alphanumeric characters.");
  256. ArrayResize(result,ArraySize(result)+1);
  257. result[indexTemp] = tempResult[j];
  258. indexTemp++;
  259. }
  260. else
  261. {
  262. //Print(" does not contain alphanumeric characters.");
  263. //ArrayResize(indexToDelete,ArraySize(indexToDelete)+1);
  264. //indexToDelete[indexTemp] = i;
  265. //indexTemp++;
  266. }
  267. }
  268. addtoMessageStructure(group_message_id,message);
  269. message(result,message,group_message_id);
  270. }
  271. }
  272. }
  273. }
  274. //+------------------------------------------------------------------+
  275. //| |
  276. //+------------------------------------------------------------------+
  277. void message(string &result[], string message, int message_id)
  278. {
  279. string lineOne[]; // = result[0];
  280. int lineIndex = 0;
  281. string direction = "";
  282. int direction_index = -1;
  283. string symbol = "";
  284. if(ArraySize(result) >= 1)
  285. {
  286. StringSplit(result[0], ' ', lineOne);
  287. if(((StringFind(result[0], "buy", 0) != -1) || (StringFind(result[0], "sell", 0) != -1)))
  288. {
  289. for(int i=0; i<ArraySize(lineOne); i++)
  290. {
  291. if(HasAlphanumeric(lineOne[i]))
  292. {
  293. ArrayResize(lineOne,ArraySize(lineOne)+1);
  294. lineOne[lineIndex] = lineOne[i];
  295. Print("Direction and Symbol: ", lineOne[lineIndex], " index is: ", lineIndex);
  296. if(lineOne[lineIndex] == buy || lineOne[lineIndex] == sell)
  297. {
  298. direction = lineOne[lineIndex];
  299. direction_index = lineIndex;
  300. //Print(" Direction is: ", direction, " Direction Index: ", direction_index);
  301. }
  302. lineIndex++;
  303. }
  304. }
  305. if(ArraySize(lineOne) >= 2)
  306. {
  307. if(direction_index == 0)
  308. {
  309. symbol = lineOne[1];
  310. StringToUpper(symbol);
  311. //Print(" This is Message format One (1). Where Direction is: ", direction, " Symbol: ", symbol);
  312. }
  313. else
  314. if(direction_index > 0)
  315. {
  316. symbol = lineOne[0];
  317. StringToUpper(symbol);
  318. //Print(" This is Message format One (1). Where Direction is: ", direction, " Symbol: ", symbol);
  319. }
  320. }
  321. symbol = symbolMapping(symbol);
  322. double sl = 0;
  323. double tp = 0; // = result[0];
  324. for(int i=0 ; i < ArraySize(result); i++)
  325. {
  326. // result[i] = StringTrimLeft(result[i]);
  327. // result[i] = StringTrimRight(result[i]);
  328. // Print("Result : ", result[i], " index is: ", i);
  329. if((StringFind(result[i], "sl", 0) != -1))
  330. {
  331. string tempSl[];
  332. result[i] = trimString(result[i]);
  333. //Print(" Sl String: ", result[i]);
  334. StringSplit(result[i], ':', tempSl);
  335. if(ArraySize(tempSl) >= 2)
  336. sl = (double) tempSl[1];
  337. Print("Sl : ", sl);
  338. }
  339. if((StringFind(result[i], "tp", 0) != -1))
  340. {
  341. // Print("Tp : ", result[i], " index is: ", i);
  342. string tempTp[];
  343. result[i] = trimString(result[i]);
  344. StringSplit(result[i], ':', tempTp);
  345. //double tp = (double) tempTp[1];
  346. if(ArraySize(tempTp) >= 2)
  347. tp = (double) tempTp[1];
  348. Print("Tp : ", tp);
  349. }
  350. }
  351. Print("Side:", direction, " Symbol: ", symbol, " Tp: ", tp, " Sl: ", sl, " Message Id: ", message_id);
  352. if(direction == buy)
  353. {
  354. placeBuyTrade(symbol, tp, sl, message_id, lotSize);
  355. }
  356. if(direction == sell)
  357. {
  358. placeSellTrade(symbol, tp, sl, message_id, lotSize);
  359. }
  360. }
  361. }
  362. }
  363. //+------------------------------------------------------------------+
  364. //| |
  365. //+------------------------------------------------------------------+
  366. void placeBuyTrade(string symbol,double tp,double sl, int messageId, double lot_size)
  367. {
  368. double ask = SymbolInfoDouble(symbol,SYMBOL_ASK);
  369. double bid = SymbolInfoDouble(symbol,SYMBOL_BID);
  370. double buySl = sl;
  371. double buyTp = tp;
  372. int ticket = OrderSend(symbol, OP_BUY, lot_size, ask, 3, buySl, buyTp, "Buy Trade Placed.", magic_no, 0, clrBlue);
  373. Print("Buy order Print: Stop Loss: ", buySl, " Take profit: ", buyTp);
  374. if(ticket < 0)
  375. {
  376. Print("Buy Order Failed ", GetLastError());
  377. }
  378. else
  379. {
  380. Print(" Buy Order Is Placed Sucessfully ");
  381. }
  382. }
  383. //+------------------------------------------------------------------+
  384. //| |
  385. //+------------------------------------------------------------------+
  386. void placeSellTrade(string symbol,double tp,double sl, int messageId, double lot_size)
  387. {
  388. double ask = SymbolInfoDouble(symbol,SYMBOL_ASK);
  389. double bid = SymbolInfoDouble(symbol,SYMBOL_BID);
  390. double sellSl = sl;
  391. double sellTp = tp;
  392. int ticket = OrderSend(symbol, OP_SELL, lot_size, bid, 3, sellSl, sellTp, "Sell Trade Placed.", magic_no, 0, clrRed);
  393. if(ticket < 0)
  394. {
  395. Print("Sell Order Failed ", GetLastError());
  396. }
  397. else
  398. {
  399. Print(" Sell Order Is Placed Sucessfully ");
  400. }
  401. }
  402. //+------------------------------------------------------------------+
  403. //| |
  404. //+------------------------------------------------------------------+
  405. void addtoMessageStructure(int message_id,string message)
  406. {
  407. for(int i=0; i < MaxOrders; i++)
  408. {
  409. if(od[i].msgid == -1)
  410. {
  411. od[i].msgid = message_id;
  412. StringToLower(message);
  413. Print(" Message ID ",message_id," of Message = ",message," is added To Structure :: ");
  414. break;
  415. }
  416. }
  417. }
  418. //+------------------------------------------------------------------+
  419. //| |
  420. //+------------------------------------------------------------------+
  421. string trimString(string inputt)
  422. {
  423. // Remove spaces from the left and right sides
  424. int start = 0;
  425. int end = StringLen(inputt) - 1;
  426. // Find the first non-space character
  427. while(start <= end && StringGetCharacter(inputt, start) == ' ')
  428. start++;
  429. // Find the last non-space character
  430. while(end >= start && StringGetCharacter(inputt, end) == ' ')
  431. end--;
  432. // Extract the substring without leading or trailing spaces
  433. return StringSubstr(inputt, start, end - start + 1);
  434. }
  435. //+------------------------------------------------------------------+
  436. //| |
  437. //+------------------------------------------------------------------+
  438. string removeExtraSpaces(string str)
  439. {
  440. string result = "";
  441. int len = StringLen(str);
  442. bool lastWasSpace = false;
  443. for(int i = 0; i < len; i++)
  444. {
  445. string currentChar = StringSubstr(str, i, 1);
  446. if(currentChar == " ")
  447. {
  448. // Skip adding this space if the last character was also a space
  449. if(lastWasSpace)
  450. continue;
  451. lastWasSpace = true;
  452. }
  453. else
  454. {
  455. lastWasSpace = false;
  456. }
  457. result += currentChar;
  458. }
  459. return result;
  460. }
  461. //+------------------------------------------------------------------+
  462. //| |
  463. //+------------------------------------------------------------------+
  464. bool HasAlphanumeric(string str)
  465. {
  466. //Print("String Length: ", StringLen(str));
  467. for(int i = 0; i <= StringLen(str); i++)
  468. {
  469. //Print("Here ", StringLen(str));
  470. if(IsAlphanumeric((char)str[i]))
  471. {
  472. return true;
  473. break;
  474. }
  475. }
  476. return false;
  477. }
  478. //+------------------------------------------------------------------+
  479. //| |
  480. //+------------------------------------------------------------------+
  481. bool IsAlphanumeric(char c)
  482. {
  483. if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
  484. return true;
  485. return false;
  486. }
  487. //+------------------------------------------------------------------+
  488. //| |
  489. //+------------------------------------------------------------------+
  490. string symbolMapping(string symbol)
  491. {
  492. for(int k = 0; k < ArraySize(symbolChart); k++)
  493. {
  494. StringToUpper(symbolChart[k]);
  495. if(symbol == symbolChart[k])
  496. {
  497. symbol = symbolSnd[k];
  498. }
  499. }
  500. symbol = prefix + symbol + suffix;
  501. return symbol;
  502. }
  503. //+------------------------------------------------------------------+
  504. //| |
  505. //+------------------------------------------------------------------+
  506. //+------------------------------------------------------------------+
  507. //+------------------------------------------------------------------+