multiple INDICATOR_DATA flagged buffers involve CopyBuffer error ?

 

Hi, (I apologize in advance if this isn't the right section) so following the SL dev. guidelines have a very simple indicator like this :

//--- indicator buffers
double         BufferA[];
double         BufferB[];
double         BufferC[];

static int counter=0; // for test purpose only

//+------------------------------------------------------------------+
//| indicator initialization function                        |
//+------------------------------------------------------------------+
int OnInit()
{
   SetIndexBuffer(0, BufferA, INDICATOR_DATA);
   SetIndexBuffer(1, BufferB, INDICATOR_DATA);
   SetIndexBuffer(2, BufferC, INDICATOR_CALCULATIONS);
}
//+------------------------------------------------------------------+
//| 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[])
{

   if(rates_total<1) return(0);
    
   //--- get current position
   int pos=prev_calculated-1;
   if(pos<0) pos=0;

   //--- main cycle
   for(int i=pos;i<rates_total && !IsStopped();i++){
      BufferA[i]=++counter;
      BufferB[i]=counter;
      BufferC[i]=counter;
   }

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

and have a standard EA like this :

TestExpert EA;

//----------------------- "Init" event handler function ---
int OnInit()
{

   if(!TerminalInfoInteger(TERMINAL_CONNECTED))
        return(INIT_FAILED);

   if(!EA.Init(Symbol(), Period(), Expert_EveryTick, Expert_MagicNumber)) {
        EA.Deinit(); return(INIT_FAILED);
   }   
   // Creating signal/strategy manager
   //

   CExpertSignal *signal=new CExpertSignal;
   if(signal==NULL){
        EA.Deinit(); return(INIT_FAILED);
   }
   
   EA.InitSignal(signal);
   signal.ThresholdOpen(Signal_ThresholdOpen);
   signal.ThresholdClose(Signal_ThresholdClose);
   signal.PriceLevel(Signal_PriceLevel);
   signal.StopLevel(Signal_StopLevel);
   signal.TakeLevel(Signal_TakeLevel);
   signal.Expiration(Signal_Expiration);


   TestSignal *filter0=new TestSignal;
   if(filter0==NULL){
        EA.Deinit(); return(INIT_FAILED);
   }
   EA.SetTestSignal(filter0);
   signal.AddFilter(filter0);
   // Set filter/strategy parameters
   
   // Creation of trailing object
   CTrailingNone *trailing=new CTrailingNone;
   if(trailing==NULL){
	EA.Deinit(); return(INIT_FAILED);
   }
   // Add trailing to expert (will be deleted automatically))
   //
   if(!EA.InitTrailing(trailing)){
	EA.Deinit(); return(INIT_FAILED);
   }
   // Set trailing parameters...
   
   //Creation of money object
   CMoneyFixedLot *money=new CMoneyFixedLot;
   if(money==NULL){
	EA.Deinit(); return(INIT_FAILED);
   }
   // Add money to expert (will be deleted automatically))
   //
   if(!EA.InitMoney(money)){
	EA.Deinit(); return(INIT_FAILED);
   }
   // Set money parameters
   //
   money.Percent(Money_FixLot_Percent);
   money.Lots(Money_FixLot_Lots);
   
   // Check all trading objects parameters   
   //
   if(!EA.ValidationSettings()){
      EA.Deinit(); return(INIT_FAILED);
   }
   // Tuning of all necessary indicators
   //
   if(!EA.InitIndicators()){
      EA.Deinit(); return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}

and :

inside the TestExpert class have a private member of TestSignal class (m_testsignal)

inside the TestSignal class have another private member of TestIndicator class (m_testindicator)

derive TestIndicator class from CiCustom in a standard manner, like those on Trend/Volumes/BillWilliams, don't use the Initialize virtual methods for creation instead use this :

bool TestSignal::InitIndicators(CIndicators *indicators)
  {
   if(indicators==NULL)
      return false;
   //--- initialization of indicators and timeseries of additional filters
   if(!CExpertSignal::InitIndicators(indicators))
      return false;
   if(!InitTestIndicator(indicators))
      return false;

   return true;
  }


bool TestSignal::InitTestIndicator(CIndicators *indicators)
  {
   if(indicators==NULL)
      return false;
   if(!indicators.Add(GetPointer(m_testindicator))){
      return false;
     }
   MqlParam p[1];
   p[0].type            = TYPE_STRING;
   p[0].string_value    = "test_indicator.ex5";
   
   if(!m_testindicator.NumBuffers(3)){
      return false;
   }   
   if(!m_testindicator.Create(_Symbol, _Period, IND_CUSTOM, 1, p)){ 
      return false;
     }
   return true;
  } 


  

add a method TestIndicator.Update() that call this.GetData(0, items, buffer_index, buffer_target) for every indicator buffer,

so now call m_testsignal.Update() {call m_testindicator.Update()} from EA.Processing(), 

What I have see is that GetData/Copybuffer aren't able to get the right data if you have more than one INDICATOR_DATA flagged buffers, they return a bad -1 derived from 4806 for all the INDICATOR_DATA flagged buffers except the first one.

(at this point I realized that maybe you can replicate the same error in a much more simple way...)

Ok it can be solved having just one buffer flagged as INDICATOR_DATA, but I don't think this was the purpose of the standard library, right ? 

Documentation on MQL5: Standard Library
Documentation on MQL5: Standard Library
  • www.mql5.com
MQL5 Standard Library is written in MQL5 and is designed to facilitate writing programs (indicators, scripts, experts) for end users. Library provides convenient access to the most of the internal MQL5 functions.
Reason: