Download MetaTrader 5

Grouping various indicators in one indicator

To add comments, please log in or register
Claudio Arrau
104
Claudio Arrau  

Hi,

in MQL4 I often grouped several indicators in one, filling the buffers with standard functions:


      GD[i]=iMA(NULL,0,FastEMA,0,MODE_EMA,PRICE_CLOSE,i);
      Short[i]=iMA(NULL,0,SlowEMA,0,MODE_EMA,PRICE_LOW,i);
      Long[i]=iMA(NULL,0,SlowEMA,0,MODE_EMA,PRICE_HIGH,i);
      Large[i]=iMA(NULL,0,LargeEMA,0,MODE_EMA,PRICE_CLOSE,i);


Now, iMA gives back a Handle instead of the values, so it is not working anymore like this in MQL5.

I only managed to call iMA from an EA with iCustom, but how can I use the standard indicator functions in my Indicator Code?

Documentation on MQL5: Technical Indicators / iMA
Documentation on MQL5: Technical Indicators / iMA
  • www.mql5.com
Technical Indicators / iMA - Documentation on MQL5
Simon Gniadkowski
Moderator
18042
Simon Gniadkowski  
claudio_arrau2:

Hi,

in MQL4 I often grouped several indicators in one, filling the buffers with standard functions:



Now, iMA gives back a Handle instead of the values, so it is not working anymore like this in MQL5.

I only managed to call iMA from an EA with iCustom, but how can I use the standard indicator functions in my Indicator Code?

If you read the Documentation carefully you will see a clear example of what you need to do . . .

 

//+------------------------------------------------------------------+
//| Filling indicator buffers from the MA indicator                  |
//+------------------------------------------------------------------+
bool FillArrayFromBuffer(double &values[],   // indicator buffer of Moving Average values
                         int shift,          // shift
                         int ind_handle,     // handle of the iMA indicator
                         int amount          // number of copied values
                         )
  {
//--- reset error code
   ResetLastError();
//--- fill a part of the iMABuffer array with values from the indicator buffer that has 0 index
   if(CopyBuffer(ind_handle,0,-shift,amount,values)<0)
     {
      //--- if the copying fails, tell the error code
      PrintFormat("Failed to copy data from the iMA indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }
//--- everything is fine
   return(true);
  }
Claudio Arrau
104
Claudio Arrau  
RaptorUK:

If you read the Documentation carefully you will see a clear example of what you need to do . . .

 

:) thanks a lot...I actually read a lot but sometimes you get blind :(

Claudio Arrau
104
Claudio Arrau  
Well, I was actually spending many hours in really understanding. Sometimes the examples are a little too complicated and giving good programming practices incl. error handling etc.
This is why I post just simple code as a show case.
The code gives 4 lines in one indicator. 2 are calculated by simply writing PRICE_HIGH and PRICE_LOW into the buffers.

Another 2 are using the iMA function.



//+------------------------------------------------------------------+
//|                                                        Atest.mq5 |
//|                                                   Claudio_arrau2 |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Claudio_arrau2"
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   4
#property indicator_label1  "GD"
#property indicator_label2  "Short"
#property indicator_label3  "Long"
#property indicator_label4  "Large"
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_type3   DRAW_LINE
#property indicator_type4   DRAW_LINE
#property indicator_color1  clrDeepSkyBlue
#property indicator_color2  clrLimeGreen
#property indicator_color3  clrRed
#property indicator_color4  clrOrange
#property indicator_style1  STYLE_SOLID
#property indicator_style2  STYLE_SOLID
#property indicator_style3  STYLE_SOLID
#property indicator_style4  STYLE_SOLID
#property indicator_width1  1
#property indicator_width2  1
#property indicator_width3  1
#property indicator_width3  1


double GDBuffer[],ShortBuffer[], LongBuffer[],LargeBuffer[];
int GDHandle,ShortHandle,LongHandle,LargeHandle;
int FastEMA=20;
int SlowEMA=1;
int LargeEMA=70;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {

   SetIndexBuffer(0,GDBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ShortBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,LongBuffer,INDICATOR_DATA);
   SetIndexBuffer(3,LargeBuffer,INDICATOR_DATA);
   GDHandle=iMA(NULL,0,FastEMA,0,MODE_EMA,PRICE_CLOSE);
   LargeHandle=iMA(NULL,0,LargeEMA,0,MODE_EMA,PRICE_CLOSE);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+

int OnCalculate (const int rates_total,      // size of input time series
                 const int prev_calculated,  // bars handled in previous call
                 const datetime& time[],     // Time
                 const double& open[],       // Open
                 const double& high[],       // High
                 const double& low[],        // Low
                 const double& close[],      // Close
                 const long& tick_volume[],  // Tick Volume
                 const long& volume[],       // Real Volume
                 const int& spread[]         // Spread
                )
  {
  
  //Method 1: Calculate Indicator with CopyBuffer, taking from the Handles in "OnInit"
   CopyBuffer(LargeHandle,0,0,rates_total,LargeBuffer);
   CopyBuffer(GDHandle,0,0,rates_total,GDBuffer);

  //Method 2: looping every Bar and writing directly to Buffer for line
   for(int i=0;i<rates_total;i++)
   {
   ShortBuffer[i]=low[i];
   LongBuffer[i]=high[i];
   }
   return(rates_total);

  }
Alain Verleyen
Moderator
33615
Alain Verleyen  
claudio_arrau2:
Well, I was actually spending many hours in really understanding. Sometimes the examples are a little too complicated and giving good programming practices incl. error handling etc.
This is why I post just simple code as a show case.
The code gives 4 lines in one indicator. 2 are calculated by simply writing PRICE_HIGH and PRICE_LOW into the buffers.

Another 2 are using the iMA function.

Some suggestions :

  • You have to check the returned value when using CopyBuffer
  //Method 1: Calculate Indicator with CopyBuffer, taking from the Handles in "OnInit"
   if (CopyBuffer(LargeHandle,0,0,rates_total,LargeBuffer)<rates_total)
      return(0);
   if (CopyBuffer(GDHandle,0,0,rates_total,GDBuffer)<rates_total)
      return(0);
  • There is no need to use a loop to copy low/high, you can use CopyLow/CopyHigh (if it's only for an example using a loop, then your example is poorly chosen).
  //Method 2: looping every Bar and writing directly to Buffer for line
   if(CopyLow(_Symbol, _Period, 0, rates_total, ShortBuffer)<rates_total)
      return(0);
   if(CopyHigh(_Symbol, _Period, 0, rates_total, LongBuffer)<rates_total)
      return(0);
  • Although functional, the indicator isn't effective because it recalculate all buffers on each tick.
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate (const int rates_total,      // size of input time series
                 const int prev_calculated,  // bars handled in previous call
                 const datetime& time[],     // Time
                 const double& open[],       // Open
                 const double& high[],       // High
                 const double& low[],        // Low
                 const double& close[],      // Close
                 const long& tick_volume[],  // Tick Volume
                 const long& volume[],       // Real Volume
                 const int& spread[]         // Spread
                 )
  {

//--- first calculation or number of bars was changed
   int start=(prev_calculated==0) ? 0 : prev_calculated-1;
   int to_copy=(prev_calculated==0) ? rates_total : rates_total-prev_calculated+1;

//Method 1: Calculate Indicator with CopyBuffer, taking from the Handles in "OnInit"
   if(CopyBuffer(LargeHandle,0,start,to_copy,LargeBuffer)<to_copy)
      return(0);
   if(CopyBuffer(GDHandle,0,start,to_copy,GDBuffer)<to_copy)
      return(0);

//Method 2: looping every Bar and writing directly to Buffer for line
   if(CopyLow(_Symbol,_Period,start,to_copy,ShortBuffer)<to_copy)
      return(0);
   if(CopyHigh(_Symbol,_Period,start,to_copy,LongBuffer)<to_copy)
      return(0);

//--- return value of prev_calculated for next call
   return(rates_total);
  }

Not compiled, not tested.

Claudio Arrau
104
Claudio Arrau  
Works fine, thank you!
To add comments, please log in or register