Managing Indicator with multiple buffers

 

Hello everyone, hope you are all doing great!

I would love to know if theres a method to deal with multiple buffers. My thought is to use iMA() function to pull data from any symbol and any timeframe. To produce something like the image bellow: Buffers

The problem becomes managing these buffers, from including, declaring, initializing, update etc.. 
Im missing the knowledge on how to create a Multi-dimensional array that would reference all 'ExtLineBuffers', so i can Loop onu it and access all buffers in on place, if this makes sense.

The code I prototyped is this:

// I have added too many buffers. Using only 7 and hard coding it / protoptyping.
// Would be nice to optimze the code properly

#property copyright   "MAGNET"
#property link        ""
#property description "Market Overview, Comparing assets"
#property strict

#property indicator_separate_window
#property indicator_buffers 15

// // DELETE THIS, ASSIGN COLORS ON INIT
#property indicator_color1 White
#property indicator_color2 White
#property indicator_color3 White
#property indicator_color4 White
#property indicator_color5 White
#property indicator_color6 White
#property indicator_color7 White


//--- PARAMETERS
input int            InpMAPeriod=24;        // Period
input int            InpMAShift=0;          // Shift
input ENUM_MA_METHOD InpMAMethod=MODE_SMA;  // Method

//--- BUFFERS
double ExtLineBuffer1[],ExtLineBuffer2[],ExtLineBuffer3[],ExtLineBuffer4[],ExtLineBuffer5[],
ExtLineBuffer6[],ExtLineBuffer7[],ExtLineBuffer8[],ExtLineBuffer9[],ExtLineBuffer10[],
ExtLineBuffer11[],ExtLineBuffer12[],ExtLineBuffer13[],ExtLineBuffer14[],ExtLineBuffer15[];


string str[7][3] = {
{"EURUSD" , "EUR" , "1" },
{"GBPUSD" , "GBP" , "1" },
{"USDJPY" , "JPY" , "-1" },
{"USDCAD" , "CAD" , "-1" },
{"USDCHF" , "CHF" , "-1" },
{"AUDUSD" , "AUD" , "1" },
{"USDSEK" , "SEK" , "-1" }};


// // CUSTOM FUNC
double MA(string symbol, int period, int shift)
{
  return iMA( symbol , 0, period , 0, InpMAMethod, PRICE_CLOSE, shift );
}

void OnDeinit(const int reason)
{
}

void OnChartEvent(const int id,         // Event ID 
                  const long& lparam,   // Parameter of type long event 
                  const double& dparam, // Parameter of type double event 
                  const string& sparam  // Parameter of type string events 
                  )
{                                  
}

// // INIT
int OnInit(void)
{

  IndicatorShortName( "OVERVIEW" );
  IndicatorDigits(Digits);

  
//--- indicator buffers mapping
 SetIndexBuffer(0,ExtLineBuffer1);
 SetIndexBuffer(1,ExtLineBuffer2);
 SetIndexBuffer(2,ExtLineBuffer3);
 SetIndexBuffer(3,ExtLineBuffer4);
 SetIndexBuffer(4,ExtLineBuffer5);
 SetIndexBuffer(5,ExtLineBuffer6);
 SetIndexBuffer(6,ExtLineBuffer7);
  
  // // SET LEVELS
  IndicatorSetInteger(INDICATOR_LEVELS,7);
  IndicatorSetInteger(INDICATOR_LEVELSTYLE,5);
  
  
  for(int i = 0 ; i < 7 ; i++){
    ObjectCreate(0,"label_" + str[i][0]     ,OBJ_TEXT,1,Time[0],0);
    ObjectSetInteger(0,"label_" + str[i][0] ,OBJPROP_ANCHOR,ANCHOR_LEFT_UPPER);
    ObjectSetText( "label_" + str[i][0], str[i][1], NULL, "Arial Black" , White );
  }    
   
  
//--- itialization done
   return(INIT_SUCCEEDED);
}


// // CALC
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[])
  {
//--- check for bars count

//--- 0 == now
   ArraySetAsSeries(close,false);
   
   ArraySetAsSeries(ExtLineBuffer1,1);
   ArraySetAsSeries(ExtLineBuffer2,1);
   ArraySetAsSeries(ExtLineBuffer3,1);
   ArraySetAsSeries(ExtLineBuffer4,1);
   ArraySetAsSeries(ExtLineBuffer5,1);
   ArraySetAsSeries(ExtLineBuffer6,1);
   ArraySetAsSeries(ExtLineBuffer7,1);

//--- first calculation
   if(prev_calculated==0)
   {
      ArrayInitialize(ExtLineBuffer1,0);
      ArrayInitialize(ExtLineBuffer2,0);
      ArrayInitialize(ExtLineBuffer3,0);
      ArrayInitialize(ExtLineBuffer4,0);
      ArrayInitialize(ExtLineBuffer5,0);
      ArrayInitialize(ExtLineBuffer6,0);
      ArrayInitialize(ExtLineBuffer7,0);
   }
   
   int bars_count=WindowBarsPerChart(); 
   int bar=WindowFirstVisibleBar();  

  
   //Comment( StringFormat( "%G ,  %G" , a , b ) );
   ExtLineBuffer1[bar]=0;
   ExtLineBuffer2[bar]=0;
   ExtLineBuffer3[bar]=0;
   ExtLineBuffer4[bar]=0;
   ExtLineBuffer5[bar]=0;
   ExtLineBuffer6[bar]=0;
   ExtLineBuffer7[bar]=0;
   
   int period = InpMAPeriod;  
   
//--- calculation
  for(int i = bar - 1 ; i>=0 ; i--)
  {
    ExtLineBuffer1[i] = ExtLineBuffer1[i+1] - ( ( MA( str[0][0] , period , i + 1 ) - MA( str[0][0] , period , i ) ) / MA( str[0][0] , period , i + 1 ) * 100 * StringToInteger( str[0][2]) );
    ExtLineBuffer2[i] = ExtLineBuffer2[i+1] - ( ( MA( str[1][0] , period , i + 1 ) - MA( str[1][0] , period , i ) ) / MA( str[1][0] , period , i + 1 ) * 100 * StringToInteger( str[1][2]) );
    ExtLineBuffer3[i] = ExtLineBuffer3[i+1] - ( ( MA( str[2][0] , period , i + 1 ) - MA( str[2][0] , period , i ) ) / MA( str[2][0] , period , i + 1 ) * 100 * StringToInteger( str[2][2]) );
    ExtLineBuffer4[i] = ExtLineBuffer4[i+1] - ( ( MA( str[3][0] , period , i + 1 ) - MA( str[3][0] , period , i ) ) / MA( str[3][0] , period , i + 1 ) * 100 * StringToInteger( str[3][2]) );
    ExtLineBuffer5[i] = ExtLineBuffer5[i+1] - ( ( MA( str[4][0] , period , i + 1 ) - MA( str[4][0] , period , i ) ) / MA( str[4][0] , period , i + 1 ) * 100 * StringToInteger( str[4][2]) );
    ExtLineBuffer6[i] = ExtLineBuffer6[i+1] - ( ( MA( str[5][0] , period , i + 1 ) - MA( str[5][0] , period , i ) ) / MA( str[5][0] , period , i + 1 ) * 100 * StringToInteger( str[5][2]) );
    ExtLineBuffer7[i] = ExtLineBuffer7[i+1] - ( ( MA( str[6][0] , period , i + 1 ) - MA( str[6][0] , period , i ) ) / MA( str[6][0] , period , i + 1 ) * 100 * StringToInteger( str[6][2]) );
  
  }
  
  ObjectSetDouble(0, "label_" + str[0][0]    ,OBJPROP_PRICE,ExtLineBuffer1[0]);
  ObjectSetDouble(0, "label_" + str[1][0]    ,OBJPROP_PRICE,ExtLineBuffer2[0]);
  ObjectSetDouble(0, "label_" + str[2][0]    ,OBJPROP_PRICE,ExtLineBuffer3[0]);
  ObjectSetDouble(0, "label_" + str[3][0]    ,OBJPROP_PRICE,ExtLineBuffer4[0]);
  ObjectSetDouble(0, "label_" + str[4][0]    ,OBJPROP_PRICE,ExtLineBuffer5[0]);
  ObjectSetDouble(0, "label_" + str[5][0]    ,OBJPROP_PRICE,ExtLineBuffer6[0]);
  ObjectSetDouble(0, "label_" + str[6][0]    ,OBJPROP_PRICE,ExtLineBuffer7[0]);
  
  IndicatorSetDouble(INDICATOR_LEVELVALUE,0,ExtLineBuffer1[0]); 
  IndicatorSetDouble(INDICATOR_LEVELVALUE,1,ExtLineBuffer2[0]); 
  IndicatorSetDouble(INDICATOR_LEVELVALUE,2,ExtLineBuffer3[0]); 
  IndicatorSetDouble(INDICATOR_LEVELVALUE,3,ExtLineBuffer4[0]);
  IndicatorSetDouble(INDICATOR_LEVELVALUE,4,ExtLineBuffer5[0]);
  IndicatorSetDouble(INDICATOR_LEVELVALUE,5,ExtLineBuffer6[0]);
  IndicatorSetDouble(INDICATOR_LEVELVALUE,6,ExtLineBuffer7[0]);
  
  
  
   
//--- return value of prev_calculated for next call
   return(rates_total);
}


The goal would be to eliminate the need to go thru all the code, checking all manual iterations for mistakes or inclusions ( i.e. Buffer1[0], Buffer2[0], ..., Buffer15[0] )

Thanks very much if you read this,

Mag.

 
Magneet: Hello everyone, hope you are all doing great! I would love to know if theres a method to deal with multiple buffers. My thought is to use iMA() function to pull data from any symbol and any timeframe. To produce something like the image bellow: The problem becomes managing these buffers, from including, declaring, initializing, update etc..  Im missing the knowledge on how to create a Multi-dimensional array that would reference all 'ExtLineBuffers', so i can Loop onu it and access all buffers in on place, if this makes sense. The code I prototyped is this: The goal would be to eliminate the need to go thru all the code, checking all manual iterations for mistakes or inclusions ( i.e. Buffer1[0], Buffer2[0], ..., Buffer15[0] ) Thanks very much if you read this,

Mag.

You would have to approach it using object-oriented programming concepts. For example, you could use an array of a structure (or class) which includes a buffer array, with methods for initialisation and manipulation, so that you could then use a loop over this array to work with the multiple buffers.

 
Magneet:

Topics concerning MT4 and MQL4 have their own section.

In future please post in the correct section.

I have moved your topic to the MQL4 and Metatrader 4 section.

 

@Keith Watford thanks for correcting my mistake, Ill pay attention now onwards.

@Fernando Carreiro i appreciate your insight very much thank you. I have no idea how to go about the path you are explaining, practically.
I would have thought there must be a way to work with an "array of referenced arrays" in mql4.

I tried 'optimizing' the code a little and noticed how slow the indicator becomes when i run the loop per buffer as opposed to all buffer in one loop. So i really need to find out how to make an array made of other arrays. Preferably a & not a copy.

If anyone has any ideas, that would be fantastic. Thanks a lot for now

Keith Watford
Keith Watford
  • 2023.01.05
  • www.mql5.com
Trader's profile
 
@Magneet #: i appreciate your insight very much thank you. I have no idea how to go about the path you are explaining, practically. I would have thought there must be a way to work with an "array of referenced arrays" in mql4. I tried 'optimizing' the code a little and noticed how slow the indicator becomes when i run the loop per buffer as opposed to all buffer in one loop. So i really need to find out how to make an array made of other arrays. Preferably a & not a copy. If anyone has any ideas, that would be fantastic. Thanks a lot for now

Here is an example using array of structure ...

#property strict
#property indicator_chart_window

#define MBufferCount 15

struct SBuffer {
   double m_dbBuffer[];
};

SBuffer oBuffers[ MBufferCount ];

int OnInit() {
   for( int i=0; i < MBufferCount; i++ )
      SetIndexBuffer( i, oBuffers[ i ].m_dbBuffer );
   return(INIT_SUCCEEDED);
};

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[] ) {
   double some_value = EMPTY_VALUE;
   for( int i = rates_total - ( ( prev_calculated < 1 ) ? 1 : prev_calculated ); i >= 0; i-- ) {
      for( int j = 0; j < MBufferCount; j++ ) {
         oBuffers[ j ].m_dbBuffer[ i ] = some_value;
      };
   };
   return rates_total;
};
 
@Fernando Carreiro Thanks very much for this ! That struct is new to me, and the way you posted this is super clear, thanks so much. Special thanks for that correction on my code for loop, where you are using this:
int i = rates_total - ( ( prev_calculated < 1 ) ? 1 : prev_calculated )
 Cheers!
 
Magneet #: Thanks very much for this ! That struct is new to me, and the way you posted this is super clear, thanks so much. Special thanks for that correction on my code for loop, where you are using this:  Cheers!
You are welcome!