close[] vs iClose

dmdamiyo
117
dmdamiyo  

I have a bar number that points to some specific time in history

bar_number

I'm running the chart in H1. Could you help me understand why:

  • close[bar_number] returns a correct value
  • iClose(_Symbol, PERIOD_H1, bar_number) - returns always 0.0.

The error is 4401. Do you see why, since it's the same timeframe and the data is present in close[]?

Also, I'm not able to use while loop and Sleep to wait for the data to be loaded since it's an indicator? Maybe I should immediately return a certain value?


The other question I have, is - what is the preferred method to use? CopyClose or iClose?

Thanks in advance ☺

William Roeder
23730
William Roeder  
  1. Bar_number does not refer to a “specific time in history,” and neither does close[bar_number]. Unless you specifically set the as-series direction for close[], close[0] could be the oldest history bar or the current (newest) forming one.
  2. iClose(_Symbol, PERIOD_CURRENT, bar_number) uses the as-series direction and returns that price on the current chart. iClose(_Symbol, PERIOD_H1, bar_number) is lookng at the H1 chart, while close[bar_number] is looking at the current chart.
  3. On MT4: Unless the current chart is that specific symbol(s)/TF(s) referenced, you must handle 4066/4073 errors before accessing candle/indicator values.
              Download history in MQL4 EA - Forex Calendar - MQL4 programming forum - Page 3 #26.4 2019.05.20

    On MT5: Unless the chart is that specific pair/TF, you must synchronize the terminal Data from the Server before accessing candle/indicator values.
              Is it mystical?! It is! - Withdraw - Technical Indicators - MQL5 programming forum 2019.05.31
              Timeseries and Indicators Access / Data Access - Reference on algorithmic/automated trading language for MetaTrader 5
              Synchronize Server Data with Terminal Data - Symbols - General - MQL5 programming forum
              SymbolInfoInteger doesn't work - Symbols - General - MQL5 programming forum 2019.09.03
              OnCalculate during weekend MT5 - General - MQL5 programming forum

dmdamiyo
117
dmdamiyo  

Thanks, but

1. Yes, I do explicitly set close as-series, so bar number 0 is the newest bar.

3. The chart is that specific pair I'm trying to access the data of.


Sorry, I see that I wrote that iClose always returns 0.0. Actually it's like that:

  • value of Bars is 100600
  • iClose starts to get values from bar 99080 (always the same bar). For older bars it returns 0.0.
  • close[] works for all of them
  • so, to summarize: close[100500] returns a value, whereas iClose(_Symbol, PERIOD_H1, 100500) returns 0.0.

I can't get to understand that behaviour.

Georgi Gaydarov
1059
Georgi Gaydarov  
dmdamiyo:

Thanks, but

1. Yes, I do explicitly set close as-series, so bar number 0 is the newest bar.

3. The chart is that specific pair I'm trying to access the data of.


Sorry, I see that I wrote that iClose always returns 0.0. Actually it's like that:

  • value of Bars is 100600
  • iClose starts to get values from bar 99080 (always the same bar). For older bars it returns 0.0.
  • close[] works for all of them
  • so, to summarize: close[100500] returns a value, whereas iClose(_Symbol, PERIOD_H1, 100500) returns 0.0.

I can't get to understand that behaviour.

Can you try with
   double close = iClose(NULL, 0, 100500 ); It will take the default symbol and period, same like close[]
Georgi Gaydarov
1059
Georgi Gaydarov  

Another possibility is that if you call iClose too soon when the indicator is initialized the history may not be loaded.

In MT5 when an indicator is launched,  and the history data is too big might not have been completely loaded upon the first call to OnCalculate.

When exactly you call both Close and iClose, can you share that code part

dmdamiyo
117
dmdamiyo  

Hi, your suggestion with NULL didn't help.

I also don't expect that the history is not ready, because Bars returns a correct number. Additionally, bar number from which it starts working is always the same.

The relevant code:

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[])
  {
//---
   ArraySetAsSeries(time,true);
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);

   int index_of_oldest_to_calc = rates_total - prev_calculated - 1;

// it works only if period is lower than H1
   if(_Period > PERIOD_H1)
     {
      LOG(LOG_LEVEL_ERROR, "Period larger than H1, won't display any data");
      ArrayInitialize(indicator_data, EMPTY_VALUE);
      // don't draw anything on intervals higher than H1
      return(rates_total);
     }
// check how many bars are on the H1 chart
   int h1_total_bars = Bars(_Symbol, PERIOD_H1);
// wait for the history to load
   if(h1_total_bars == 0)
     {
      DEBUG("Bars() in PERIOD_H1 = 0");
      return(0);
     }

   for(int bar_number=rates_total-3;
       bar_number>=0 && !IsStopped();
       bar_number--)
     {
      // get H1 number of the bar
      int h1_bar_number = iBarShift(NULL, PERIOD_H1, time[bar_number], true);
      
      if (h1_bar_number == -1){
         continue;
      }

      // we cannot go over the possible history
      if(h1_bar_number+period > h1_total_bars)
        {
         indicator_data[bar_number] = EMPTY_VALUE;
         indicator_color_data[bar_number] = EMPTY_VALUE;
         continue;
        }

      //previous 2 close and open values
      double open_previous = iOpen(NULL, PERIOD_H1, h1_bar_number+1);
      double close_previous = iClose(NULL, PERIOD_H1, h1_bar_number+1);

      double open_pre_previous = iOpen(NULL, PERIOD_H1, h1_bar_number+2);
      double close_pre_previous = iClose(NULL, PERIOD_H1, h1_bar_number+2);
      // highest & lowest point of the previous bar
      //double prev_body_max = MathMax(open_previous, close_previous);
      //double prev_body_min = MathMin(open_previous, close_previous);
      // lowest point of the previous bar
      double pre_prev_body_max = MathMax(open_pre_previous, close_pre_previous);
      double pre_prev_body_min = MathMin(open_pre_previous, close_pre_previous
Georgi Gaydarov
1059
Georgi Gaydarov  

You run this on H1 chart, right?

Because if you run that code on different time frame the rates_total is different and then you get here

      int h1_bar_number = iBarShift(NULL, PERIOD_H1, time[bar_number], true);

and then the loop breaks. And there is possibility that you have more history for M5 and less for H1, which start from different date. Perhaps that can be the problem.

But if you run that code on H1, I can't find anything that could be a problem. Maybe it is a bug in the MT.

dmdamiyo
117
dmdamiyo  

I run into this issue when I run on H1, so it seems like a bug.

But not a very serious one, since it's only for a few oldest bars.
William Roeder
23730
William Roeder  
dmdamiyo I run into this issue when I run on H1, so it seems like a bug. But not a very serious one, since it's only for a few oldest bars.
  1. How To Ask Questions The Smart Way. 2004
              Don't rush to claim that you have found a bug.
    Questions Not To Ask
              My program doesn't work. I think system facility X is broken.

  2.       if(h1_bar_number+period > h1_total_bars)
    bar_number is like 123. Period (H1) is 16385 an enumeration. Adding them is meaningless. On MT5 ENUM_TIMEFRAMES values are not the period in minutes.
    Use EnumToString(TF[i]) to see the string representation of the time frame.
    Use PeriodSeconds(TF[i]) to see the duration of the time frame.
              Why are MT5 ENUM_TIMEFRAMES strange? - General - MQL5 programming forum - Page 2 #11 2020.06.21