diff --git a/Include/MyIncludes/SMA_Recursive_Calculator.mqh b/Include/MyIncludes/SMA_Recursive_Calculator.mqh new file mode 100644 index 0000000..0994ef8 --- /dev/null +++ b/Include/MyIncludes/SMA_Recursive_Calculator.mqh @@ -0,0 +1,148 @@ +//+------------------------------------------------------------------+ +//| SMA_Recursive_Calculator.mqh | +//| Calculation engine for a recursive Simple Moving Average. | +//| Copyright 2025, xxxxxxxx | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, xxxxxxxx" + +#include + +//+==================================================================+ +class CSMARecursiveCalculator + { +protected: + int m_period; + double m_price[]; + virtual bool PreparePriceSeries(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]); +public: + CSMARecursiveCalculator(void) {}; + virtual ~CSMARecursiveCalculator(void) {}; + bool Init(int period); + void Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &sma_buffer[]); + }; + +//+------------------------------------------------------------------+ +bool CSMARecursiveCalculator::Init(int period) + { + m_period = (period < 1) ? 1 : period; + return true; + } + +//+------------------------------------------------------------------+ +void CSMARecursiveCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &sma_buffer[]) + { + if(rates_total < m_period) + return; + if(!PreparePriceSeries(rates_total, price_type, open, high, low, close)) + return; + + double sma_prev = 0; + +// Initial SMA calculation + double first_sum = 0; + for(int i = 0; i < m_period; i++) + { + first_sum += m_price[i]; + } + sma_buffer[m_period - 1] = first_sum / m_period; + sma_prev = sma_buffer[m_period - 1]; + +// Recursive calculation for the rest of the bars + for(int i = m_period; i < rates_total; i++) + { + // SMA[i] = SMA[i-1] + (Price[i] / N) - (Price[i-N] / N) + double current_sma = sma_prev + (m_price[i] / m_period) - (m_price[i - m_period] / m_period); + sma_buffer[i] = current_sma; + sma_prev = current_sma; + } + } + +//+------------------------------------------------------------------+ +bool CSMARecursiveCalculator::PreparePriceSeries(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) + { + ArrayResize(m_price, rates_total); + switch(price_type) + { + case PRICE_CLOSE: + ArrayCopy(m_price, close, 0, 0, rates_total); + break; + case PRICE_OPEN: + ArrayCopy(m_price, open, 0, 0, rates_total); + break; + case PRICE_HIGH: + ArrayCopy(m_price, high, 0, 0, rates_total); + break; + case PRICE_LOW: + ArrayCopy(m_price, low, 0, 0, rates_total); + break; + case PRICE_MEDIAN: + for(int i=0; i