From ae3f2bea0339e904c07db386b0c430598f661a63 Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Fri, 28 Nov 2025 14:11:53 +0100 Subject: [PATCH] refactor: Optimized for incremental calculation --- Include/MyIncludes/MovingAverage_Engine.mqh | 290 ++++++++++++-------- 1 file changed, 171 insertions(+), 119 deletions(-) diff --git a/Include/MyIncludes/MovingAverage_Engine.mqh b/Include/MyIncludes/MovingAverage_Engine.mqh index 3232fb9..0150555 100644 --- a/Include/MyIncludes/MovingAverage_Engine.mqh +++ b/Include/MyIncludes/MovingAverage_Engine.mqh @@ -1,13 +1,13 @@ //+------------------------------------------------------------------+ //| MovingAverage_Engine.mqh | -//| VERSION 1.30: Added DEMA and TEMA for lag reduction. | +//| VERSION 1.40: Optimized for incremental calculation. | //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" #include -//--- UPDATED: Enum to select the MA type for calculation --- +//--- Enum to select the MA type for calculation enum ENUM_MA_TYPE { SMA, @@ -25,17 +25,30 @@ class CMovingAverageCalculator protected: int m_period; ENUM_MA_TYPE m_ma_type; + + //--- Persistent Buffers for Incremental Calculation 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[]); - void CalculateEMA(int rates_total, int period, const double &source[], double &dest[]); + //--- Buffers for complex MAs (TMA, DEMA, TEMA) + double m_temp_buffer1[]; // Used for TMA(sma1), DEMA(ema1), TEMA(ema1) + double m_temp_buffer2[]; // Used for DEMA(ema2), TEMA(ema2) + double m_temp_buffer3[]; // Used for TEMA(ema3) + + //--- Updated: Accepts start_index + virtual bool PreparePriceSeries(int rates_total, int start_index, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]); + + //--- Updated: Accepts start_index + void CalculateEMA(int rates_total, int start_index, int period, const double &source[], double &dest[]); public: CMovingAverageCalculator(void) {}; virtual ~CMovingAverageCalculator(void) {}; bool Init(int period, ENUM_MA_TYPE ma_type); - void Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &ma_buffer[]); + + //--- Updated: Accepts prev_calculated + void Calculate(int rates_total, int prev_calculated, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &ma_buffer[]); + int GetPeriod(void) const { return m_period; } }; @@ -46,8 +59,11 @@ class CMovingAverageCalculator_HA : public CMovingAverageCalculator { private: CHeikinAshi_Calculator m_ha_calculator; + // Internal HA buffers (Persistent) + double m_ha_open[], m_ha_high[], m_ha_low[], m_ha_close[]; + protected: - virtual bool PreparePriceSeries(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) override; + virtual bool PreparePriceSeries(int rates_total, int start_index, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) override; }; //+==================================================================+ @@ -55,7 +71,7 @@ protected: //+==================================================================+ //+------------------------------------------------------------------+ -//| | +//| Init | //+------------------------------------------------------------------+ bool CMovingAverageCalculator::Init(int period, ENUM_MA_TYPE ma_type) { @@ -65,26 +81,49 @@ bool CMovingAverageCalculator::Init(int period, ENUM_MA_TYPE ma_type) } //+------------------------------------------------------------------+ -//| | +//| Main Calculation (Optimized) | //+------------------------------------------------------------------+ -void CMovingAverageCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &ma_buffer[]) +void CMovingAverageCalculator::Calculate(int rates_total, int prev_calculated, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &ma_buffer[]) { if(rates_total < m_period) return; - if(!PreparePriceSeries(rates_total, price_type, open, high, low, close)) + +//--- 1. Determine Start Index + int start_index; + if(prev_calculated == 0) + start_index = 0; + else + start_index = prev_calculated - 1; + +//--- 2. Resize Buffers + if(ArraySize(m_price) != rates_total) + { + ArrayResize(m_price, rates_total); + // Resize temp buffers only if needed by type + if(m_ma_type == TMA || m_ma_type == DEMA || m_ma_type == TEMA) + ArrayResize(m_temp_buffer1, rates_total); + if(m_ma_type == DEMA || m_ma_type == TEMA) + ArrayResize(m_temp_buffer2, rates_total); + if(m_ma_type == TEMA) + ArrayResize(m_temp_buffer3, rates_total); + } + +//--- 3. Prepare Price (Optimized) + if(!PreparePriceSeries(rates_total, start_index, price_type, open, high, low, close)) return; int start_pos = m_period - 1; - for(int i = 0; i < rates_total; i++) // Clear all values initially - ma_buffer[i] = EMPTY_VALUE; + int loop_start = MathMax(start_pos, start_index); +//--- 4. Calculate MA based on type switch(m_ma_type) { case EMA: - CalculateEMA(rates_total, m_period, m_price, ma_buffer); + CalculateEMA(rates_total, start_index, m_period, m_price, ma_buffer); break; + case SMMA: - for(int i = start_pos; i < rates_total; i++) + for(int i = loop_start; i < rates_total; i++) { if(i == start_pos) { @@ -94,11 +133,13 @@ void CMovingAverageCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE pri ma_buffer[i]=sum/m_period; } else + // Recursive SMMA works incrementally because ma_buffer[i-1] is preserved ma_buffer[i]=(ma_buffer[i-1]*(m_period-1)+m_price[i])/m_period; } break; + case LWMA: - for(int i = start_pos; i < rates_total; i++) + for(int i = loop_start; i < rates_total; i++) { double sum=0, w_sum=0; for(int j=0; j