//+------------------------------------------------------------------+ //| ZeroLag_EMA_Calculator.mqh | //| Calculation engine for the John Ehlers' Zero-Lag EMA. | //| VERSION 3.00: Optimized for incremental calculation. | //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" #include //+==================================================================+ //| CLASS 1: CZeroLagEMACalculator (Base Class) | //+==================================================================+ class CZeroLagEMACalculator { protected: int m_period; bool m_optimize_gain; double m_gain_limit; //--- Persistent Buffers for Incremental Calculation double m_price[]; //--- State Buffers for Standard Mode double m_ema1[]; double m_ema2[]; //--- State Buffers for Optimized Gain Mode double m_ema[]; double m_ec[]; //--- 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[]); public: CZeroLagEMACalculator(void) {}; virtual ~CZeroLagEMACalculator(void) {}; bool Init(int period, bool optimize_gain, double gain_limit); //--- 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 &zlema_buffer[]); }; //+------------------------------------------------------------------+ //| Init | //+------------------------------------------------------------------+ bool CZeroLagEMACalculator::Init(int period, bool optimize_gain, double gain_limit) { m_period = (period < 1) ? 1 : period; m_optimize_gain = optimize_gain; m_gain_limit = gain_limit; return true; } //+------------------------------------------------------------------+ //| Main Calculation (Optimized) | //+------------------------------------------------------------------+ void CZeroLagEMACalculator::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 &zlema_buffer[]) { if(rates_total < m_period * 2) return; int start_index; if(prev_calculated == 0) start_index = 0; else start_index = prev_calculated - 1; // Resize Buffers if(ArraySize(m_price) != rates_total) { ArrayResize(m_price, rates_total); if(!m_optimize_gain) { ArrayResize(m_ema1, rates_total); ArrayResize(m_ema2, rates_total); } else { ArrayResize(m_ema, rates_total); ArrayResize(m_ec, rates_total); } } if(!PreparePriceSeries(rates_total, start_index, price_type, open, high, low, close)) return; double alpha = 2.0 / (m_period + 1.0); if(!m_optimize_gain) { // --- Standard (Double EMA) Zero-Lag EMA Calculation --- int loop_start = MathMax(m_period, start_index); // Initialization if(loop_start == m_period) { double sum=0; for(int j=0; j