Add an EMA on a custom indicator

 

Hi,

I created a simple custom indicator to display a ratio between 2 instruments. It's display a line, calcul is ok. But now i want to add an EMA7 on this custom indicator and when i try it display nothing. Could you help me? Thanks in advance :)

My code:

//+------------------------------------------------------------------+
//|                                                     SpreadV1.mq5 |
//|                                                             Jiyu |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Jiyu"
#property version   "1.00"

#property indicator_separate_window
#property indicator_buffers 
2 
#property indicator_plots   
2 

#property indicator_label1  "Ratio"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrGray
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "EMA7"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

input string Symbol01   = "EURUSD";
input string Symbol02   = "GBPUSD";

double Ratio[];
double EMA7[];
int i, count, IntPeriod;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0, Ratio, INDICATOR_DATA);
   SetIndexBuffer(1, EMA7, INDICATOR_DATA);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{

   ArraySetAsSeries(time,true);
   ArraySetAsSeries(close,true);

   ArraySetAsSeries(Ratio,true);
   ArraySetAsSeries(EMA7,true);
   
   MqlRates rates1[]; ArraySetAsSeries(rates1,true);
   MqlRates rates2[]; ArraySetAsSeries(rates2,true);
  
   int start = prev_calculated;

   if(start == 0)
     start = 1;

   int limit = rates_total - start;

   for(i = 0; i < limit; i++)
   {
      CopyRates(Symbol01, 0, time[i], 1, rates1);
      CopyRates(Symbol02, 0, time[i], 1, rates2);
      Ratio[i] = rates1[0].close / rates2[0].close;
   }
   
   for(i = 0; i < limit; i++)
   {   
      EMA7[i] = iMAOnArray(Ratio, 0, 7, 0, MODE_EMA, 0);
   }     
     
   return(rates_total);
}

double iMAOnArray(double &array[],
                      int total,
                      int period,
                      int ma_shift,
                      int ma_method,
                      int shift)
  {
   double buf[],arr[];
   if(total==0) total=ArraySize(array);
   if(total>0 && total<=period) return(0);
   if(shift>total-period-ma_shift) return(0);
   switch(ma_method)
     {
      case MODE_EMA :
        {
         if(ArrayResize(buf,total)<0) return(0);
         double pr=2.0/(period+1);
         int    pos=total-2;
         while(pos>=0)
           {
            if(pos==total-2) buf[pos+1]=array[pos+1];
            buf[pos]=array[pos]*pr+buf[pos+1]*(1-pr);
            pos--;
           }
         return(buf[shift+ma_shift]);
        }
      default: return(0);
     }
   return(0);
  }
 
Jiyu:

Hi,

I created a simple custom indicator to display a ratio between 2 instruments. It's display a line, calcul is ok. But now i want to add an EMA7 on this custom indicator and when i try it display nothing. Could you help me? Thanks in advance :)

My code:

for(i = 0; i < limit; i++)
{   
   EMA7[i] = iMAOnArray(Ratio, 0, 7, 0, MODE_EMA, i );
}     
 
Why are you calculating ema value all from start?
I don't think there is a problem except long loading time which is mostly due to iMAOnArray calculating everything from start on every single iteration.
Added that you are loading data from another chart that adds to load time.
 
Nagisa Unada #:
Hi, thanks for your help but it doesn't work...
 
Yashar Seyyedin #:
Why are you calculating ema value all from start?
I don't think there is a problem except long loading time which is mostly due to iMAOnArray calculating everything from start on every single iteration.
Added that you are loading data from another chart that adds to load time.
I don't think that's a loading problem. Perhaps something in my for loop (i'm a beginner). But i would like to try your idea: how to display my indicator only from now?
 
Jiyu #:
Hi, thanks for your help but it doesn't work...

I have confirmed that it does indeed work on my MT5. However, it takes a bit of time to display.

 
//+------------------------------------------------------------------+
//|                                                     SpreadV1.mq5 |
//|                                                             Jiyu |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Jiyu"
#property version   "1.00"

#property indicator_separate_window
#property indicator_buffers 2 
#property indicator_plots   2 

#property indicator_label1  "Ratio"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrGray
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "EMA7"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

input string Symbol01   = "EURUSD";
input string Symbol02   = "GBPUSD";

double Ratio[];
double EMA7[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0, Ratio, INDICATOR_DATA);
   SetIndexBuffer(1, EMA7, INDICATOR_DATA);

   ArraySetAsSeries(Ratio,true);
   ArraySetAsSeries(EMA7,true);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   MqlRates rates1[]; ArraySetAsSeries(rates1,true);
   MqlRates rates2[]; ArraySetAsSeries(rates2,true);
  
   int limit = MathMax(rates_total-prev_calculated-2 ,1);

   for(int i = limit; i >=0 ; i--)
   {
      bool b1=CopyRates(Symbol01, 0, i, 1, rates1);
      bool b2=CopyRates(Symbol02, 0, i, 1, rates2);
      if(!b1 || !b2) 
      {
         Print("Problem loading data!");
         return prev_calculated;
      }
      Ratio[i] = rates1[0].close / rates2[0].close;
      EMA7[i]=EMA7[i+1]*(1-2.0/8.0)+Ratio[i]*2.0/8.0;
   }
        
   return(rates_total);
}

 
Nagisa Unada #:

I have confirmed that it does indeed work on my MT5. However, it takes a bit of time to display.

Ok, I will try again

 
Jiyu #:

Ok, I will try again

l checked again and believe there's more to fix. Logical errors also. So I rewrote it all. Please check.
 
// After calculating all Ratio values
if(limit > 0) {
    // Calculate EMA for the entire Ratio array at once, outside the loop
    double previousEMA = Ratio[0]; // Initial EMA value can be the first Ratio value or another starting point
    for(i = 0; i < limit; i++) {
        double currentPrice = Ratio[i];
        EMA7[i] = (currentPrice * (2.0 / (7 + 1))) + (previousEMA * (1 - (2.0 / (7 + 1))));
        previousEMA = EMA7[i]; // Update previousEMA for the next iteration
    }
}
 

I modified the script posted by Yashar above so that it won't give errors when switching to different timeframes


//+------------------------------------------------------------------+
//|                                                     SpreadV1.mq5 |
//|                                                             Jiyu |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Jiyu"
#property version   "1.00"

#property indicator_separate_window
#property indicator_buffers 2 
#property indicator_plots   2 

#property indicator_label1  "Ratio"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrGray
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#property indicator_label2  "EMA7"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1



input string Symbol01   = "EURUSD";
input string Symbol02   = "GBPUSD";
input int bars = 1000;

double Ratio[];
double EMA7[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0, Ratio, INDICATOR_DATA);
   SetIndexBuffer(1, EMA7, INDICATOR_DATA);

   ArraySetAsSeries(Ratio,true);
   ArraySetAsSeries(EMA7,true);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+


int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   MqlRates rates1[]; ArraySetAsSeries(rates1,true);
   MqlRates rates2[]; ArraySetAsSeries(rates2,true);
   
 
  // Copy rates data for both symbols
   bool b1 = CopyRates(Symbol01, 0, 0, rates_total, rates1);
   bool b2 = CopyRates(Symbol02, 0, 0, rates_total, rates2);
   
   if (!b1 || !b2) {
   
      Print("Problem loading data!");
      return prev_calculated;
   }
   
   // Calculate Ratio and EMA7 up until the defined amount of bars
   for(int i = bars; i >= 0; i--){
   
      Ratio[i] = rates1[i].close / rates2[i].close;
      if((i+1) > 0) EMA7[i] = EMA7[i+1] * (1 - 2.0/8.0) + Ratio[i] * 2.0/8.0;
   }

          
   return(rates_total);
}
Reason: