ArraySetAsSeries

 

I know I have asked about this before on the mql4 forum but never got to the bottom of it.

From the documentatin:  Arrays of price data passed as input parameters into the OnCalculate() function do not obligatorily have the indexing direction the same as in timeseries. The necessary indexing direction can be set using the ArraySetAsSeries() function.

I am confused by this information, how can an array's indexing direction be uncertain ?  This could mean one of several things, assume array has 1,000 values.

  1. The array was initially set as series and the data entered in the correct order so the most recent value is in the zero index
  2. The array was initially set as series and the data entered in reverse order so the most recent value is in the 999 index
  3. The array was NOT initially set as series and the data entered in the correct order so the most recent value is in the zero index
  4. The array was NOT initially set as series and the data entered in reverse order so the most recent value is the the 999 index
  5. The array was initially in one state, data entered in correct order and then series reversed before we get to access it therefore data is now reversed and indexing should be reversed.
  6. The array was initially in one state, data entered in reverse order and then series is reversed before we access it, therefore data is now correct and indexing should not be changed

My point is this if the indexing is uncertain, and we assume SetAsSeries() should be false, if we therefore set it to false and the array state was scenario 1 we would be reversing the array and all the data would be in the wrong indexes. But if the initial state of the array was scenario 2 and we set it to false, things would be correct, so how do we know which it is ?

The only way that could work is we would have to KNOW, that if the array was set as true the data is reversed in the array. This could happen if the array was initially set as false when the data is entered in the correct order and then the array is changed to true before we access it, OR the array was set as true to begin with and the data was all entered in reverse. Why should any of those things be an uncertainty ? Things do not happen at random unless they are coded to happen at random.

A similar thing would happen in scenario 3 and 4, except this time we would have to know if the array was set as false,  the data was in the correct direction to begin with.

This is why I do not understand, how can an array indexing be uncertain to begin with ? Or am I totally missing something about this ?

It seems to me even MQ own coders are not sure about this, while looking through the included MQ indicator codes for guidance I see some of them set both the Indicator Buffers and the Price arrays to false (ATR, CCI, Heiken Ashi) , some call  ArrayGetAsSeries snd then set the price arrays to false only if they were true to begin with (Moving Averages) and some just use the price arrays and indicator buffers "as is" (Accumulation, Bears, Bulls, Momentum)

 
SDC:

By default, the array indexing time series is set true.

 

But for secure better call the ArraySetAsSeries () 

 

yes they are true when i call them by ArrayGetAsSeries() and we know the zero index contains the latest value. But then look at the src code for ATR and other indicators,

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[])
  {
   int i,limit;
//--- check for bars count and input parameter
   if(rates_total<=InpAtrPeriod || InpAtrPeriod<=0)
      return(0);
//--- counting from 0 to rates_total
   ArraySetAsSeries(ExtATRBuffer,false);
   ArraySetAsSeries(ExtTRBuffer,false);
   ArraySetAsSeries(open,false);
   ArraySetAsSeries(high,false);
   ArraySetAsSeries(low,false);
   ArraySetAsSeries(close,false);
//--- preliminary calculations
   if(prev_calculated==0)
     {
      ExtTRBuffer[0]=0.0;
      ExtATRBuffer[0]=0.0;
      //--- filling out the array of True Range values for each period
      for(i=1; i<rates_total; i++)
         ExtTRBuffer[i]=MathMax(high[i],close[i-1])-MathMin(low[i],close[i-1]);

Price arrays series are changed to false, this means their oldest values would now be in the zero indexes and the most recent in the highest indexes ? Why do MQ coders do that sometimes but not all the time ? In some other indicators they just use the price arrays as they are already.

The buffers series are also set to false but how is that relevent ? The values are entered into the buffer explicitly by index, so what difference is it going to make which way the buffers are indexed ? Zero index is Zero index no matter how you slice it.

Edit: I am now thinking the buffer array must be automatically reset back to true before it is drawn therfore re-reversing the whole thing. That is the only way the ATR and other MQ indicators coded as above could work. This is so frustrating, so much time taken to figure out what should be standard documentation. It still does not explain the original issue of ambiguous indexing of the arrays, if the price array was false to begin with and the data was entered correctly so most recent value is in the lowest index, the above code would not work properly.  The re-reversal of the buffers before they are drawn would screw it all up. I dont see how we can work with those arrays when the initial indexing is uncertain and why should it even be uncertain in the first place ? Things dont just randomly happen unless they are coded to randomly happen.

 
SDC:

yes they are true when i call them by ArrayGetAsSeries() and we know the zero index contains the latest value. But then look at the src code for ATR and other indicators,

Price arrays series are changed to false, this means their oldest values would now be in the zero indexes and the most recent in the highest indexes ? Why do MQ coders do that sometimes but not all the time ? In some other indicators they just use the price arrays as they are already.

The buffers series are also set to false but how is that relevent ? The values are entered into the buffer explicitly by index, so what difference is it going to make which way the buffers are indexed ? Zero index is Zero index no matter how you slice it.

Edit: I am now thinking the buffer array must be automatically reset back to true before it is drawn therfore re-reversing the whole thing. That is the only way the ATR coded as above could work. This is so frustrating, so much time taken to figure out what should be standard documentation. It still does not explain the original issue of ambiguous indexing of the arrays, if the price array was false to begin with and the data was entered correctly so most recent value is in the lowest index, the above code would not work properly.  The re-reversal of the buffers before they are drawn would screw it all up. I dont see how we can work with those arrays when the initial indexing is uncertain and why should it even be uncertain in the first place ? Things dont just randomly happen unless they are coded to randomly happen.

Show your code function int OnInit ().
 
Fleder:
Show your code function int OnInit ().


The code I posted above is not my code it is from the ATR src code included with the MT4 terminal. There is nothing unusual about its OnInit() function.

int OnInit(void)
  {
   string short_name;
//--- 1 additional buffer used for counting.
   IndicatorBuffers(2);
   IndicatorDigits(Digits);
//--- indicator line
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtATRBuffer);
   SetIndexBuffer(1,ExtTRBuffer);
//--- name for DataWindow and indicator subwindow label
   short_name="ATR("+IntegerToString(InpAtrPeriod)+")";
   IndicatorShortName(short_name);
   SetIndexLabel(0,short_name);
//--- check for input parameter
   if(InpAtrPeriod<=0)
     {
      Print("Wrong input parameter ATR Period=",InpAtrPeriod);
      return(INIT_FAILED);
     }
//---
   SetIndexDrawBegin(0,InpAtrPeriod);
//---
   return(INIT_SUCCEEDED);
  }
 
SDC:


The code I posted above is not my code it is from the ATR src code included with the MT4 terminal. There is nothing unusual about its OnInit() function.

Indexing direction for MQL4 and MQL5 differ.
 

The mql5 docs say the same thing about the OnCalculate arrays as the mql4 docs. That is why I posted about this here, I figured the mql5 guys been working with them for longer so might understand this issue better.

In order not to depend on the default values, you must unconditionally call the ArraySetAsSeries() function for those arrays, that are expected to work with.

Event Handling Functions - MQL4 Documentation
  • docs.mql4.com
Event Handling Functions - MQL4 Documentation
 

The documentation for MQL5:

Note

After binding, the dynamic array buffer[] will be indexed as in common arrays, even if the indexing of timeseries is pre-installed for the bound array. If you want to change the order of access to elements of the indicator array, use theArraySetAsSeries() function after binding the array using the SetIndexBuffer() function. Please note that you can't change the size for dynamic arrays set as indicator buffers by the function SetIndexBuffer(). For indicator buffers, all operations of size changes are performed by the executing sub-system of the terminal.

 
int OnInit(void)
  {
   string short_name;
//--- 1 additional buffer used for counting.
   IndicatorBuffers(2);
   IndicatorDigits(Digits);
//--- indicator line
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtATRBuffer);
   SetIndexBuffer(1,ExtTRBuffer);
   ArraySetAsSeries(ExtATRBuffer,true);
   ArraySetAsSeries(ExtATRBuffer,true);
//--- name for DataWindow and indicator subwindow label
   short_name="ATR("+IntegerToString(InpAtrPeriod)+")";
   IndicatorShortName(short_name);
   SetIndexLabel(0,short_name);
//--- check for input parameter
   if(InpAtrPeriod<=0)
     {
      Print("Wrong input parameter ATR Period=",InpAtrPeriod);
      return(INIT_FAILED);
     }
//---
   SetIndexDrawBegin(0,InpAtrPeriod);
//---
   return(INIT_SUCCEEDED);
  }
 

Where did you get that code ? It is different to mine.

 
SDC:

Where did you get that code ? It is different to mine.

I just added to it a couple of functions.
Reason: