From 5d9f92c6aebaf302bae8f8f245f7e3de07f27380 Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Sun, 21 Dec 2025 14:32:27 +0100 Subject: [PATCH] refactor: Optimized for incremental calculation --- .../MyIncludes/Gaussian_Filter_Calculator.mqh | 216 ++++++++++-------- 1 file changed, 123 insertions(+), 93 deletions(-) diff --git a/Include/MyIncludes/Gaussian_Filter_Calculator.mqh b/Include/MyIncludes/Gaussian_Filter_Calculator.mqh index 12ce4c2..d9786a9 100644 --- a/Include/MyIncludes/Gaussian_Filter_Calculator.mqh +++ b/Include/MyIncludes/Gaussian_Filter_Calculator.mqh @@ -1,50 +1,53 @@ //+------------------------------------------------------------------+ //| Gaussian_Filter_Calculator.mqh | //| Calculation engine for the John Ehlers' Gaussian Filter. | -//| VERSION 2.10: Corrected state management & centralized enums| +//| VERSION 3.00: Optimized for incremental calculation. | //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" #include -//--- Enums are now centralized here to be available for all consumers --- -enum ENUM_CANDLE_SOURCE { SOURCE_STD, SOURCE_HA }; enum ENUM_INPUT_SOURCE { SOURCE_PRICE, SOURCE_MOMENTUM }; +//+==================================================================+ +//| CLASS 1: CGaussianFilterCalculator | //+==================================================================+ class CGaussianFilterCalculator { protected: int m_period; ENUM_INPUT_SOURCE m_source_type; + + //--- Persistent Buffer for Price double m_price[]; //--- Filter coefficients double c0, a1, a2; - //--- State variables for the recursive filter (CRITICAL FIX) - double m_f1, m_f2; - - virtual bool PreparePriceSeries(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]); + //--- 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: - CGaussianFilterCalculator(void) : m_f1(0), m_f2(0) {}; // Initialize state + CGaussianFilterCalculator(void) {}; virtual ~CGaussianFilterCalculator(void) {}; bool Init(int period, ENUM_INPUT_SOURCE source_type); - void Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &filter_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 &filter_buffer[]); }; +//+------------------------------------------------------------------+ +//| Init | //+------------------------------------------------------------------+ bool CGaussianFilterCalculator::Init(int period, ENUM_INPUT_SOURCE source_type) { m_period = (period < 2) ? 2 : period; m_source_type = source_type; - m_f1 = 0; - m_f2 = 0; // Reset state on init - double beta = 2.451 * (1.0 - cos(2.0 * M_PI / m_period)); +// Calculate coefficients (Ehlers' formula) + double beta = 2.415 * (1.0 - cos(2.0 * M_PI / m_period)); double alpha = -beta + sqrt(beta * beta + 2.0 * beta); c0 = alpha * alpha; @@ -55,126 +58,153 @@ bool CGaussianFilterCalculator::Init(int period, ENUM_INPUT_SOURCE source_type) } //+------------------------------------------------------------------+ -void CGaussianFilterCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &filter_buffer[]) +//| Main Calculation (Optimized) | +//+------------------------------------------------------------------+ +void CGaussianFilterCalculator::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 &filter_buffer[]) { if(rates_total < 3) return; - if(!PreparePriceSeries(rates_total, price_type, open, high, low, close)) + + int start_index; + if(prev_calculated == 0) + start_index = 0; + else + start_index = prev_calculated - 1; + +// Resize internal buffer + if(ArraySize(m_price) != rates_total) + ArrayResize(m_price, rates_total); + + if(!PreparePriceSeries(rates_total, start_index, price_type, open, high, low, close)) return; -//--- On the very first calculation, initialize the first few values robustly - if(ArraySize(filter_buffer) == 0 || filter_buffer[0] == 0) +//--- Incremental Loop +// We start at index 2 because we need i-1 and i-2 + int loop_start = MathMax(2, start_index); + +// Initialization for the very first bars + if(loop_start == 2) { filter_buffer[0] = m_price[0]; filter_buffer[1] = m_price[1]; - m_f1 = filter_buffer[1]; - m_f2 = filter_buffer[0]; } - for(int i = 2; i < rates_total; i++) + for(int i = loop_start; i < rates_total; i++) { - double current_f = c0 * m_price[i] + a1 * m_f1 + a2 * m_f2; - filter_buffer[i] = current_f; - m_f2 = m_f1; - m_f1 = current_f; + // Recursive calculation: f[i] = c0*price[i] + a1*f[i-1] + a2*f[i-2] + // We use filter_buffer directly for f[i-1] and f[i-2] because it persists between ticks. + filter_buffer[i] = c0 * m_price[i] + a1 * filter_buffer[i-1] + a2 * filter_buffer[i-2]; } } //+------------------------------------------------------------------+ -bool CGaussianFilterCalculator::PreparePriceSeries(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) +//| Prepare Price (Standard - Optimized) | +//+------------------------------------------------------------------+ +bool CGaussianFilterCalculator::PreparePriceSeries(int rates_total, int start_index, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) { - ArrayResize(m_price, rates_total); - if(m_source_type == SOURCE_PRICE) + for(int i = start_index; i < rates_total; i++) { - switch(price_type) + if(m_source_type == SOURCE_PRICE) { - 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