Help with arrays and memory

 

From the diaries of the world's worst programmer

So I'm learning about arrays but not being very bright, struggling to understand how they actually populate themselves and how that affects memory allocation and resources.

I'm trying to build my own currency strength indicator. First step, build an indicator to measure an individual currency. I tested a few different algo's and came up with this;

//+------------------------------------------------------------------+
//|                                                         boom.mq4 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Strength
#property indicator_label1  "Strength"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      L_Period=21;
input int      TimeFrame=30;
//--- indicator buffers
double         StrengthBuffer[];
//--- internal arrays
double         LongCandle[],AbsCandle[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,StrengthBuffer);
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   ArrayResize(StrengthBuffer,Bars+L_Period,Bars+L_Period);
   ArrayResize(LongCandle,Bars+L_Period,Bars+L_Period);
   ArrayResize(AbsCandle,Bars+L_Period,Bars+L_Period);

   for(int i=0; i<rates_total; i++)  
    {
      {
       double Body     = MathAbs(iOpen(Symbol(),TimeFrame,i)-iClose(Symbol(),TimeFrame,i));
       double BodySize = Body/Point;

       if(BodySize==0.0) BodySize=0.01;

       if(iOpen(Symbol(),TimeFrame,i)<iClose(Symbol(),TimeFrame,i))  LongCandle[i]=BodySize;
       else LongCandle[i]=0.01;

       AbsCandle[i]=BodySize;
      }
     
      double deltalong = 0.0, deltaabs = 0.0;
   
      for(int cnt=i; cnt<(i+L_Period); cnt++)
       {
        deltalong=deltalong+LongCandle[cnt];
        deltaabs=deltaabs+AbsCandle[cnt];
       }   
    
      StrengthBuffer[i] = (deltalong/deltaabs)*10;
    }

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

 

 Seemed to work well off a live chart, however,in strategy tester, it slowed to stalling point.

 Didn't pay too much attention to this fact and moved to step two, gather data from multiple currency pairs. I came up with this basic indicator to be able to view that data.

//+------------------------------------------------------------------+
//|                                               Strength Meter.mq4 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots   6
//--- plot EURUSD
#property indicator_label1  "EURUSD"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot EURGPB
#property indicator_label2  "EURGPB"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot EURJPY
#property indicator_label3  "EURJPY"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrGreen
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot EURAUD
#property indicator_label4  "EURAUD"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrYellow
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1
//--- plot EURCAD
#property indicator_label5  "EURCAD"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrFuchsia
#property indicator_style5  STYLE_SOLID
#property indicator_width5  1
//--- plot EURNZD
#property indicator_label6  "EURNZD"
#property indicator_type6   DRAW_LINE
#property indicator_color6  clrLime
#property indicator_style6  STYLE_SOLID
#property indicator_width6  1
//--- input parameters
input int      Look_Back=96;
input int      TimeFrame=15;
//--- indicator buffers
double         EURUSDBuffer[];
double         EURGPBBuffer[];
double         EURJPYBuffer[];
double         EURAUDBuffer[];
double         EURCADBuffer[];
double         EURNZDBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,EURUSDBuffer);
   SetIndexBuffer(1,EURGPBBuffer);
   SetIndexBuffer(2,EURJPYBuffer);
   SetIndexBuffer(3,EURAUDBuffer);
   SetIndexBuffer(4,EURCADBuffer);
   SetIndexBuffer(5,EURNZDBuffer);
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   int limit;
   int counted_bars=IndicatorCounted();
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;

//---- calculate values
   for(int i=0; i<limit; i++)
    {
     EURUSDBuffer[i] = iCustom("EURUSD",TimeFrame,"boom v1.2",Look_Back,0,0,i);
     EURGPBBuffer[i] = iCustom("EURGBP",TimeFrame,"boom v1.2",Look_Back,0,0,i);
     EURJPYBuffer[i] = iCustom("EURJPY",TimeFrame,"boom v1.2",Look_Back,0,0,i);
     EURAUDBuffer[i] = iCustom("EURAUD",TimeFrame,"boom v1.2",Look_Back,0,0,i);
     EURCADBuffer[i] = iCustom("EURCAD",TimeFrame,"boom v1.2",Look_Back,0,0,i);
     EURNZDBuffer[i] = iCustom("EURNZD",TimeFrame,"boom v1.2",Look_Back,0,0,i);
    }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

 

So I applied it to a live chart and things started well. Looked to be collecting data exactly as desired. But it didn't take long before I notice my platform was starting to slow down before finally, the platform froze during the ECB conference. 

 

Hoping someone can tell me what happen and what I need to do to fix it.  

 
  1.    SetIndexBuffer(0,StrengthBuffer);
    :
       ArrayResize(StrengthBuffer,Bars+L_Period,Bars+L_Period);
    Do not resize buffers, they are already sized before the call. Make your other arrays non-visible buffers.

  2.    for(int i=0; i<rates_total; i++)  
    Why are you recalculating all bars every tick? That is why it "slowed to stalling point." Do your lookbacks correctly.
  3.    for(int i=0; i<rates_total; i++){
          :
           AbsCandle[i]=BodySize;
          :
          for(int cnt=i; cnt<(i+L_Period); cnt++){
            deltalong=deltalong+LongCandle[cnt];
            deltaabs=deltaabs+AbsCandle[cnt];
    You are calculating new bars first (not recommended) and at the same time looking at older values (which haven't been done.)
  4. for(int i=0; i<rates_total; i++){
       double Body     = MathAbs(iOpen(Symbol(),TimeFrame,i)-iClose(Symbol(),TimeFrame,i));
    You are mixing apples and oranges Fails if chart is not TimeFrame.
     EURUSDBuffer[i] = iCustom("EURUSD",TimeFrame,"boom v1.2",Look_Back,0,0,i);
 

Many thanks for your response. I've cleaned my mess up to look like this

//+------------------------------------------------------------------+
//|                                                         boom.mq4 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_level1     4
#property indicator_level2     4.8
#property indicator_level3     5
#property indicator_level4     5.2
#property indicator_level5     6
#property indicator_levelcolor clrWhite
#property indicator_levelstyle STYLE_DASHDOTDOT
//--- plot Strength
#property indicator_label1  "Strength"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
//--- input parameters
input int      L_Period=21;
//--- indicator buffers
double         StrengthBuffer[];
//--- internal arrays
double         LongCandle[],AbsCandle[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   IndicatorBuffers(3);
   SetIndexBuffer(0,StrengthBuffer);
   SetIndexBuffer(1,LongCandle);
   SetIndexBuffer(2,AbsCandle);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   for(int i=rates_total-1-MathMax(L_Period,prev_calculated); i>=0; --i)
     {
        {
         double Body     = MathAbs(iOpen(Symbol(),0,i)-iClose(Symbol(),0,i));
         double BodySize = Body/Point;

         if(BodySize==0.0) BodySize=0.01;

         if(iOpen(Symbol(),0,i)<iClose(Symbol(),0,i)) LongCandle[i]=BodySize;
         else LongCandle[i]=0.01;

         AbsCandle[i]=BodySize;
        }

      double deltalong=0.0,deltaabs=0.0;

      for(int cnt=i+L_Period; cnt>=i; cnt--)
        {
         deltalong=deltalong+LongCandle[cnt];
         deltaabs=deltaabs+AbsCandle[cnt];
        }

      StrengthBuffer[i]=(deltalong/deltaabs)*10;
     }
//--- return value of prev_calculated for next call
   return(rates_total-1);
  }
//+------------------------------------------------------------------+

 

Hope that's got the right  count and taken the oranges out. Seems to work smoothly in ST.

 
  1. Why use function calls when you can use the Predefined Variables - MQL4 Reference
    if(iOpen(Symbol(),0,i)<iClose(Symbol(),0,i))
    if(Open[i] < Close[i])
  2. Are you sure you want to sum L_Period + 1 values?
    for(int cnt=i+L_Period; cnt>=i; cnt--)
 
WHRoeder:
  1. Why use function calls when you can use the Predefined Variables - MQL4 Reference
  2. Are you sure you want to sum L_Period + 1 values?
1) is because I'm the worst programmer ever and 2) is proof. Thanks for taking the time to help.