Introduce CSmoothingBase as an intermediate abstract base class between
CSubIndiBase and concrete smoothing sub-indicators (such as CSma).
Extract common traits shared across all smoothing algorithms:
- Declare pure virtual onCalculate() to standardize the calculation interface.
- Pull up the output indicator buffer (buffer[]) and its clearBuffersAt() hook.
- Generalize correctPeriod() with a configurable minPeriod parameter.
- Hardcode emptyValue to EMPTY_VALUE in the base class constructor.
Update CSma to inherit from CSmoothingBase and remove redundant members.
Add an overload for CSubIndiBase::prepareCalculation() that outputs whether
drawBegin is included in the calculation range via the isFullCalculation flag.
Adopt this overload in CSma::onCalculate(), allowing the redundant prepareRecurrenceSeed()
helper to be inlined and removed since the if (isFullCalculation) check makes seed
initialization transparent and self-documenting.
Using "rates_total - prev_calculated > 1" was insufficient for detecting
when the seed value at drawBegin needed to be computed by summation.
When calculating with minimal history (prev_calculated == barsRequired),
recalcStartIdx equals drawBegin. Because the difference is <= 1, summation
was skipped and the recurrence loop ran at index drawBegin, causing a fatal
'Array out of range' error when accessing source[drawBegin - period] (index -1).
Introduce prepareRecurrenceSeed() to calculate the seed via summation
whenever recalcStartIdx <= drawBegin, and start the recurrence from drawBegin + 1.
https://www.mql5.com/en/forum/510519#comment_60245675