Rates function problem

 

Hi All,

I am baffled by the issue below. Very simple code asking for the high & low of the first bar on a chart of specified timeframe.

extern ENUM_TIMEFRAMES tf = PERIOD_D1;                

void OnStart()
{
RefreshRates();
MqlRates rates[];
ArrayCopyRates(rates,NULL,tf);
Print(tf,"   ",rates[0].high,"   ",rates[0].low);
Print(tf,"   ",iHigh(NULL,tf,0),"   ",iLow(NULL,tf,0));
}

if I drop the script on a daily chart and choose tf = PERIOD_D1 I get the following results:

 These values are correct as given directly on the chart (Data window)

if I drop the script on the daily chart but choose tf = PERIOD_H1 I get the following results:

 These are not correct! (as compared with data window below)

 

If I drop the script onto the hour chart and choose tf = PERIOD_H1 the results are correct.

I just cannot see what I have done wrong in the code - please can someone offer advice?

thanks

 
sd59:I just cannot see what I have done wrong
Check your return codes and find out why. What are Function return values ? How do I use them ? - MQL4 forum and Common Errors in MQL4 Programs and How to Avoid Them - MQL4 Articles
 

check yourself what index of 0,1,..Bars-1,Bars means either most recent or the oldest bar => use

rates[0].time

I for myself wrote a #define-function for actualBar(i) and previousBar(i):

#define previousBar(i) (i-1) // or in a different way deepens on your code!

#define    actualBar(i) (i):

rates[ actualBar(0) ].time
 

Check your return codes and find out why. What are Function return values ? How do I use them ? - MQL4 forum

This gives examples of OrderSelect()/OrderSend functions which can be interrogated for return codes - iHigh() function does not have a return code it has a return value. It should give the value it has been asked to retrieve. 

gooly, I am sorry I don't understand your suggestion.

 Let's make it simpler..

extern ENUM_TIMEFRAMES tf = PERIOD_D1;

void OnStart()
{
RefreshRates();
Print(tf,"   ",iHigh(NULL,tf,0),"   ",iLow(NULL,tf,0));
}

 Even this gives inconsistent results when I vary the combination of tf and the chart timeframe on which the script is dropped.

I am simply asking it for the high and low values of the first bar (zero bar) on a specified timeframe. 

Could it have something to do with history values? The charts visually appear to be up to date (timewise). 

 
sd59:

 Let's make it simpler..

extern ENUM_TIMEFRAMES tf = PERIOD_D1;

void OnStart()
{
RefreshRates();
Print(tf,"   ",iHigh(NULL,tf,0),"   ",iLow(NULL,tf,0));
}


 Even this gives inconsistent results when I vary the combination of tf and the chart timeframe on which the script is dropped.

I am simply asking it for the high and low values of the first bar (zero bar) on a specified timeframe. 

Could it have something to do with history values? The charts visually appear to be up to date (timewise). 

Hello,

 

I can confirm what you are seeing. Also, at least in my part, if I change the TF back and forth (on chart ), it comes back to normal. A bug for sure

 

best regards 

 
Demos:

Hello,

 

I can confirm what you are seeing. Also, at least in my part, if I change the TF back and forth (on chart ), it comes back to normal. A bug for sure

 

best regards 

 Thanks for the reply Demos - this is a serious bug! I have used this in-built function in many other programmes and taken for granted it was returning correct value. I have only noticed now because with the particular programme I am building I have to double check the bar data manually (i.e directly from the chart).

  What happens now? Should someone from Metaquotes double check this?

thanks 

 
Can you reproduce the problem, or does it happen only for the first run? When only for the first run, then it is usual behaviour resulting from lazy history data loading.
 
sd59:

 Thanks for the reply Demos - this is a serious bug! I have used this in-built function in many other programmes and taken for granted it was returning correct value. I have only noticed now because with the particular programme I am building I have to double check the bar data manually (i.e directly from the chart).

  What happens now? Should someone from Metaquotes double check this?

thanks 


Ovo:
Can you reproduce the problem, or does it happen only for the first run? When only for the first run, then it is usual behaviour resulting from lazy history data loading.

 Hello, I messed around a bit, but here is what happens 

a) You may start with a chart, which has not any previous history loaded. Normally it will open at H1

b) Put this one on OnInit() so it will repeat in TF change

Alert(iHigh(NULL,PERIOD_D1,0)," ", iHigh(NULL,0,0) );

 It will Alert the first one as 0

c) Now, change the TF to anything but D1. At this time, the Alert will have the correct D1 price, althought we did not load the D1  

 

So, from what I can understand, the behaviour experienced is not a bug, but the fact that upon a TF change, the history load behaves as follows:

a)  At first launch of the chart, it loads H1. 

And now the critical part 

b) If we change to another TF, it is loaded specifically as requested. But, if we have attached an EA as above, which asks for PERIOD_D1, that TF will be included on the next TF change, whatever the TF we change to hehe :) Something like preemption  

 

best regards 

 
Demos:


 Hello, I messed around a bit, but here is what happens 

a) You may start with a chart, which has not any previous history loaded. Normally it will open at H1

b) Put this one on OnInit() so it will repeat in TF change

 It will Alert the first one as 0

c) Now, change the TF to anything but D1. At this time, the Alert will have the correct D1 price, althought we did not load the D1  

 

So, from what I can understand, the behaviour experienced is not a bug, but the fact that upon a TF change, the history load behaves as follows:

a)  At first launch of the chart, it loads H1. 

And now the critical part 

b) If we change to another TF, it is loaded specifically as requested. But, if we have attached an EA as above, which asks for PERIOD_D1, that TF will be included on the next TF change, whatever the TF we change to hehe :) Something like preemption  

 

best regards  

 Yes, you understand it properly.

- If you open a chart in the terminal, it loads the history for its timeframe. Other timeframes history remains untouched.

- When you attempt to reach other timeframe from the script, the terminal duplicates the other timeframe history and passes the duplicate to your script. Then it asynchronously (I guess it is asynchronous) starts updating the original buffer.

- If no history was for the other timeframe, it fetches only a few last candles (512-2048). If you need a deeper history, you really need to open the timeframe chart in the terminal to force additional data fetching.

 

BTW, RefreshRates() as a first line command has no effect, as it recreates buffers which it just created.

 
Ovo:

 Yes, you understand it properly.

- If you open a chart in the terminal, it loads the history for its timeframe. Other timeframes history remains untouched.

- When you attempt to reach other timeframe from the script, the terminal duplicates the other timeframe history and passes the duplicate to your script. Then it asynchronously (I guess it is asynchronous) starts updating the original buffer.

- If no history was for the other timeframe, it fetches only a few last candles (512-2048). If you need a deeper history, you really need to open the timeframe chart in the terminal to force additional data fetching.

hello,

regarding the 2nd argument, i would like to point out a fact; the problem-source of confusion may be that when we have a fresh chart and we attach a script, new history is not loaded according to the needs of the script. But we have to make a manual (or in-code) TF change first, and it is then when history is loaded as per scripts need. 

 PS. for the purpose of the topic, i used ChartSetSymbolPeriod() to see if the above work code-wise. But, allas, i put it on OnInit(). But, since ChartSetSymbolPeriod() causes a reinit (you can read the reference manual for that), MetaTrader hangs big time, doing OnInit() again and again 

edit

You are in fact right. By the moment the script or EA is loaded on a chart, present (in code) TFs are getting loaded and are ready for use after, so no need for any TF change by the user 

 

Well, so far the design is understandable. Just one catch is still there - there is no way how to reliably detect that the (asynchronous) history load completed.

I believe the original MQL4 designer prepared the code ERR_HISTORY_WILL_UPDATED with the GetLasError(), but do not attempt to try it - it has a dummy implementation, returning this constant on a first call, and then never ever, regardless whether the history data was loaded or not.