//+------------------------------------------------------------------+ //| My-Functions.mqh | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property strict // Include necessary libraries #include #include #include #include #include #include // Global Variables // ================ // Chart control bool removeFromThisChartOnly = true; // Trading parameters int slip = 20; // Slippage in points double TradeVolume = 0.5; // Default lot size for buy orders double sd = 100; // Start Difference for buy orders (in points) double sl = 0; // Stop Loss for buy orders (in points) double tp = 0; // Take Profit for buy orders (in points) double tsl = 50; // Trailing Stop Loss for buy orders (in points) // Sell order parameters double TradeVolumeSell = 0.5; // Default lot size for sell orders double sdSell = 100; // Start Difference for sell orders (in points) double slSell = 0; // Stop Loss for sell orders (in points) double tpSell = 0; // Take Profit for sell orders (in points) double tslSell = 50; // Trailing Stop Loss for sell orders (in points) // Trailing stop levels double buynewtsl = 10000000; // Current trailing stop level for buy orders double sellnewtsl = 0; // Current trailing stop level for sell orders // Price tracking double buyprice = 100000; // Current buy price double sellprice = 1; // Current sell price double buylimitprice = 1; // Current buy limit price double selllimitprice = 100000; // Current sell limit price // Time Functions datetime timetostartopenchart = TimeCurrent(); datetime timetostartclosechart = TimeCurrent(); // Trade limits int max_trades_same_type = 3; // Maximum number of trades of same type // Account tracking double MaxAccountBalance = AccountBalance(); // Maximum account balance double InitialAccountBalance = AccountBalance();// Initial account balance double MinAccountBalance = 1000000; // Minimum account balance threshold // Symbol and source arrays string symbols[] = { "XAUUSD", "XAGUSD", "XTIUSD", "USDJPY", "EURJPY", "GBPJPY", "CHFJPY", "USDCHF", "XAUEUR","XAUGBP","NZDUSD", "USDCAD", "AUDUSD", "EURUSD", "EURGBP", "EURNZD", "GBPUSD", "NZDCAD", "GBPNZD", "GBPAUD", "EURAUD", "NZDCHF" }; string sources[] = {"Own", "News", "Younus"}; int count_symbols = ArraySize(symbols); // Number of symbols in array int count_sources = ArraySize(sources); // Number of sources in array // Telegram bot configuration CCustomBot bot; string InpToken = "8181067618:AAGqA6S1y59CG5JgxX-c2rcgEt0kvpgCBvY"; // UK Bot int check_telegram_updates = 2150; // Update check interval in milliseconds int capture_previous_update_id = 0; ulong chat_id = 0; //+------------------------------------------------------------------+ //| Order Placement Functions | //+------------------------------------------------------------------+ /** * Places a buy stop order * @param MagicBuy The magic number to identify the order */ void showbalance() { double CurrentAccountBalance = AccountBalance(); if (MaxAccountBalance < AccountBalance()) MaxAccountBalance = AccountBalance(); if (MinAccountBalance > AccountBalance()) MinAccountBalance = AccountBalance(); Comment ("Initial Account Balance was ",InitialAccountBalance,", Minimum Balance was ",MinAccountBalance,", Max Balance was ", MaxAccountBalance,", Current Balance is ",CurrentAccountBalance," and Current Equity is ",AccountEquity(), ""); } void chartopenclose() { if (TimeCurrent()-timetostartopenchart>20) { Print ("Trying to Open Chart in Use"); timetostartopenchart=TimeCurrent(); // Open Symbol Chart for (int b= OrdersTotal()-1;b>=0;b--) { if (OrderSelect(b,SELECT_BY_POS,MODE_TRADES)) { bool found = false; long ID = ChartFirst(); while(ID>=0) { if(ChartSymbol(ID)==OrderSymbol()) { found=true; break; } ID=ChartNext(ID); } if(!found) ChartOpen(OrderSymbol(),0); }}} if (TimeCurrent() - timetostartclosechart > 30) { Print("Trying to Close Chart not in use"); timetostartclosechart = TimeCurrent(); long ID_chart = ChartFirst(); ID_chart = ChartNext(ID_chart); // Skip the first chart while(ID_chart >= 0) { bool shouldClose = true; string chartSymbol = ChartSymbol(ID_chart); // 1. Always keep these protected symbols if (chartSymbol == "XAUUSD" || chartSymbol == "Cocoa_K5" || chartSymbol == "CHINA50") { shouldClose = false; Print("Keeping protected symbol: ", chartSymbol); } // 2. Check for open trades on this symbol if (shouldClose) { for(int b = OrdersTotal() - 1; b >= 0; b--) { if (OrderSelect(b, SELECT_BY_POS, MODE_TRADES) && OrderSymbol() == chartSymbol) { shouldClose = false; Print("Keeping chart with open trade: ", chartSymbol); break; } } } // 3. Ultimate EA Detection - Check for chart objects if (shouldClose) { int objTotal = ObjectsTotal(ID_chart); if (objTotal > 2) // Most EAs create at least 2-3 objects { shouldClose = false; Print("Keeping possible EA chart (", objTotal, " objects): ", chartSymbol); } } // 4. Final closing decision if (shouldClose) { Print("Closing unused chart: ", chartSymbol); ChartClose(ID_chart); } ID_chart = ChartNext(ID_chart); } } } long GetChartIDSymbol(string symb) { bool found = false; long ID = ChartFirst(); while (ID >= 0) { if (ChartSymbol(ID) == symb) { found = true; break; } ID = ChartNext(ID); } return ID; } bool CheckBuyOpenOrders(int MagicBuy) { for (int i = 0; i < OrdersTotal(); i++) { int OrderBO = OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if (OrderType() == OP_BUY && OrderMagicNumber() == MagicBuy) return true; } return false; } bool CountBuyOpenOrders(string symb) { int ordercount = 0; for (int i = 0; i < OrdersTotal(); i++) { int OrderSO = OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol() == symb && (OrderType() == OP_BUY)) ordercount = ordercount + 1; } if (ordercount < max_trades_same_type) return true; else return false; } bool CheckBuyStopOpenOrders(int MagicBuy) { for (int i = 0; i < OrdersTotal(); i++) { int OrderBO = OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if (OrderType() == OP_BUYSTOP && OrderMagicNumber() == MagicBuy) return true; } return false; } void BuyStopOrder(int MagicBuy) { if (sl == 0 && tsl != 0) sl = tsl; double buy = Ask + sd * Point; buy = NormalizeDouble(buy, _Digits); double slbuy = buy - sl * Point; slbuy = NormalizeDouble(slbuy, _Digits); double tpbuy = buy + tp * Point; tpbuy = NormalizeDouble(tpbuy, _Digits); if (sl == 0) slbuy = 0; if (tp == 0) tpbuy = 0; int orderbuystop = OrderSend(_Symbol, OP_BUYSTOP, TradeVolume, buy, slip, slbuy, tpbuy, NULL, MagicBuy, 0, clrBlue); buyprice = buy; if (sl != 0 && tsl != 0) buynewtsl = slbuy; } bool CheckBuyLimitOpenOrders(int MagicBuy) { for (int i = 0; i < OrdersTotal(); i++) { int OrderBO = OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if (OrderType() == OP_BUYLIMIT && OrderMagicNumber() == MagicBuy) return true; } return false; } void BuyLimitOrder(int MagicBuy) { if (sl == 0 && tsl != 0) sl = tsl; double buy = Ask - sd * Point; buy = NormalizeDouble(buy, _Digits); double slbuy = buy - sl * Point; slbuy = NormalizeDouble(slbuy, _Digits); double tpbuy = buy + tp * Point; tpbuy = NormalizeDouble(tpbuy, _Digits); if (sl == 0) slbuy = 0; if (tp == 0) tpbuy = 0; int orderlimitstop = OrderSend(_Symbol, OP_BUYLIMIT, TradeVolume, buy, slip, slbuy, tpbuy, NULL, MagicBuy, 0, clrBlue); buylimitprice = buy; if (sl != 0 && tsl != 0) buynewtsl = slbuy; } void CloseBuyOrders(int MagicBuy) { Comment("Buy Orders are Closed"); for (int i = OrdersTotal() - 1; i >= 0; i--) { int OrderAll = OrderSelect(i, SELECT_BY_POS); if (OrderSymbol() != Symbol() && removeFromThisChartOnly) continue; if (OrderType() == OP_BUY && OrderMagicNumber() == MagicBuy) { double price = MarketInfo(OrderSymbol(), MODE_BID); int OpenDelete = OrderClose(OrderTicket(), OrderLots(), price, 5); } Sleep(100); int error = GetLastError(); if (error > 0) Print("Unanticipated error: "); RefreshRates(); } } bool CheckSellOpenOrders(int MagicSell) { for (int i = 0; i < OrdersTotal(); i++) { int OrderSO = OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if (OrderType() == OP_SELL && OrderMagicNumber() == MagicSell) return true; } return false; } bool CountSellOpenOrders(string symb) { int ordercount = 0; for (int i = 0; i < OrdersTotal(); i++) { int OrderSO = OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol() == symb && (OrderType() == OP_SELL)) ordercount = ordercount + 1; } if (ordercount < max_trades_same_type) return true; else return false; } bool CheckSellStopOpenOrders(int MagicSell) { for (int i = 0; i < OrdersTotal(); i++) { int OrderSO = OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if (OrderType() == OP_SELLSTOP && OrderMagicNumber() == MagicSell) return true; } return false; } void SellStopOrder(int MagicSell) { if (slSell == 0 && tslSell != 0) slSell = tslSell; double sell = Bid - sdSell * Point; sell = NormalizeDouble(sell, _Digits); double tpsellnew = sell - tpSell * Point; tpsellnew = NormalizeDouble(tpsellnew, _Digits); double slsellnew = sell + slSell * Point; slsellnew = NormalizeDouble(slsellnew, _Digits); if (slSell == 0) slsellnew = 0; if (tpSell == 0) tpsellnew = 0; int ordersell = OrderSend(_Symbol, OP_SELLSTOP, TradeVolumeSell, sell, slip, slsellnew, tpsellnew, NULL, MagicSell, 0, clrGreen); sellprice = sell; if (slSell != 0 && tslSell != 0) sellnewtsl = slsellnew; } bool CheckSellLimitOpenOrders(int MagicSell) { for (int i = 0; i < OrdersTotal(); i++) { int OrderSO = OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if (OrderType() == OP_SELLLIMIT && OrderMagicNumber() == MagicSell) return true; } return false; } void SellLimitOrder(int MagicSell) { if (slSell == 0 && tslSell != 0) slSell = tslSell; double sell = Bid + sdSell * Point; sell = NormalizeDouble(sell, _Digits); double tpsellnew = sell - tpSell * Point; tpsellnew = NormalizeDouble(tpsellnew, _Digits); double slsellnew = sell + slSell * Point; slsellnew = NormalizeDouble(slsellnew, _Digits); if (slSell == 0) slsellnew = 0; if (tpSell == 0) tpsellnew = 0; int ordersell = OrderSend(_Symbol, OP_SELLLIMIT, TradeVolumeSell, sell, slip, slsellnew, tpsellnew, NULL, MagicSell, 0, clrGreen); selllimitprice = sell; if (slSell != 0 && tslSell != 0) sellnewtsl = slsellnew; } void CloseSellOrders(int MagicSell) { Comment("Sell Orders are Closed"); for (int i = OrdersTotal() - 1; i >= 0; i--) { int OrderAll = OrderSelect(i, SELECT_BY_POS); if (OrderSymbol() != Symbol() && removeFromThisChartOnly) continue; if (OrderType() == OP_SELL && OrderMagicNumber() == MagicSell) { double price = MarketInfo(OrderSymbol(), MODE_ASK); int OpenDelete = OrderClose(OrderTicket(), OrderLots(), price, 5); } Sleep(100); int error = GetLastError(); if (error > 0) Print("Unanticipated error: "); RefreshRates(); } } bool CheckOpenOrders(int Magic) { for (int i = 0; i < OrdersTotal(); i++) { int OrderSO = OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if (OrderMagicNumber() == Magic) return true; } return false; } void ClosePendingOrders(int Magic) { Comment("All Pending Orders are Closed"); for (int i = OrdersTotal() - 1; i >= 0; i--) { int OrderPending = OrderSelect(i, SELECT_BY_POS); double price = MarketInfo(OrderSymbol(), MODE_ASK); if (OrderType() == OP_BUY) price = MarketInfo(OrderSymbol(), MODE_BID); if (OrderMagicNumber() == Magic) { int PendingDelete = OrderDelete(OrderTicket()); } Sleep(100); int error = GetLastError(); if (error > 0) Print("Unanticipated error: "); RefreshRates(); } } void CloseAllOrders(int Magic) { Comment("All Orders are Closed"); for (int i = OrdersTotal() - 1; i >= 0; i--) { int OrderAll = OrderSelect(i, SELECT_BY_POS); if (OrderSymbol() != Symbol() && removeFromThisChartOnly) continue; double price = MarketInfo(OrderSymbol(), MODE_ASK); if (OrderType() == OP_BUY) price = MarketInfo(OrderSymbol(), MODE_BID); if ((OrderType() == OP_BUY && OrderMagicNumber() == Magic) || (OrderType() == OP_SELL && OrderMagicNumber() == Magic)) { int OpenDelete = OrderClose(OrderTicket(), OrderLots(), price, 5); } else { int AllDelete = OrderDelete(OrderTicket()); } Sleep(100); int error = GetLastError(); if (error > 0) Print("Unanticipated error: "); RefreshRates(); } } bool lastlosscheck() { int OrderCheck = OrderSelect(OrdersHistoryTotal() - 1, SELECT_BY_POS, MODE_HISTORY); if (OrderProfit() < 0) return true; else return false; } int CreateMagicNumber(string source, string symb, string type, int ordernum) { int sourcenumber = 9900000; int symbnumber = 99900; int typenumber = 99; // Find source index for (int x = 0; x < count_sources; x++) { if (source == sources[x]) sourcenumber = 1000000 * (x + 1); } // Find symbol index for (int x = 0; x < count_symbols; x++) { if (symb == symbols[x]) symbnumber = 30000 + (x + 1) * 100; } // Set type number if (type == "Buy") typenumber = 10; if (type == "Sell") typenumber = 20; // Combine all components int magicnumber = sourcenumber + symbnumber + typenumber + ordernum; return magicnumber; } string GetMagicSource(int Magic) { string tempmagic = IntegerToString(Magic); tempmagic = StringSubstr(tempmagic, 0, 2); int sourcemagic = StrToInteger(tempmagic) / 10; string source = sources[sourcemagic - 1]; return source; } string GetMagicSymbol(int Magic) { string tempmagic = IntegerToString(Magic); tempmagic = StringSubstr(tempmagic, 2, 3); int symbolmagic = StrToInteger(tempmagic) - 300; string symbol = symbols[symbolmagic - 1]; return symbol; } string GetMagicType(int Magic) { string tempmagic = IntegerToString(Magic); tempmagic = StringSubstr(tempmagic, 5, 1); string type = "Buy"; if (tempmagic == "2") type = "Sell"; return type; } int GetMagicOrderNum(int Magic) { string tempmagic = IntegerToString(Magic); tempmagic = StringSubstr(tempmagic, 6, 1); int ordernum = StrToInteger(tempmagic); return ordernum; } int GetMagicSourceIndex(int Magic) { string tempmagic = IntegerToString(Magic); tempmagic = StringSubstr(tempmagic, 0, 2); int sourcemagic = StrToInteger(tempmagic) / 10; int source = sourcemagic - 1; return source; } int GetMagicSymbolIndex(int Magic) { string tempmagic = IntegerToString(Magic); tempmagic = StringSubstr(tempmagic, 2, 3); int symbolmagic = StrToInteger(tempmagic) - 300; int symbol = symbolmagic - 1; return symbol; } int GetMagicTypeNum(int Magic) { string tempmagic = IntegerToString(Magic); tempmagic = StringSubstr(tempmagic, 5, 1); int type = 0; if (tempmagic == "2") type = 1; return type; } string toUpper(string text) { StringToUpper(text); return text; } double PipsToPrice(double pips, string symb) { double price; if (symb == "XAUUSD" || symb == "XTIUSD" || symb == "XAUEUR" || symb == "XAUGBP") { price = pips / 100; return price; } if (symb == "USDJPY" || symb == "EURJPY" || symb == "GBPJPY" || symb == "CHFJPY" || symb == "XAGUSD") { price = pips / 1000; return price; } if (symb == "USDCAD" || symb == "AUDUSD" || symb == "EURUSD" || symb == "EURGBP" || symb == "EURNZD" || symb == "USDCHF" || symb == "GBPUSD" || symb == "NZDCAD" || symb == "NZDUSD" || symb == "GBPNZD" || symb == "GBPAUD" || symb == "EURAUD" ) { price = pips / 100000; return price; } return 0; } int telegram_to_mt4() { CJAVal js; string headers; char post[], result[]; int res = WebRequest("GET", "https://api.telegram.org/bot" + InpToken + "/getUpdates?offset=-1", "", NULL, 10000, post, ArraySize(post), result, headers); string server_response_data = CharArrayToString(result); js.Deserialize(result); string update_id_str = js["result"][0]["update_id"].ToStr(); int update_id = StrToInteger(update_id_str); string chat_id_str = js["result"][0]["message"]["chat"]["id"].ToStr(); chat_id = (ulong)chat_id_str; string output[]; string output2[]; if (capture_previous_update_id < update_id) { capture_previous_update_id = update_id; string chat_message_text = js["result"][0]["message"]["text"].ToStr(); string chat_message_caption = js["result"][0]["message"]["caption"].ToStr(); StringSplit(chat_message_text, StringGetCharacter("\n", 0), output); StringSplit(chat_message_caption, StringGetCharacter("\n", 0), output2); if (res == -1) { Print("Error in WebRequest. Error code = ", GetLastError()); MessageBox("Add the address in the list of allowed URLs on tab 'Expert Advisors'", "Error", MB_ICONINFORMATION); } else { // Save chat ID int filehandle11 = FileOpen("chat_id.txt", FILE_WRITE | FILE_TXT); FileWriteString(filehandle11, IntegerToString(chat_id)); FileClose(filehandle11); // Save message details int filehandle2 = FileOpen("message_details.txt", FILE_WRITE | FILE_CSV); int count_lines = ArraySize(output); for (int x = 0; x < count_lines; x++) { FileWriteString(filehandle2, output[x]); FileWriteString(filehandle2, ","); } int count_lines2 = ArraySize(output2); for (int x = 0; x < count_lines2; x++) { FileWriteString(filehandle2, output2[x]); FileWriteString(filehandle2, ","); } FileClose(filehandle2); } } return capture_previous_update_id; } string TruncateNumber(string number) { int start_index = StringFind(number, "."); if (start_index == -1) return number; string vals[2] = {"", ""}; StringSplit(number, '.', vals); if (StringLen(vals[1]) <= 3) return number; return StringConcatenate(vals[0], ".", StringSubstr(vals[1], 0, 4)); } double updatetextboxdouble(string ssparam, string boxname, double boxvaluecurrent) { double boxvalue=boxvaluecurrent; if(ssparam == boxname) { string volumeText = ObjectGetString(0, boxname, OBJPROP_TEXT); boxvalue = StringToDouble(volumeText); ObjectSetString(0, boxname, OBJPROP_TEXT, string(boxvalue)); } return boxvalue; } string updatetextboxstring(string s2param, string boxname, string boxvaluecurrent) { string boxvalue=boxvaluecurrent; if(s2param == boxname) { string volumeText = ObjectGetString(0, boxname, OBJPROP_TEXT); ObjectSetString(0, boxname, OBJPROP_TEXT, boxvalue); } return boxvalue; } void createLabel(CLabel &labelCtrl, CAppDialog &parent, string name, string text, int startx, int endx, int starty, int endy) { labelCtrl.Create(0,name,0,startx,starty,endx,endy); parent.Add(labelCtrl); labelCtrl.Text(text); } void createInputBox(CEdit &editCtrl, CAppDialog &parent, string name, string text, int startx, int endx, int starty, int endy) { editCtrl.Create(0,name,0,startx,starty,endx,endy); parent.Add(editCtrl); editCtrl.Text(string(text)); } string SecondsToHMS(int totalSeconds) { int hours = totalSeconds / 3600; int minutes = (totalSeconds % 3600) / 60; int seconds = totalSeconds % 60; return StringFormat("%02d:%02d:%02d", hours, minutes, seconds); } int GetTextWidth(string text, int fontSize = 10) { // Average width per character for basic fonts double avgCharWidth = fontSize * 0.6; // You can tweak this multiplier if needed return (int)(StringLen(text) * avgCharWidth); } bool isbasecurrency(string symbol, string currency) { if (StringLen(symbol) < 6 || StringLen(currency) != 3) return false; // Basic validation string base = StringSubstr(symbol, 0, 3); // First 3 letters are base currency return (base == currency); }