暫無描述

blTelegramToMT4.mq4 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  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.1"
  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:MT4)
  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"; // "http://myapp.local";
  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. StringReplace(result[i],":", " ");
  333. result[i] = trimString(result[i]);
  334. result[i] = spaceRemove(result[i]);
  335. //Print(" Sl String: ", result[i]);
  336. StringSplit(result[i], ' ', tempSl);
  337. if(ArraySize(tempSl) >= 2)
  338. sl = (double) tempSl[1];
  339. Print("Sl : ", sl);
  340. }
  341. if((StringFind(result[i], "tp", 0) != -1))
  342. {
  343. Print("Tp : ", result[i], " index is: ", i);
  344. string tempTp[];
  345. StringReplace(result[i],":", " ");
  346. result[i] = trimString(result[i]);
  347. result[i] = spaceRemove(result[i]);
  348. Print("Tp After String Replace : ", result[i], " index is: ", i);
  349. StringSplit(result[i], ' ', tempTp);
  350. //double tp = (double) tempTp[1];
  351. for(int j=0 ; j < ArraySize(tempTp); j++)
  352. {
  353. Print(" Data is: ", tempTp[j]);
  354. }
  355. if(ArraySize(tempTp) >= 2)
  356. tp = (double) tempTp[1];
  357. Print("Tp : ", tp);
  358. }
  359. }
  360. Print("Side:", direction, " Symbol: ", symbol, " Tp: ", tp, " Sl: ", sl, " Message Id: ", message_id);
  361. if(direction == buy)
  362. {
  363. placeBuyTrade(symbol, tp, sl, message_id, lotSize);
  364. }
  365. if(direction == sell)
  366. {
  367. placeSellTrade(symbol, tp, sl, message_id, lotSize);
  368. }
  369. }
  370. }
  371. }
  372. //+------------------------------------------------------------------+
  373. //| |
  374. //+------------------------------------------------------------------+
  375. void placeBuyTrade(string symbol,double tp,double sl, int messageId, double lot_size)
  376. {
  377. double ask = SymbolInfoDouble(symbol,SYMBOL_ASK);
  378. double bid = SymbolInfoDouble(symbol,SYMBOL_BID);
  379. double buySl = sl;
  380. double buyTp = tp;
  381. int ticket = OrderSend(symbol, OP_BUY, lot_size, ask, 3, buySl, buyTp, "Buy Trade Placed.", magic_no, 0, clrBlue);
  382. Print("Buy order Print: Stop Loss: ", buySl, " Take profit: ", buyTp);
  383. if(ticket < 0)
  384. {
  385. Print("Buy Order Failed ", GetLastError());
  386. }
  387. else
  388. {
  389. Print(" Buy Order Is Placed Sucessfully ");
  390. }
  391. }
  392. //+------------------------------------------------------------------+
  393. //| |
  394. //+------------------------------------------------------------------+
  395. void placeSellTrade(string symbol,double tp,double sl, int messageId, double lot_size)
  396. {
  397. double ask = SymbolInfoDouble(symbol,SYMBOL_ASK);
  398. double bid = SymbolInfoDouble(symbol,SYMBOL_BID);
  399. double sellSl = sl;
  400. double sellTp = tp;
  401. int ticket = OrderSend(symbol, OP_SELL, lot_size, bid, 3, sellSl, sellTp, "Sell Trade Placed.", magic_no, 0, clrRed);
  402. if(ticket < 0)
  403. {
  404. Print("Sell Order Failed ", GetLastError());
  405. }
  406. else
  407. {
  408. Print(" Sell Order Is Placed Sucessfully ");
  409. }
  410. }
  411. //+------------------------------------------------------------------+
  412. //| |
  413. //+------------------------------------------------------------------+
  414. void addtoMessageStructure(int message_id,string message)
  415. {
  416. for(int i=0; i < MaxOrders; i++)
  417. {
  418. if(od[i].msgid == -1)
  419. {
  420. od[i].msgid = message_id;
  421. StringToLower(message);
  422. Print(" Message ID ",message_id," of Message = ",message," is added To Structure :: ");
  423. break;
  424. }
  425. }
  426. }
  427. //+------------------------------------------------------------------+
  428. //| |
  429. //+------------------------------------------------------------------+
  430. string trimString(string inputt)
  431. {
  432. // Remove spaces from the left and right sides
  433. int startt = 0;
  434. int end = StringLen(inputt) - 1;
  435. // Find the first non-space character
  436. while(startt <= end && StringGetCharacter(inputt, startt) == ' ')
  437. startt++;
  438. // Find the last non-space character
  439. while(end >= startt && StringGetCharacter(inputt, end) == ' ')
  440. end--;
  441. // Extract the substring without leading or trailing spaces
  442. return StringSubstr(inputt, startt, end - startt + 1);
  443. }
  444. //+------------------------------------------------------------------+
  445. //| |
  446. //+------------------------------------------------------------------+
  447. string spaceRemove(string inputt)
  448. {
  449. int len = StringLen(inputt);
  450. string out = "";
  451. bool inSpace = false;
  452. for(int i = 0; i < len; i++)
  453. {
  454. ushort ch = StringGetCharacter(inputt, i);
  455. // treat space, tab, CR, LF as whitespace
  456. bool isSpace = (ch == 32 || ch == 9 || ch == 10 || ch == 13);
  457. if(isSpace)
  458. {
  459. // mark that we are inside a whitespace run, but don't append yet
  460. inSpace = true;
  461. continue;
  462. }
  463. // when we hit a non-space after whitespace, add a single space (if out not empty)
  464. if(inSpace && StringLen(out) > 0)
  465. out += " ";
  466. // append the non-space character (use substr to preserve unicode chars)
  467. out += StringSubstr(inputt, i, 1);
  468. inSpace = false;
  469. }
  470. return(out);
  471. }
  472. //+------------------------------------------------------------------+
  473. //| |
  474. //+------------------------------------------------------------------+
  475. string removeExtraSpaces(string str)
  476. {
  477. string result = "";
  478. int len = StringLen(str);
  479. bool lastWasSpace = false;
  480. for(int i = 0; i < len; i++)
  481. {
  482. string currentChar = StringSubstr(str, i, 1);
  483. if(currentChar == " ")
  484. {
  485. // Skip adding this space if the last character was also a space
  486. if(lastWasSpace)
  487. continue;
  488. lastWasSpace = true;
  489. }
  490. else
  491. {
  492. lastWasSpace = false;
  493. }
  494. result += currentChar;
  495. }
  496. return result;
  497. }
  498. //+------------------------------------------------------------------+
  499. //| |
  500. //+------------------------------------------------------------------+
  501. bool HasAlphanumeric(string str)
  502. {
  503. //Print("String Length: ", StringLen(str));
  504. for(int i = 0; i <= StringLen(str); i++)
  505. {
  506. //Print("Here ", StringLen(str));
  507. if(IsAlphanumeric((char)str[i]))
  508. {
  509. return true;
  510. break;
  511. }
  512. }
  513. return false;
  514. }
  515. //+------------------------------------------------------------------+
  516. //| |
  517. //+------------------------------------------------------------------+
  518. bool IsAlphanumeric(char c)
  519. {
  520. if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
  521. return true;
  522. return false;
  523. }
  524. //+------------------------------------------------------------------+
  525. //| |
  526. //+------------------------------------------------------------------+
  527. string symbolMapping(string symbol)
  528. {
  529. for(int k = 0; k < ArraySize(symbolChart); k++)
  530. {
  531. StringToUpper(symbolChart[k]);
  532. if(symbol == symbolChart[k])
  533. {
  534. symbol = symbolSnd[k];
  535. }
  536. }
  537. symbol = prefix + symbol + suffix;
  538. return symbol;
  539. }
  540. //+------------------------------------------------------------------+
  541. //| |
  542. //+------------------------------------------------------------------+
  543. //+------------------------------------------------------------------+
  544. //+------------------------------------------------------------------+