When an indicator first loads, prev_calculated is 0 on the first execution. On subsequent calls, prev_calculated holds the number of bars processed in the previous execution.
So when the indicator has has calculated more than one bar, prev_calculated – 1 is accepted as the last processed bar and is an efficient starting point for future calculations - if the current bar in the indicator is all that is necessary to be updated on each recalculation.
If the indicator must update X bars at a time like in the Fractals indicator (example 5 bars), then a possible starting index would be prev_calculated – 5.
When prev_calculated is zero (first execution), the indicator needs to calculate the preliminary data.
In some custom indicators, you need enough historical data points to correctly calculate the buffers, this would be for example pivot indicators where the result is obtained based on a period of bars. This also applies to indicators that do not use CopyBuffer.
In this kind of indicator, you could have a start index like this:
int start = (prev_calculated == 0) ? period_var : prev_calculated – 1;
or
int start = (prev_calculated < period_var) ? period_var : prev_calculated – 1;
If you wanted to create bar confirmations, then you should alter the start index to support this:
int start = (prev_calculated == 0) ? period_var : prev_calculated - (bar_confirmations + 1);
( + 1 should be added to bar_confirmations to account for the fact that “bar_confirmations” can be 0 and prev_calculated – 1 is the last calculated bar)
Copying bars with CopyBuffer:
prev_calculated can theoretically be -1 (though usually 0) or greater than rates_total.
In some indicator functions like iMA, an equivalent number of bars are copied with CopyBuffer, and while there is no strict minimum number of bars required to be copied, you need to copy sufficient bars for the indicator to calculate properly. If prev_calculated < 0, restarting from 0 can be done to prevent errors with the plotting, but it should start the update from the last copied bar otherwise.
When copying bars in an indicator with copybuffer, it’s best not to copy all rates/bars because it can slow down the indicator, which will then also slow down an EA if the indicator is being used in the EA with iCustom.
To properly and safely copy bars, you need to ensure that prev_calculated is not less than 0 and not greater than rates_total. If it is less than zero, copy all bars temporarily, otherwise only copy new bars. By doing this, you do not need to recalculate everything on each execution. Note that "rates_total - prev_calculated + 1" is going to reliably fetch only new data that hasn't been processed yet... prev_calculated plus one extra bar, as new data can arrive during the current calculation.
if(prev_calculated > rates_total || prev_calculated < 0){ to_copy = rates_total; } else { to_copy = rates_total - prev_calculated; if(prev_calculated > 0) to_copy++; }
or
if(prev_calculated > rates_total || prev_calculated < 0) { to_copy = rates_total; } else { to_copy = rates_total - prev_calculated + 1; }
Now call the CopyBuffer function to copy the data into the designated buffer:
if(CopyBuffer(handle, 0, 0, to_copy, buffer) < 0){ Print(“Error encountered copying bars, please stand by.”); ChartRedraw(); }
Then for a calculation loop which uses one of the indicators from the framework such as "iMA", the start index will commonly look like this:
int start = (prev_calculated < 0) ? 1 : prev_calculated - 1;