How to handle the MQL5 Indicators in Multi-Currency and Multi-Timeframe EA?

 

Hello,

I have built an multiTimeframe and MultiSymbol EA. For example, i am using Moving Average, it create handle for all the selected symbols and timeframe. 

1. Sometime Due to Moving Average full EA get stuck
2. Sometime CopyBuffer get failed and return 0 (for all indicators)
3. When i deinit and init again by changing Timeframe my EA getting stuck (Until i close and reopen metatrader again).


My Code :

input string TradingSymbols = "EURUSD,GBPUSD,USDJPY,USDCHF,USDCAD,AUDUSD,NZDUSD,GBPCAD,EURGBP,AUDNZD,XAGUSD,XAUUSD,XAUGBP,XAUAUD,XAUEUR,XAUCAD,XAUJPY,XAUCHF,BTCUSD";
input string __TimeFrame__ = "***TimeFrame Settings***";
// ===== Minute Timeframes =====
input bool PeriodM1   = true;   // PERIOD_M1
input bool PeriodM2   = true;   // PERIOD_M2
input bool PeriodM3   = true;   // PERIOD_M3
input bool PeriodM4   = true;   // PERIOD_M4
input bool PeriodM5   = true;   // PERIOD_M5
input bool PeriodM6   = true;   // PERIOD_M6
input bool PeriodM10  = true;   // PERIOD_M10
input bool PeriodM12  = true;   // PERIOD_M12
input bool PeriodM15  = true;   // PERIOD_M15
input bool PeriodM20  = true;   // PERIOD_M20
input bool PeriodM30  = true;   // PERIOD_M30

// ===== Hour Timeframes =====
input bool PeriodH1   = true;   // PERIOD_H1
input bool PeriodH2   = true;   // PERIOD_H2
input bool PeriodH3   = true;   // PERIOD_H3
input bool PeriodH4   = true;   // PERIOD_H4
input bool PeriodH6   = true;   // PERIOD_H6
input bool PeriodH8   = true;   // PERIOD_H8
input bool PeriodH12  = true;   // PERIOD_H12

// ===== Higher Timeframes =====
input bool PeriodD1   = true;   // PERIOD_D1
input bool PeriodW1   = true;   // PERIOD_W1
input bool PeriodMN1  = true;   // PERIOD_MN1

input string __MovingAverage_Indicator__ = "***Moving Average Indicator Settings***";
input ENUM_APPLIED_PRICE MovingAverage_AppliedPrice = PRICE_CLOSE;
input ENUM_MA_METHOD MovingAverage_Method = MODE_EMA;
input int MovingAverage_Period = 200;
input int MovingAverage_MAShift = 0;

int gSymbolIndex = 0;
string validSymbols[];
ENUM_TIMEFRAMES TimeFrameArray[];

//+------------------------------------------------------------------+
//|   OnInit                                                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   InitMultiSymbols();
   TimeFrameEnabled();

//Indicator Handle
   int MaxPeriod = MovingAverage_Period * 3;

   for(int s=0; s<ArraySize(validSymbols); s++)
     {
      string sym = validSymbols[s];
      SymbolSelect(sym, true);
      for(int t=0; t<ArraySize(TimeFrameArray); t++)
        {
         ENUM_TIMEFRAMES tf = TimeFrameArray[t];
         MqlRates rates[];
         if(CopyRates(sym, tf, 0, MaxPeriod, rates) <= 0)
           {
            Print("Failed to load history for ", sym, " ", EnumToString(tf));
           }
         GetMAHandle(sym, tf, MovingAverage_Period, MovingAverage_MAShift, MovingAverage_Method, MovingAverage_AppliedPrice);
        }
     }

   TesterHideIndicators(true);

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| On Deinit                                                        |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   for(int i=0;i<ArraySize(MAHandles);i++)
     {
      if(MAHandles[i].handle != INVALID_HANDLE)
        {
         if(!IndicatorRelease(MAHandles[i].handle))
            Print("Failed to release MA handle: ", MAHandles[i].handle);
         MAHandles[i].handle = INVALID_HANDLE;
        }
     }
   ArrayResize(MAHandles,0);
  }

//+------------------------------------------------------------------+
//|    OnTick                                                        |
//+------------------------------------------------------------------+
void OnTick()
  {
   for(int s=0; s<ArraySize(validSymbols); s++)
     {
      string sym = validSymbols[s];
      for(int t=0; t<ArraySize(TimeFrameArray); t++)
        {
         ENUM_TIMEFRAMES tf = TimeFrameArray[t];

         double MovingAverageValue = fMA(sym, tf, MovingAverage_Period, 0, MovingAverage_Method, MovingAverage_AppliedPrice, 1);

        }
     }
  }

//+------------------------------------------------------------------+
//|     Symbol Array                                                 |
//+------------------------------------------------------------------+
void InitMultiSymbols()
  {
   ArrayResize(validSymbols, 0);
   gSymbolIndex = 0;

   string inputPairs[];
   int pairCount = StringSplit(TradingSymbols, ',', inputPairs);
   if(pairCount <= 0)
     {
      Print("InitMultiSymbols: No TradingSymbols");
      return;
     }

   bool isTester = MQLInfoInteger(MQL_TESTER);
   int totalMW   = SymbolsTotal(true);

   for(int i = 0; i < pairCount; i++)
     {
      if(isTester)
        {
         // Tester: accept input directly
         ArrayResize(validSymbols, ArraySize(validSymbols) + 1);
         validSymbols[ArraySize(validSymbols) - 1] = inputPairs[i];
        }
      else
        {
         // Live/Demo: only if in Market Watch
         for(int m = 0; m < totalMW; m++)
           {
            if(SymbolName(m, true) == inputPairs[i])
              {
               ArrayResize(validSymbols, ArraySize(validSymbols) + 1);
               validSymbols[ArraySize(validSymbols) - 1] = inputPairs[i];
               break;
              }
           }
        }
     }
  }

//+------------------------------------------------------------------+
//|   Timeframe                                                      |
//+------------------------------------------------------------------+
void TimeFrameEnabled()
  {
   int tfCount = 0;
   ArrayResize(TimeFrameArray, 21);   // max possible TFs

   if(PeriodM1)
      TimeFrameArray[tfCount++] = PERIOD_M1;
   if(PeriodM2)
      TimeFrameArray[tfCount++] = PERIOD_M2;
   if(PeriodM3)
      TimeFrameArray[tfCount++] = PERIOD_M3;
   if(PeriodM4)
      TimeFrameArray[tfCount++] = PERIOD_M4;
   if(PeriodM5)
      TimeFrameArray[tfCount++] = PERIOD_M5;
   if(PeriodM6)
      TimeFrameArray[tfCount++] = PERIOD_M6;
   if(PeriodM10)
      TimeFrameArray[tfCount++] = PERIOD_M10;
   if(PeriodM12)
      TimeFrameArray[tfCount++] = PERIOD_M12;
   if(PeriodM15)
      TimeFrameArray[tfCount++] = PERIOD_M15;
   if(PeriodM20)
      TimeFrameArray[tfCount++] = PERIOD_M20;
   if(PeriodM30)
      TimeFrameArray[tfCount++] = PERIOD_M30;

   if(PeriodH1)
      TimeFrameArray[tfCount++] = PERIOD_H1;
   if(PeriodH2)
      TimeFrameArray[tfCount++] = PERIOD_H2;
   if(PeriodH3)
      TimeFrameArray[tfCount++] = PERIOD_H3;
   if(PeriodH4)
      TimeFrameArray[tfCount++] = PERIOD_H4;
   if(PeriodH6)
      TimeFrameArray[tfCount++] = PERIOD_H6;
   if(PeriodH8)
      TimeFrameArray[tfCount++] = PERIOD_H8;
   if(PeriodH12)
      TimeFrameArray[tfCount++] = PERIOD_H12;

   if(PeriodD1)
      TimeFrameArray[tfCount++] = PERIOD_D1;
   if(PeriodW1)
      TimeFrameArray[tfCount++] = PERIOD_W1;
   if(PeriodMN1)
      TimeFrameArray[tfCount++] = PERIOD_MN1;

   ArrayResize(TimeFrameArray, tfCount);   // shrink to real size
  }


//+------------------------------------------------------------------+
//|   Series Checl                                                   |
//+------------------------------------------------------------------+
bool IsSeriesReady(string sy, ENUM_TIMEFRAMES tf)
  {
   long sync = 0;
   if(!SeriesInfoInteger(sy, tf, SERIES_SYNCHRONIZED, sync))
      return false;

   return (sync == 1);
  }

//+------------------------------------------------------------------+
//|  Force Rates                                                     |
//+------------------------------------------------------------------+
bool ForceRates(string sy, ENUM_TIMEFRAMES tf)
  {
   int MaxPeriod = MovingAverage_Period * 3;
   
   MqlRates rates[];
   ArraySetAsSeries(rates, true);

   int copied = CopyRates(sy, tf, 0, MaxPeriod, rates);
   return (copied > 0);
  }

//+------------------------------------------------------------------+
//|      Moving Average                                              |
//+------------------------------------------------------------------+
struct MA_HANDLE
  {
   string            symbol;
   ENUM_TIMEFRAMES   tf;
   int               period;
   int               shift;
   ENUM_MA_METHOD    method;
   ENUM_APPLIED_PRICE price;
   int               handle;
  };

MA_HANDLE MAHandles[];
//MA Handle
int GetMAHandle(string sy, ENUM_TIMEFRAMES tf, int period, int ma_shift, ENUM_MA_METHOD method, ENUM_APPLIED_PRICE price)
  {
   for(int i=0;i<ArraySize(MAHandles);i++)
     {
      if(MAHandles[i].symbol==sy &&
         MAHandles[i].tf==tf &&
         MAHandles[i].period==period &&
         MAHandles[i].shift==ma_shift &&
         MAHandles[i].method==method &&
         MAHandles[i].price==price)
        {
         return MAHandles[i].handle;
        }
     }

//Symbol Safety
   if(!SymbolSelect(sy, true))
     {
      Print(__FUNCTION__, "SymbolSelect Returned Error for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return -919;
     }

//Symbol Sync Check
   if(!SymbolIsSynchronized(sy))
     {
      Print(__FUNCTION__, "Symbol Synchreonized Returned Error for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return -919;
     }

//Check Bars
   if(Bars(sy, tf) < period)
     {
      Print(__FUNCTION__, "Bars (No Enough Bars) Returned Error for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return -919;
     }

//force price data
   if(!ForceRates(sy, tf))
     {
      Print(__FUNCTION__, "Rate Returned Error for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return -919;
     }

// Ensure series is synchronized
   if(!IsSeriesReady(sy, tf))
     {
      Print(__FUNCTION__, " Series Returned Error for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return -919;
     }

   int h = iMA(sy, tf, period, ma_shift, method, price);
   if(h == INVALID_HANDLE)
     {
      Print(__FUNCTION__, " Failed to create MA for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return INVALID_HANDLE;
     }

   int n = ArraySize(MAHandles);
   ArrayResize(MAHandles, n+1);

   MAHandles[n].symbol = sy;
   MAHandles[n].tf     = tf;
   MAHandles[n].period = period;
   MAHandles[n].shift  = ma_shift;
   MAHandles[n].method = method;
   MAHandles[n].price  = price;
   MAHandles[n].handle = h;

   return h;
  }

//MA Value
double fMA(string sy, ENUM_TIMEFRAMES tf, int period, int ma_shift, ENUM_MA_METHOD method, ENUM_APPLIED_PRICE price, int shift)
  {

   int h = GetMAHandle(sy, tf, period, ma_shift, method, price);
   if(h == INVALID_HANDLE || h == -919)
     {
      Print(__FUNCTION__, "Invalid Handle Returned 0 for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return 0;
     }

// Ensure indicator is calculated
   if(BarsCalculated(h) <= shift + period)
     {
      Print(__FUNCTION__, "BarsCalculated (Shift) Returned 0 for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return 0;
     }

   double buf[];
   ArraySetAsSeries(buf, true);
   if(CopyBuffer(h, 0, shift, 1, buf) <= 0)
     {
      Print(__FUNCTION__, " CopyBuffer Returned 0 for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return 0;
     }

   return buf[0];
  }


I have attached full handle EA for multiple indicator (In-case if you needed for reference), Kindly check the attachment.


Please Help me optimism and fix the code. 

Files:
 
Shanmugi:

Hello,

I have built an multiTimeframe and MultiSymbol EA. For example, i am using Moving Average, it create handle for all the selected symbols and timeframe. 

1. Sometime Due to Moving Average full EA get stuck
2. Sometime CopyBuffer get failed and return 0 (for all indicators)
3. When i deinit and init again by changing Timeframe my EA getting stuck (Until i close and reopen metatrader again).


My Code :


I have attached full handle EA for multiple indicator (In-case if you needed for reference), Kindly check the attachment.


Please Help me optimism and fix the code. 

Traders and coders are working for free:

  • if it is interesting for them personally, or
  • if it is interesting for many members on this forum.

Freelance section of the forum should be used in most of the cases.

Trading applications for MetaTrader 5 to order
Trading applications for MetaTrader 5 to order
  • 2026.02.14
  • www.mql5.com
The largest freelance service with MQL5 application developers