ArrayCopyRates bug - direct subtraction of time values is zero

 

Using MQ4 Build 509

If I directly subtract two time values mq4 gives 0, but if stored in intermediate variables the result is correct. 

(probably something to do with the  way mq4 implements the syntactic sugar to make the TIME longs look like doubles??)

Run following script for demo...


int start()
 {
   int fld = 0;
   double a[][6];
   double d1,d2;
   int num = ArrayCopyRates(a,Symbol(),PERIOD_D1);
   if (num > 1) {
      d1 = a[0][fld];
      d2 = a[num-1][fld];
      Alert("old:"+a[num-1][fld]);
      Alert("new:"+a[0][fld]);
      Alert("diff1: "+(a[0][fld]-a[num-1][fld]));
      Alert("diff2: "+(d1-d2));
   }

   return(0);
 }
 
   //{https://www.mql5.com/en/forum/129734/page2 says ArrayCopyRates is a nonreentrant,
   // non-thread-safe call. Therefor you must put a mutex around the call in
   // case of multiple EAs on multiple charts. Alteratively, since init() is
   // single threaded across all charts, put all ACRs there.
int nBars(double a[][]){ return( ArrayRange(a,0) ); } // ArrayRange allows 1D or 2D arrays
 

Thanks useful to know that I just need a single ACR call in init().

There is still the issue that direct subtraction of time values does not work (even if there is only a single thread). Just thought I'd highlight it!


Also appreciate youre useful bits of code I see in this thread https://www.mql5.com/en/forum/133792

 
// https://www.mql5.com/en/forum/129734/page2 says ArrayCopyRates is a nonreentrant,
// non-thread-safe call. Therefor you must put a mutex around the call in
// case of multiple EAs on multiple charts.

I stated that ALL you need is a single ACR call in init() based on my misunderstanding that init was single threaded like indicators start, i.e. must return in 2.5 seconds. Only deinit and start when isStopped must return in 2.5 seconds

Now I state you need a single ACR call in init() but it must be surrounded by a mutex when there are multiple EAs on multiple charts calling it.

 
WHRoeder:

I stated that ALL you need is a single ACR call in init() based on my misunderstanding that init was single threaded like indicators start, i.e. must return in 2.5 seconds. Only deinit and start when isStopped must return in 2.5 seconds

Now I state you need a single ACR call in init() but it must be surrounded by a mutex when there are multiple EAs on multiple charts calling it.


Just to be clear this is a completely separate issue to my original issue raise in the first post right? (that direct subtraction of the datetime value is broken? Regardless of whether the ACR call is in init() or start()?

 

You called ACR in start but didn't check and handle 4066. Subsequent calls will NOT return 4066, thus you think there are elements in the array, but they haven't yet been filled.

direct subtraction of datetime values are fine.

 

To avoid confusion/distraction here is the original issue (subtraction of datetime) as an EA with ACR in init().

Now is my OP understood? Nothing to do with threading/mutex issues, as it manifested with a single EA on a single chart...

It is IMO related to the syntactic sugar used to make the DLL structure look like an array of doubles to MQL, when the memory structure is actually a mixture of doubles and ints...

Any more comment on this or usual silence :)


// ACR Datetime bug
double a[][6];
int num;

int init()
  {
  Print("init1");
  
    num = ArrayCopyRates(a,Symbol(),PERIOD_D1);
  Print("init2");
   
   return(0);
  }
int deinit()
  {
   return(0);
  }
int start()
 {
  Print("start",num);
   int fld = 0;
   double d1,d2;
   if (num > 1) {
      d1 = a[0][fld];
      d2 = a[num-1][fld];
      Print("oldest time:"+TimeToStr(a[num-1][fld],TIME_DATE|TIME_SECONDS));
      Print("recent time:"+TimeToStr(a[0][fld],TIME_DATE|TIME_SECONDS));
      Print("gap: "+(a[0][fld]-a[num-1][fld]));
      Print("gap2: "+(d1-d2));
      num = 0;

   }
   return(0);
}

Output is :


18:59:49 ACR GBPUSD,H1: loaded successfully
18:59:50 ACR GBPUSD,H1: init1
18:59:50 ACR GBPUSD,H1: init2
18:59:50 ACR GBPUSD,H1: initialized
18:59:51 ACR GBPUSD,H1: start3567
18:59:51 ACR GBPUSD,H1: oldest time:2000.01.03 00:00:00
18:59:51 ACR GBPUSD,H1: recent time:2013.09.17 00:00:00
18:59:51 ACR GBPUSD,H1: gap: 0.00000000
18:59:51 ACR GBPUSD,H1: gap2: 432518400.00000000

18:59:51 ACR GBPUSD,H1: start0

 

PS The irony is, this thread was my second post on this forum, about two months ago, after my first exposure to MQL4 about a month before that. I had spent - probably about 12 literal hours, tracking down that bug, assuming all the while it was my own error, in the calculation,

then upon finding the bug, dutifully prepared a test case to highlight the bug, and report it, think how helpful I'm being to others, (as the forums had helped me a lot up to that point), and was promptly told I was mistaken without any evidence to back up, and completely ignoring my test case?

And after that no-one else seemed to care to comment on it. Whether to confirm or deny. So I was a little surprised at that...

This is why I've always felt there should be a peer reviewed list of know issues in a well know place, so that we can all help one another avoid these pitfalls that often result in a day (or two) of our lives wasted!
 
ydrol:

PS The irony is, this thread was my second post on this forum, about two months ago, after my first exposure to MQL4 about a month before that. I had spent - probably about 12 literal hours, tracking down that bug, assuming all the while it was my own error, in the calculation,

then upon finding the bug, dutifully prepared a test case to highlight the bug, and report it, think how helpful I'm being to others, (as the forums had helped me a lot up to that point), and was promptly told I was mistaken without any evidence to back up, and completely ignoring my test case?

And after that no-one else seemed to care to comment on it. Whether to confirm or deny. So I was a little surprised at that...

This is why I've always felt there should be a peer reviewed list of know issues in a well know place, so that we can all help one another avoid these pitfalls that often result in a day (or two) of our lives wasted!

I don't think it's an ACR Bug at all . . . if it was your d1 and d2 values would be wrong . . . I think it's a Print() type casting bug which can be made to work, if it was an ACR bug it couldn't be made to work . . . try the following:

// ACR Datetime bug
double a[][6];
int num;

int init()
  {
  Print("init1");
  
    num = ArrayCopyRates(a,Symbol(),PERIOD_D1);
  Print("init2");
   
   return(0);
  }
int deinit()
  {
   return(0);
  }
int start()
 {
  Print("start",num);
   int fld = 0;
   double d1,d2;
   if (num > 1) {
      d1 = a[0][fld];
      d2 = a[num-1][fld];
      Print("oldest time:"+TimeToStr(a[num-1][fld],TIME_DATE|TIME_SECONDS));
      Print("recent time:"+TimeToStr(a[0][fld],TIME_DATE|TIME_SECONDS));
      Print("gap: "+( (a[0][fld] / 1.0) - a[num-1][fld]));               // changed by RaptorUK
      Print("gap2: "+(d1-d2));
      num = 0;

   }
   return(0);
}
 
RaptorUK:

I don't think it's an ACR Bug at all . . . if it was your d1 and d2 values would be wrong . . . I think it's a Print() type casting bug which can be made to work, if it was an ACR bug it couldn't be made to work . . . try the following:

OK, maybe not typecasting . . . maybe a memory issue.
 

Hmm, interesting, I just also tried:

// ACR Datetime bug
double a[][6];
int num;

int init()
  {
  Print("init1");
  
    num = ArrayCopyRates(a,Symbol(),PERIOD_D1);
  Print("init2");
   
   return(0);
  }
int deinit()
  {
   return(0);
  }
int start()
 {
  Print("start",num);
   int fld = 0;
   double d1,d2,d3; // added d3
   if (num > 1) {
      d1 = a[0][fld];
      d2 = a[num-1][fld];
      d3 = a[0][fld]  - a[num-1][fld];
      Print("oldest time:"+TimeToStr(a[num-1][fld],TIME_DATE|TIME_SECONDS));
      Print("recent time:"+TimeToStr(a[0][fld],TIME_DATE|TIME_SECONDS));
      Print("gap: "+( (a[0][fld] / 1.0) - a[num-1][fld]));               // changed by RaptorUK
      Print("gap2: "+(d1-d2));
      Print("gap3: "+(d3)); // New bit
      num = 0;

   }
   return(0);
}

and get :


23:12:55 ACR GBPUSD,H1: init1
23:12:55 ACR GBPUSD,H1: init2
23:12:55 ACR GBPUSD,H1: initialized
23:12:55 ACR GBPUSD,H1: start3568
23:12:55 ACR GBPUSD,H1: oldest time:2000.01.03 00:00:00
23:12:55 ACR GBPUSD,H1: recent time:2013.09.18 00:00:00
23:12:55 ACR GBPUSD,H1: gap: 432604800.00000000
23:12:55 ACR GBPUSD,H1: gap2: 432604800.00000000
23:12:55 ACR GBPUSD,H1: gap3: 0.00000000
23:12:58 ACR GBPUSD,H1: start0


I think its a bug in the expression parser somewhere when subtracting two ACR date values ??

Reason: