Download MetaTrader 5

Grouping various indicators in one indicator

To add comments, please log in or register
Do you have Linux? Find out how to install MetaTrader on it!
Claudio Arrau
104
Claudio Arrau 2013.07.22 10:50 

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
17999
Simon Gniadkowski 2013.07.22 11:42  
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 2013.07.22 12:25  
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 2013.07.22 21:19  
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
30725
Alain Verleyen 2013.07.22 22:05  
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 2013.07.23 22:25  
Works fine, thank you!
To add comments, please log in or register