Incorrect Chart candle high & Low after running for a while. - page 2

 
Vladislav Boyko #:

It looks like you are using something else (maybe iHigh()/iLow() or High[]/Low[]) instead of arrays that are passed by reference to the OnCalculate() function.

https://www.mql5.com/en/forum/475546

No, am actually using the OnCalculate() rates buffers, that is why it is baffling, as I can't tell, where it is getting its values from.

 
Ryan L Johnson #:

Interestingly, your last 10 bars appear to have the right calculation/display. If 10 bars is your intended lookback period, then eliminate the preceding superfluous dots with ...

PLOT_DRAW_BEGIN (Plot settings: PlotIndexSetInteger - Creating application programs - MQL5 Programming for Traders - MetaTrader 5 algorithmic/automatic trading language manual).

SetIndexDrawBegin

Sets the bar number from which the drawing of the given indicator line must start

Post edited by moderator

I can't understand the behaviour of the indicator, it plots well no problem at all, until the error occurs. Also, the candle on which its calculation are to start, is included in the code.

 
Thank-god Avwerosuoghene Odukudu #: the code is nothing complex,
      if(lastHigh!=high[idx])
        {
         Up[idx] = high[idx];
         lastHigh = high[idx];
        }
  1. If the condition is false, do you set your buffers to EMPTY_VALUE?

  2. Where do you set high/low directions?

    In MT4, buffers and MT4 predefined arrays are all ordered AsSeries. There is a difference between the arrays passed to OnCalculate (e.g. low[]) and the MT4 predefined variables (e.g. Low[].) The passed arrays have no default direction, just like MT5.

    To determine the indexing direction of time[], open[], high[], low[], close[], tick_volume[], volume[] and spread[] arrays, call ArrayGetAsSeries(). In order not to depend on default values, you should unconditionally call the ArraySetAsSeries() function for those arrays, which are expected to work with.
              Event Handling Functions - Functions - Language Basics - MQL4 Reference

 
William Roeder #:
  1. If the condition is false, do you set your buffers to EMPTY_VALUE?

  2. Where do you set high/low directions?

    In MT4, buffers and MT4 predefined arrays are all ordered AsSeries. There is a difference between the arrays passed to OnCalculate (e.g. low[]) and the MT4 predefined variables (e.g. Low[].) The passed arrays have no default direction, just like MT5.

1) No, In the condition that it is false, the buffer (UP) in this case, holds the value of the most recent high. it is set to "EMPTY_VALUE", when the candle is first added.

2) When the new candle is added (at limit>0) to the chart, a dot is placed below and above, with the values as seen from the OnCalculate. There is no direction, just placing a dot above  at the high, and below at the low.

Yes, I am aware of the predefined arrays being orded AsSeries. Am using the arrays passed to the OnCalculate. 

 
Thank-god Avwerosuoghene Odukudu #:
if(prev_calculated==0)
     {
      for(int d=0; d<2; d++)
         SetIndexDrawBegin(d, rates_total);
      return rates_total-1;
     }

You can't just ignore the situation when prev_calculated is zero. You should initialize all buffers with empty values and recalculate them for each bar. If the indicator has been running for a while and the terminal suddenly sets prev_calculated to 0, then this is not happening for nothing.

For the code from your example, it will not be difficult to calculate the arrow values again for each bar on the chart. If you have data there that cannot be restored, it is not enough to simply store it in an indicator buffer. Indicator buffers can be "corrupted" when the terminal adds or removes bars, after which you will not be able to find out which bars the values ​​stored in the buffer belonged to.

 
You can't know where exactly the terminal added bars or removed them from if the terminal set prev_calculated = 0. Forget whatever you had in the buffers, you can't leave old values ​​in the buffers after the terminal set prev_calculated = 0.
 
Vladislav Boyko #:

You can't just ignore the situation when prev_calculated is zero. You should initialize all buffers with empty values and recalculate them for each bar. If the indicator has been running for a while and the terminal suddenly sets prev_calculated to 0, then this is not happening for nothing.

Yes, that is why am setting from which bar to begin its plotting. If I initialize the plot buffers to EMPTY_VALUE, I lose all real time historic values calculated prior.

Vladislav Boyko #:

For the code from your example, it will not be difficult to calculate the arrow values again for each bar on the chart. If you have data there that cannot be restored, it is not enough to simply store it in an indicator buffer. Indicator buffers can be "corrupted" when the terminal adds or removes bars, after which you will not be able to find out which bars the values ​​stored in the buffer belonged to.

It does not recalculate, just working with the real time (currently forming candle) only.

Please, is there a way I can check for this.

 
Thank-god Avwerosuoghene Odukudu #:
Please, is there a way I can check for this.

What exactly do you want to check?

Here's the terminal adding bars to the right end:

2024.12.14 06:56:20.222 tempname USDCAD,M1: prev_calculated 0, rates_total 41554, left 2024.05.13 21:06, right 2024.12.13 23:58
2024.12.14 06:56:20.075 tempname USDCAD,M1: prev_calculated 0, rates_total 41532, left 2024.05.13 21:06, right 2024.06.21 22:58
2024.12.14 06:56:20.060 tempname USDCAD,M1: initialized
2024.12.14 06:56:20.007 tempname USDCAD,H1: uninit reason 3

And here the terminal adds bars to the left end:

2024.12.14 07:00:39.171 tempname AUDNZD,M1: prev_calculated 0, rates_total 2048, left 2024.12.12 13:48, right 2024.12.13 23:58
2024.12.14 07:00:39.086 tempname AUDNZD,M1: prev_calculated 0, rates_total 1536, left 2024.12.12 22:20, right 2024.12.13 23:58
2024.12.14 07:00:38.939 tempname AUDNZD,M1: prev_calculated 0, rates_total 1024, left 2024.12.13 06:55, right 2024.12.13 23:58
2024.12.14 07:00:38.871 tempname AUDNZD,M1: prev_calculated 0, rates_total 512, left 2024.12.13 15:27, right 2024.12.13 23:58
2024.12.14 07:00:38.686 tempname AUDNZD,M1: initialized
2024.12.14 07:00:38.686 tempname AUDNZD,H1: uninit reason 3

I just did these 2 tests. I managed to do it even though the market is closed. I simply changed the timeframe to M1 (which had not been used for a long time) and pressed the home button. The indicator I used:

#property strict
#property indicator_chart_window

int OnInit() { return(INIT_SUCCEEDED); }

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[])
  {
   PrintFormat("prev_calculated %i, rates_total %i, left %s, right %s", prev_calculated, rates_total, TimeToString(time[rates_total - 1]), TimeToString(time[0]));
   return(rates_total);
  }

void OnDeinit(const int reason) {  }
 
Vladislav Boyko #:

Here's the terminal adding bars to the right end:

And here the terminal adds bars to the left end:

Now imagine that you had data in indicator buffers, the size of which the terminal changed.

Those 2 examples were primitive. The terminal can also delete bars from the chart sometimes, judging by what other users write on this forum (I myself have never seen bars deleted from the chart). After buffers are truncated, they may still contain data, but the indexing is corrupted.

 
Thank-god Avwerosuoghene Odukudu #:

Yes, that is why am setting from which bar to begin its plotting. If I initialize the plot buffers to EMPTY_VALUE, I lose all real time historic values calculated prior.

It does not recalculate, just working with the real time (currently forming candle) only.

Please, is there a way I can check for this.

Here's how I avoid nested loops:

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[])
  {
//--- calculation of the starting bar index for the inner loop
   if(prev_calculated == 0)  // check for the first call for the inner loop
     {
      limit = startBar - 1;  // starting index for the calculation of all of the bars in the inner loop
     }
   else
     {
      limit = startBar - prev_calculated - 1; // starting index for the calculation of new bars in the inner loop
      //copyBars = rates_total - 1 - prev_calculated;
     }

//--- main loop
   for(bar = rates_total - 1; bar >= 0; bar--)
     {
      CustomFunction(bar);   
     }

   return(rates_total - 1);
  }

//+------------------------------------------------------------------+

void CustomFunction(int i)
  { 
   if(i <= startBar && yourvalue != 2147483647) // filter out EMPTY_VALUE ==> 2147483647 in MT4
   {
    yourbuffer[i] = yourvalue
   }
  }

MT4 empty value: Other constants - Named Constants - Constants, Enumerations and Structures - MQL4 Reference

Other constants - Named Constants - Constants, Enumerations and Structures - MQL4 Reference
Other constants - Named Constants - Constants, Enumerations and Structures - MQL4 Reference
  • docs.mql4.com
Other constants - Named Constants - Constants, Enumerations and Structures - MQL4 Reference