Using ArrayResize

 

Hi,

I have the code below. It checks if price broke above a Donchian channel and then retraced for a number of bars. When I hard-code the integer into my dcVals array things work as expected. It only prints exactly when the channel was broken and 5 bars retraced.

But when I use a variable, DC_BARS, things are different. It triggers at the time I want like when hard-coded, but continues to give false triggers because dcVals[6] evaluates to 0.0 for some reason. Any idea what I'm doing wrong? P.S. Is there a better way to copy a range of indicator values into an ea?

Thanks.

Edit: This is the Donchian indicator that I used: https://www.mql5.com/en/code/8965


#property version   "1.00"
#property strict

int DC_BARS = 7;

int OnInit(){
    return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason){
}

void OnTick(){
    if(newCandleStarted()){
        double dcVals[7];             //<- This works
        //double dcVals[];              <- This doesn't work
        //ArrayResize[dcVals, DC_BARS]; <- This doesn't work
        for(int i=0; i<7; i++){
            dcVals[i] = iCustom(_Symbol, PERIOD_H1, "Donchian", 0, i+1);

        if(dcVals[6] < dcVals[5] &&
           dcVals[5] == dcVals[0])
                Print(dcVals[6], " ==== enter here ==== ", dcVals[0]);
        }
    }
}

int newCandleStarted(){
    // https://www.youtube.com/watch?v=BGCQkf8GjIo
    MqlRates priceData[];
    ArraySetAsSeries(priceData, true);
    CopyRates(_Symbol, _Period, 0, 3, priceData);

    static datetime timeStampLastCheck;
    datetime timeStampCurrentCandle;
    timeStampCurrentCandle = priceData[0].time;
    
    if(timeStampCurrentCandle != timeStampLastCheck){
        timeStampLastCheck = timeStampCurrentCandle;
        return True;
    }
    else return False;
}
Donchian Channel Indicator
Donchian Channel Indicator
  • www.mql5.com
HardLevels Shows important support / resistance levels from different timeframes. Advanced filtering included. Harami Just a configurable Bear & Bull "Harami" pattern finder. TD Sequential TD Sequential indicator based off of the...
 

Hello friend,

I haven't used arrayresize before, but I noticed the some declarations might be incorrect. MQL4 Manual.

int  ArrayResize( 
   void&  array[],              // array passed by reference 
   int    new_size,             // new array size 
   int    reserve_size=0        // reserve size value (excess) 
   );

and your code

void OnTick(){
    if(newCandleStarted()){
        double dcVals[7];             //<- This works
        //double dcVals[];              <- This doesn't work
        //ArrayResize[dcVals, DC_BARS]; <- This doesn't work
        for(int i=0; i<7; i++){
            dcVals[i] = iCustom(_Symbol, PERIOD_H1, "Donchian", 0, i+1);

        if(dcVals[6] < dcVals[5] &&
           dcVals[5] == dcVals[0])
                Print(dcVals[6], " ==== enter here ==== ", dcVals[0]);
        }
    }
}
 

Not tested, but it did compile.

double dcVals[];
   int new_size=7,reserve_size=10;
int NewArray =ArrayResize( dcVals,new_size,reserve_size); 
 

Oops, the square brackets are a typo :/ but with parentheses like in reply #2 I get the problem I described. The reserved size parameter doesn't make any difference. Here is some example output:

2019.02.03 11:09:50.892 2019.01.17 07:00:00  don_break EURGBP,H1: 0.0 ==== enter here ==== 0.88791
2019.02.03 11:09:50.891 2019.01.17 06:00:00  don_break EURGBP,H1: 0.0 ==== enter here ==== 0.88791
2019.02.03 11:09:50.891 2019.01.17 05:00:00  don_break EURGBP,H1: 0.0 ==== enter here ==== 0.88791
2019.02.03 11:09:50.890 2019.01.17 04:00:00  don_break EURGBP,H1: 0.0 ==== enter here ==== 0.88791
2019.02.03 11:09:50.889 2019.01.17 03:00:00  don_break EURGBP,H1: 0.0 ==== enter here ==== 0.88791
2019.02.03 11:09:50.888 2019.01.17 02:00:00  don_break EURGBP,H1: 0.88785 ==== enter here ==== 0.88791
 

Doh, it was braces fail. The for loop should not include the if statement. This is resolved, thanks.

 

Congratulations,

Try Alert(); instead of Print();

Myself, I like to know the problem quickly, without finding the log files.

 

Hello friend,

Shouldn't it just be (, i );  I'm on where near an expert, but ( +1 ) isn't declared as (int). so it may be omitted from the dcVal[ i ]

        for(int i=0; i<7; i++){
            dcVals[i] = iCustom(_Symbol, PERIOD_H1, "Donchian", 0, i+1);
 

Hi Grumpy,

I'm not entirely sure what you mean but I have +1 in iCustom because I only want to consider closed bars. Though something like this might work:

int DC_BARS = 8;

...

    for(int i=1; i<DC_BARS; i++)
        maxVals[i] = iCustom(_Symbol, PERIOD_H1, "Donchian", 0, i);
 

When you specify an array[size] you are declaring it as a static array, and the number of elements that you initialize it with are all that will ever be for the life of the variable. Also, the declaration requires a constant integer, so you cannot not use a variable. 

Static:

int arr[6]; //ok

#define SIZE 6
int arr[SIZE]; //ok

int size = 6;
int arr[size]; //NO!


Dynamic:

int arr[];
ArrayResize(arr, 6);



If don't need to pass the array to any MQL functions then you should use the standard library vector collections. 

#property version   "1.00"
#property strict
#include <arrays/arraydouble.mqh>

int OnInit()
{
    return(INIT_SUCCEEDED);
}

void OnTick()
{
   if (newCandleStarted()) {
      CArrayDouble dcVals;
      for (int i=0; i<7; i++) {
         dcVals.Add(iCustom(_Symbol, PERIOD_H1, "Donchian", 0, i+1));
      }
      if (dcVals[6] < dcVals[5] && dcVals[5] == dcVals[0]){
         Print(dcVals[6], " ==== enter here ==== ", dcVals[0]);
      }
   }
}

int newCandleStarted()
{
   static datetime timeStampLastCheck = WRONG_VALUE;
   datetime current = SeriesInfoInteger(_Symbol, PERIOD_CURRENT, SERIES_LASTBAR_DATE);
   if (current != timeStampLastCheck) {
      bool res = (timeStampLastCheck != WRONG_VALUE);
      timeStampLastCheck = current;
      return res;
   }
   return false;
}
Reason: