Create Auto-Shifting Arrays

 

My understanding is that Constants such as Open[], Close[], etc. automatically shift right each time a new bar is created.

As does and Double Array that you designate as an indicator buffer.

My question is, can you declare your own arrays that will automatically shift in the same way?

So that you can store calculations for each bar and have it stay in sync.

This seems like a very obvious thing that you would want to do, yet I can find no reference to it.

Is it built in to the API?

 
LaurenceRietdijk:

My understanding is that Constants such as Open[], Close[], etc. automatically shift right each time a new bar is created.

As does and Double Array that you designate as an indicator buffer.

My question is, can you declare your own arrays that will automatically shift in the same way?

So that you can store calculations for each bar and have it stay in sync.

You can do that in Indicators. But not in Experts.

 
LaurenceRietdijk: My question is, can you declare your own arrays that will automatically shift in the same way?
Indicators have buffers which automatically shift. Arrays do not automatically do anything. You must do it yourself in EA.
          Array indexing and resizing an AS_SERIES array - Indexes - MQL4 and MetaTrader 4 - MQL4 programming forum
 

You can easily create a custom collection to auto-shift. Here is an example of one. 

#property strict
#property indicator_chart_window

#include <Arrays\ArrayObj.mqh>

template<typename T>
class CAutoShiftArray : public CObject
{
protected:
   class CData : public CObject
   {
   public:
      CData(const datetime t):data(NULL),time_stamp(t){}
      datetime time_stamp;
      T        data;
      virtual int Compare(const CObject *node,const int mode=0)const override
      {
         const CData *other = node;
         if(this.time_stamp > other.time_stamp) return -1;
         if(this.time_stamp < other.time_stamp) return 1;
         return 0;
      }
   };
   CArrayObj   m_array;
public:
   CAutoShiftArray()
   {
      int total = ArraySize(Time);
      m_array.Reserve(total);
      for(int i = 0;i < total; i++)
         m_array.Add(new CData(Time[i]));
   }     
   /********************
   only two public methods for access Get/Set
   *********************/
   T Get(const int index)
   {
      _AlignCollection();
      CData *res = m_array.At(index);
      if(!CheckPointer(res))
         printf("Collection out of range error (GET)!");
      return res.data;
   }
   void Set(const int index, const T data)
   {
      _AlignCollection();
      CData *res = m_array.At(index);
      if(!CheckPointer(res))
         printf("Collection out of range error (SET)!");
      res.data = data;
   }
   // verify collection alignment with Time[]
   bool VerifyAlignment()
   {
      int total = ArraySize(Time);
      for(int i=0;i<total;i++)
         if(Time[i] != ((CData*)m_array.At(i)).time_stamp)
            return false;
      return true;
   }
   /*********************/
protected:
   void _AlignCollection()
   {
      if(m_array.Total() > 0 && ((CData*)m_array.At(0)).time_stamp == Time[0])
         return;
      int total = ArraySize(Time);
      m_array.Sort();
      for(int i=0;i<total;i++)
      {
         CData *data = new CData(Time[i]);
         if(m_array.Search(data) < 0)
            m_array.InsertSort(data);
         else
         {
            delete data;
            break;
         }
      }
   }
};

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
//---
   CAutoShiftArray<double> close_prices;
   for(int i=0;i<ArraySize(Time);i++)
      close_prices.Set(i,Close[i]);
      
   string comm;   
   for(int i=0;i<10;i++)
   {
      comm+=StringFormat(  "Close[%s] @ %s\n",
                           DoubleToString(close_prices.Get(i),_Digits), 
                           TimeToString(Time[i]));
   }

   ulong ms = GetMicrosecondCount();
   string status = string(close_prices.VerifyAlignment());
   comm+=StringFormat("Collection verification status [%s] in %d ms.",status,(GetMicrosecondCount()-ms)/1000);
//--- return value of prev_calculated for next call

   Comment(comm);
   return(0);
  }

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(){ return(INIT_SUCCEEDED); }