Need help to limit the duration of the indicator to a single day..

 

Hey, guys!

I want to do some backtesting, but the indicator I'm studying gets very heavy and slow.

If I put it on April 2018, It will be shown from there until today. Therefore, it has to use a lot of memory and time to calculate all these data.

How can I limit it so it will be shown day by day?

Here is the code:

//+------------------------------------------------------------------+
//|                                         VWAP_Custom_Position.mq5 |
//|                                           José Ricardo Magalhães |
//|                                            joserrrm@yahoo.com.br |
//+------------------------------------------------------------------+
#property copyright "José Ricardo Magalhães"
#property link      "joserrrm@yahoo.com.br"
#property version   "1.02"
#property description "The indicator calculates standard VWAP (Volume Weighted Average Price) line"
#property description "The start point is defined by the (movable) ARROW created on chart."
#property description " "
#property description "Purpose: Identify the players average price from a certain point in time"
#property description " "
#property description "# IMPORTANT: Each line must have a unique ID #"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot vwap
#property indicator_label1  "VWAP Custom"
#property indicator_type1   DRAW_SECTION
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
//---
enum PRICE_METHOD
  {
   Close,
   Open,
   High,
   Low,
   Median,  // Median Price (HL/2)
   Typical, // Typical Price (HLC/3)
   Weighted // Weighted Close (HLCC/4)
  };
//--- input parameters
input string            vwapID    = "04";       // VWAP ID   ( must be unique )
input PRICE_METHOD      Method    = Low;    // Price Calculation Method
input color             vwapColor = Blue;    // VWAP Color
input int               arrowSize = 3;          // Arrow Size
input ENUM_ARROW_ANCHOR Anchor    = ANCHOR_TOP; // Arrow Anchor Point
//--- indicator buffers
double         vwapBuffer[];
//--- global variables
int            startVWAP;
string         Prefix;
string         indicator_name;
int            iRatesTotal;
datetime       iTime[];
double         iOpen[],iHigh[],iLow[],iClose[],iVolume[];
long           obj_time;
bool           first=true;
int            counter=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
// indicator buffers mapping
   SetIndexBuffer(0,vwapBuffer,INDICATOR_DATA);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,vwapColor);
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
   indicator_name="VWAP_Custom_Position_"+IntegerToString(MathRand()/32);
   IndicatorSetString(INDICATOR_SHORTNAME,indicator_name);
   Prefix="Obj_"+vwapID;
// Testa a existência do Objeto
   if(ObjectFind(0,Prefix)==0)
     {
      if(CheckGlobalVariable(1)=="NO" && CheckGlobalVariable(2)=="NO") return(INIT_FAILED);
      else
        {
         DeleteGlobalVariable(1);
         DeleteGlobalVariable(2);
         return(INIT_SUCCEEDED);
        }
     }
   else return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator Deinitialization function                       |
//+------------------------------------------------------------------+     
void OnDeinit(const int reason)
  {
   if(reason==REASON_PARAMETERS || reason==REASON_CHARTCHANGE) CreateGlobalVariable(1);
   if(reason==REASON_CLOSE) CreateGlobalVariable(2);
   if(reason==REASON_REMOVE || reason==REASON_CHARTCLOSE || reason==REASON_TEMPLATE)
     {
      ObjectsDeleteAll(0,Prefix);
      ChartRedraw(0);
     }
   if(reason==REASON_INITFAILED)
     {
      Print("ERROR: Object '",Prefix,"' already exists in chart. Delete object before insert the indicator");
      ChartIndicatorDelete(0,0,indicator_name);
     }
  }
//+------------------------------------------------------------------+
//| Custom indicator Chart Event function                            |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
   if(sparam==Prefix) EventSetMillisecondTimer(100);
   else EventKillTimer();
  }
//+------------------------------------------------------------------+
//| Custom indicator TIMER function                                  |
//+------------------------------------------------------------------+
void OnTimer()
  {
// Identifica a posição horizontal do objeto   
   obj_time = ObjectGetInteger(0,Prefix,OBJPROP_TIME);
   for(int i=iRatesTotal-1; i>0; i--) { if(obj_time>=(long)iTime[i]) {startVWAP=i; break;} }
// Zera a VWAP
   ArrayInitialize(vwapBuffer,0.0);
// Refaz a VWAP
   CalculateVWAP();
  }
//+------------------------------------------------------------------+
//| 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[])
  {
// Inicializa os Buffers
   if(first)
     {
      ArrayResize(iTime,  (int)(1.5*rates_total),(int)(rates_total/5));
      ArrayResize(iOpen,  (int)(1.5*rates_total),(int)(rates_total/5));
      ArrayResize(iHigh,  (int)(1.5*rates_total),(int)(rates_total/5));
      ArrayResize(iLow,   (int)(1.5*rates_total),(int)(rates_total/5));
      ArrayResize(iClose, (int)(1.5*rates_total),(int)(rates_total/5));
      ArrayResize(iVolume,(int)(1.5*rates_total),(int)(rates_total/5));
      ArrayInitialize(vwapBuffer,0.0);
      ArrayInitialize(iTime,0.0);
      ArrayInitialize(iOpen,0.0);
      ArrayInitialize(iHigh,0.0);
      ArrayInitialize(iLow,0.0);
      ArrayInitialize(iClose,0.0);
      ArrayInitialize(iVolume,0.0);
     }
// Carrega os vetores de preço
   counter=first ? 0 : MathMax(prev_calculated-1,0);
   for(int i=counter; i<rates_total; i++)
     {
      iRatesTotal=rates_total;
      iTime[i]=time[i];
      iOpen[i]=open[i];
      iHigh[i]=high[i];
      iLow[i]=low[i];
      iClose[i]=close[i];
      iVolume[i]=(double)volume[i];
     }
// Criação do Objeto Referência
   if(ObjectFind(0,Prefix)!=0) CreateObject();
// Parâmetros customizaveis do Objeto Referência
   if(first) CustomizeObject();
// Identifica a posição horizontal do objeto   
   obj_time=ObjectGetInteger(0,Prefix,OBJPROP_TIME);
   if(prev_calculated>rates_total || first)
     {
      for(int i=iRatesTotal-1; i>0; i--) { if(obj_time>=(long)iTime[i]) {startVWAP=i; break;} }
      if(startVWAP>=1)
        {
         // Verifica se há dados no buffer da vwap à esquerda do objeto. Caso positivo zera o buffer
         if(vwapBuffer[startVWAP-1]!=0) ArrayInitialize(vwapBuffer,0.0);
         // Calcula a VWAP
         CalculateVWAP();
        }
      PrintFormat("in - %i - %i",prev_calculated,rates_total);
      first=false;
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+
void CalculateVWAP()
  {
// Calcula a VWAP
Print("calc");
   double sumPrice=0,sumVol=0;
   for(int i=startVWAP; i<iRatesTotal; i++)
     {
      sumPrice    += Price(iOpen,iHigh,iLow,iClose,i)*iVolume[i];
      sumVol      += iVolume[i];
      vwapBuffer[i]= sumPrice/sumVol;
     }
  }
//+------------------------------------------------------------------+
double Price(const double &open[],
             const double &high[],
             const double &low[],
             const double &close[],
             int          index)
  {
   double output;
   if(Method==Open) output=open[index];
   else if(Method==High)     output=high[index];
   else if(Method==Low)      output=low[index];
   else if(Method==Median)   output=(high[index]+low[index])/2;
   else if(Method==Typical)  output=(high[index]+low[index]+close[index])/3;
   else if(Method==Weighted) output=(high[index]+low[index]+close[index]+close[index])/4;
   else                      output=close[index];
   return(output);
  }
//+------------------------------------------------------------------+
void CreateObject()
  {
   int      offset=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR) -(int)ChartGetInteger(0,CHART_WIDTH_IN_BARS)/2;
   datetime Hposition=iTime[iRatesTotal-offset];
   double   Vposition;
   if(Anchor==ANCHOR_TOP) Vposition=iLow[iRatesTotal-offset];
   else                   Vposition=iHigh[iRatesTotal-offset];

   ObjectCreate(0,Prefix,OBJ_ARROW,0,Hposition,Vposition);
//--- Código Wingdings 
   ObjectSetInteger(0,Prefix,OBJPROP_ARROWCODE,233);
//--- definir o estilo da linha da borda 
   ObjectSetInteger(0,Prefix,OBJPROP_STYLE,STYLE_DOT);
   ObjectSetInteger(0,Prefix,OBJPROP_FILL,false);
//--- exibir em primeiro plano (false) ou fundo (true) 
   ObjectSetInteger(0,Prefix,OBJPROP_BACK,false);
//--- permitir (true) ou desabilitar (false) o modo de movimento do sinal com o mouse 
//--- ao criar um objeto gráfico usando a função ObjectCreate, o objeto não pode ser 
//--- destacado e movimentado por padrão. Dentro deste método, o parâmetro de seleção 
//--- é verdade por padrão, tornando possível destacar e mover o objeto 
   ObjectSetInteger(0,Prefix,OBJPROP_SELECTABLE,true);
//--- ocultar (true) ou exibir (false) o nome do objeto gráfico na lista de objeto  
   ObjectSetInteger(0,Prefix,OBJPROP_HIDDEN,false);
//--- definir a prioridade para receber o evento com um clique do mouse no gráfico 
   ObjectSetInteger(0,Prefix,OBJPROP_ZORDER,100);
   ObjectSetInteger(0,Prefix,OBJPROP_FILL,true);
  }
//+------------------------------------------------------------------+
void CustomizeObject()
  {
//--- Tamanho do objeto
   ObjectSetInteger(0,Prefix,OBJPROP_WIDTH,arrowSize);
//--- Cor
   ObjectSetInteger(0,Prefix,OBJPROP_COLOR,vwapColor);
//--- Código Wingdings
   if(Anchor==ANCHOR_TOP)    ObjectSetInteger(0,Prefix,OBJPROP_ARROWCODE,233);
   if(Anchor==ANCHOR_BOTTOM) ObjectSetInteger(0,Prefix,OBJPROP_ARROWCODE,234);
//--- Ponto de Ancoragem
   ObjectSetInteger(0,Prefix,OBJPROP_ANCHOR,Anchor);
   ObjectSetInteger(0,Prefix,OBJPROP_SELECTED,true);
  }
//+------------------------------------------------------------------+
void CreateGlobalVariable(int type)
  {
   string gVarProp = "_VWAP_is_editing_"+Prefix;
   string gVarExit = "_VWAP_exists_"+Prefix+"_"+_Symbol+"_M"+IntegerToString(_Period)+"_";
//---
   if(type==1) GlobalVariableSet(gVarProp,1);
   else
     {
      for(int i=1; i<100; i++)
        {
         if(!GlobalVariableCheck(gVarExit+IntegerToString(i)))
           {
            GlobalVariableSet(gVarExit+IntegerToString(i),1);
            break;
           }
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string CheckGlobalVariable(int type)
  {
   string answer;
   string gVarProp = "_VWAP_is_editing_"+Prefix;
   string gVarExit = "_VWAP_exists_"+Prefix+"_"+_Symbol+"_M"+IntegerToString(_Period)+"_";
//---
   if(type==1) answer=GlobalVariableCheck(gVarProp) ? "YES" : "NO";
   else
     {
      answer="NO";
      for(int i=1; i<100; i++)
        {
         if(GlobalVariableCheck(gVarExit+IntegerToString(i)))
           {
            answer=gVarExit+IntegerToString(i);
            break;
           }
        }
     }
   return(answer);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DeleteGlobalVariable(int type)
  {
   string gVarProp = "_VWAP_is_editing_"+Prefix;
   string gVarExit = "_VWAP_exists_"+Prefix+"_"+_Symbol+"_M"+IntegerToString(_Period)+"_";
//---
   if(type==1) {if(GlobalVariableCheck(gVarProp)) GlobalVariableDel(gVarProp);}
   else
     {
      for(int i=1; i<100; i++)
        {
         if(GlobalVariableCheck(gVarExit+IntegerToString(i)))
           {
            GlobalVariableDel(gVarExit+IntegerToString(i));
            break;
           }
        }
     }
  }
//+------------------------------------------------------------------+
 

Joás Bezerra:

If I put it on April 2018, It will be shown from there until today.

Therefore, it has to use a lot of memory and time to calculate all these data.

  1.       for(int i=iRatesTotal-1; i>0; i--) { if(obj_time>=(long)iTime[i]) {startVWAP=i; break;} }
    
    You calculate all bars, not just from when. Calculate only what has changed.
              How to do your lookbacks correctly.

  2. You have seven (7) arrays. If you have 5000 bars, that takes 7*5000*8 or 274 KB (on a 4 million KB machine.) What do you mean it "use a lot of memory?" As for time, see #1

  3. You resize your arrays on the first tick only. Therefor once you exceed 1.5 original bar count you fail with array exceeded. You would know that if you had used strict.
    Always use strict. Fixing the warnings will save you hours of debugging.
              Program Properties (#property) - Preprocessor - Language Basics - MQL4 Reference

  4. Why do you initialize your arrays to zero when the next thing you do is fill them?

  5. Why are you filling those arrays? On MT5 you can use copyX routines and take no memory (except for the buffer.) On MT4 you don't need them at all, use the predefined arrays, no filling required.

  6.    else if(Method==High)     
       else if(Method==Low)      
       else if(Method==Median)   
       else if(Method==Typical)  
       else if(Method==Weighted)
    Multiple tests, use switch.