MultiTimeframe MultiSymbol EA - How to handle the Indicators?

 

Hello, 

I have built an multiTimeframe and MultiSymbol EA and it use 4 indicator to confirm signal across different symbol and timeframe in MQL4 and i am converting it to MQL5. I am new to MQL5 and i am facing difficult to understand how to handle the Indicators. 

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 function getting broken (Until i close and reopen metatrader again). 

My Code (Kindly check the attachment for full handle code):

I am unable to post full code here because i am getting an error " Message may not exceed 64000 characters ". So kindly check the attachment. 

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

//Indicator Handle
   int MaxPeriod = MathMax(
                      MathMax(RSI_Period, BollingerBands_Period),
                      MathMax(ADX_Period, 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));
           }

         if(MovingAverage)
            GetMAHandle(sym, tf, MovingAverage_Period, MovingAverage_MAShift, MovingAverage_Method, MovingAverage_AppliedPrice);

         if(RelativeStrengthIndex)
            GetRSIHandle(sym, tf, RSI_Period, RSI_AppliedPrice);

         if(BollingerBands)
            GetBBHandle(sym, tf, BollingerBands_Period, BollingerBands_deviation, BollingerBands_BandShift, BollingerBands_AppliedPrice);

         if(AverageDirectionalIndex)
            GetADXHandle(sym, tf, ADX_Period);
        }
     }

   TesterHideIndicators(true);

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//|    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 RSIValue = 0;
         if(RelativeStrengthIndex)
            RSIValue  = fRSI(sym, tf, RSI_Period, RSI_AppliedPrice, 1);

         double BB_UpperBand = 0, BB_LowerBand = 0;
         if(BollingerBands)
           {
            BB_UpperBand  = fBands(sym, tf, BollingerBands_Period, BollingerBands_deviation, 0, BollingerBands_AppliedPrice, UPPER_BAND, 1);

            BB_LowerBand  = fBands(sym, tf, BollingerBands_Period, BollingerBands_deviation, 0, BollingerBands_AppliedPrice, LOWER_BAND, 1);
           }

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

         double ADXStrength = 0, ADX_PlusDI = 0, ADX_MinusDI = 0;
         if(AverageDirectionalIndex)
           {
            ADXStrength = fADX(sym, tf, ADX_Period, MAIN_LINE, 1);

            ADX_PlusDI = fADX(sym, tf, ADX_Period, PLUSDI_LINE, 1);

            ADX_MinusDI = fADX(sym, tf, ADX_Period, MINUSDI_LINE, 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 CountPeriod)
  {
   MqlRates rates[];
   ArraySetAsSeries(rates, true);

   int copied = CopyRates(sy, tf, 0, CountPeriod, 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;
        }
     }

   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)
  {

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

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

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

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

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

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

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

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

   double buf[];
   ArraySetAsSeries(buf, true);

// Copy safely
   if(CopyBuffer(h, 0, shift, 1, buf) <= 0)
     {
      Print(__FUNCTION__, " CopyBuffer Returned 0 for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return 0;
     }

   return buf[0];
  }

//+------------------------------------------------------------------+
//|      BollingerBands                                              |
//+------------------------------------------------------------------+
struct BB_HANDLE
  {
   string            symbol;
   ENUM_TIMEFRAMES   tf;
   int               period;
   double            deviation;
   int               shift;
   ENUM_APPLIED_PRICE price;
   int               handle;
  };

BB_HANDLE BBHandles[];
//BB Handle
int GetBBHandle(string sy, ENUM_TIMEFRAMES tf, int period, double deviation, int bands_shift, ENUM_APPLIED_PRICE price)
  {
   for(int i=0; i<ArraySize(BBHandles); i++)
     {
      if(BBHandles[i].symbol == sy &&
         BBHandles[i].tf == tf &&
         BBHandles[i].period == period &&
         BBHandles[i].deviation == deviation &&
         BBHandles[i].shift == bands_shift &&
         BBHandles[i].price == price)
        {
         return BBHandles[i].handle; // 🔁 reuse
        }
     }

// ❗ create only once
   int h = iBands(sy, tf, period, bands_shift, deviation, price);
   if(h == INVALID_HANDLE)
     {
      Print(__FUNCTION__, " Failed to create for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return INVALID_HANDLE;
     }

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

   BBHandles[n].symbol    = sy;
   BBHandles[n].tf        = tf;
   BBHandles[n].period    = period;
   BBHandles[n].deviation = deviation;
   BBHandles[n].shift     = bands_shift;
   BBHandles[n].price     = price;
   BBHandles[n].handle    = h;

   return h;
  }
//BB Value
double fBands(string sy, ENUM_TIMEFRAMES tf, int period, double deviation, int bands_shift, ENUM_APPLIED_PRICE price, int mode, int shift)
  {

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

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

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

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

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

   int h = GetBBHandle(sy, tf, period, deviation, bands_shift, price);
   if(h == INVALID_HANDLE)
     {
      Print(__FUNCTION__, " Invalid Handle Returned 0 for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return 0;
     }

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

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

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

   return buf[0];
  }

//+------------------------------------------------------------------+
//|      RSI                                                         |
//+------------------------------------------------------------------+
struct RSI_HANDLE
  {
   string            symbol;
   ENUM_TIMEFRAMES   tf;
   int               period;
   ENUM_APPLIED_PRICE price;
   int               handle;
  };

RSI_HANDLE RSIHandles[];
//RSI Handle
int GetRSIHandle(string sy, ENUM_TIMEFRAMES tf, int period, ENUM_APPLIED_PRICE price)
  {
   for(int i=0; i<ArraySize(RSIHandles); i++)
     {
      if(RSIHandles[i].symbol == sy &&
         RSIHandles[i].tf == tf &&
         RSIHandles[i].period == period &&
         RSIHandles[i].price == price)
        {
         return RSIHandles[i].handle; // 🔁 reuse
        }
     }

// ❗ create once
   int h = iRSI(sy, tf, period, price);
   if(h == INVALID_HANDLE)
     {
      Print(__FUNCTION__, " Failed to create for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return INVALID_HANDLE;
     }

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

   RSIHandles[n].symbol = sy;
   RSIHandles[n].tf     = tf;
   RSIHandles[n].period = period;
   RSIHandles[n].price  = price;
   RSIHandles[n].handle = h;

   return h;
  }
//Get RSI Value
double fRSI(string sy, ENUM_TIMEFRAMES tf, int period, ENUM_APPLIED_PRICE price, int shift)
  {

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

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

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

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

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

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

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

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

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

   return buf[0];
  }

//+------------------------------------------------------------------+
//|      ADX                                                         |
//+------------------------------------------------------------------+
struct ADX_HANDLE
  {
   string            symbol;
   ENUM_TIMEFRAMES   tf;
   int               period;
   int               handle;
  };

ADX_HANDLE ADXHandles[];

//Get ADX Handle
int GetADXHandle(string sy, ENUM_TIMEFRAMES tf, int period)
  {
   for(int i = 0; i < ArraySize(ADXHandles); i++)
     {
      if(ADXHandles[i].symbol == sy &&
         ADXHandles[i].tf == tf &&
         ADXHandles[i].period == period)
        {
         return ADXHandles[i].handle; // 🔁 reuse
        }
     }

// ❗ create once
   int h = iADX(sy, tf, period);
   if(h == INVALID_HANDLE)
     {
      Print(__FUNCTION__, " Failed to create for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return INVALID_HANDLE;
     }

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

   ADXHandles[n].symbol = sy;
   ADXHandles[n].tf     = tf;
   ADXHandles[n].period = period;
   ADXHandles[n].handle = h;

   return h;
  }

//ADX Value
double fADX(string sy, ENUM_TIMEFRAMES tf, int period, int mode, int shift)
  {

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

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

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

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

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

   int h = GetADXHandle(sy, tf, period);
   if(h == INVALID_HANDLE)
     {
      Print(__FUNCTION__, "Invalid Handle Returned 0 for symbol: ", sy, " timeframe: ", EnumToString(tf));
      return 0;
     }

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

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

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

   return buf[0];
  }
//+------------------------------------------------------------------+


Kindly help me fix this. 

Files:
 
Shanmugi:

Hello, 

I have built an multiTimeframe and MultiSymbol EA and it use 4 indicator to confirm signal across different symbol and timeframe in MQL4 and i am converting it to MQL5. I am new to MQL5 and i am facing difficult to understand how to handle the Indicators. 

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 function getting broken (Until i close and reopen metatrader again). 

My Code (Kindly check the attachment for full handle code):

I am unable to post full code here because i am getting an error " Message may not exceed 64000 characters ". So kindly check the attachment. 


Kindly help me fix this. 

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.13
  • www.mql5.com
The largest freelance service with MQL5 application developers