From e2d9fd1fa0a537370054f6d5a82a0bcb13d2ff31 Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Sat, 3 Jan 2026 09:26:55 +0100 Subject: [PATCH] refactor(indicators): Optimized for incremental calculation --- ...Polynomial_Regression_Slope_Calculator.mqh | 253 ++++++++++-------- 1 file changed, 143 insertions(+), 110 deletions(-) diff --git a/Include/MyIncludes/Polynomial_Regression_Slope_Calculator.mqh b/Include/MyIncludes/Polynomial_Regression_Slope_Calculator.mqh index 326fc50..2432c64 100644 --- a/Include/MyIncludes/Polynomial_Regression_Slope_Calculator.mqh +++ b/Include/MyIncludes/Polynomial_Regression_Slope_Calculator.mqh @@ -1,47 +1,40 @@ //+------------------------------------------------------------------+ //| Polynomial_Regression_Slope_Calculator.mqh | //| Engine for the Polynomial Regression Slope oscillator. | +//| VERSION 2.00: Optimized for incremental calculation. | //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" #include +//+==================================================================+ +//| CLASS 1: CPolynomialRegressionSlopeCalculator | //+==================================================================+ class CPolynomialRegressionSlopeCalculator { protected: int m_period; + + //--- Persistent Buffer 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[]); + //--- 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: CPolynomialRegressionSlopeCalculator(void) {}; virtual ~CPolynomialRegressionSlopeCalculator(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[], + + //--- 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 &slope_buffer[]); }; //+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -class CPolynomialRegressionSlopeCalculator_HA : public CPolynomialRegressionSlopeCalculator - { -private: - CHeikinAshi_Calculator m_ha_calculator; -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; - }; // Full definition below - -//+==================================================================+ -//| METHOD IMPLEMENTATIONS | -//+==================================================================+ - -//+------------------------------------------------------------------+ -//| | +//| Init | //+------------------------------------------------------------------+ bool CPolynomialRegressionSlopeCalculator::Init(int period) { @@ -50,140 +43,180 @@ bool CPolynomialRegressionSlopeCalculator::Init(int period) } //+------------------------------------------------------------------+ -//| | +//| Main Calculation (Optimized) | //+------------------------------------------------------------------+ -void CPolynomialRegressionSlopeCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], +void CPolynomialRegressionSlopeCalculator::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 &slope_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 Buffer + if(ArraySize(m_price) != rates_total) + ArrayResize(m_price, 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; +//--- 4. Calculate Polynomial Regression Slope (Incremental Loop) + int loop_start = MathMax(m_period - 1, start_index); - for(int i = start_pos; i < rates_total; i++) +// Pre-calculate X sums (constant for fixed period) +// Optimization: Calculate once in Init? No, period might change? No, Init sets period. +// But let's keep it local for simplicity, or move to Init for speed. +// For N=50, it's fast enough. + + double sum_x=0, sum_x2=0, sum_x3=0, sum_x4=0; + for(int j = 0; j < m_period; j++) { - double sum_x=0, sum_y=0, sum_x2=0, sum_xy=0, sum_x3=0, sum_x4=0, sum_x2y=0; + double x = j; + sum_x += x; + sum_x2 += x*x; + sum_x3 += x*x*x; + sum_x4 += x*x*x*x; + } + + double n = m_period; + double D = n * (sum_x2 * sum_x4 - sum_x3 * sum_x3) - sum_x * (sum_x * sum_x4 - sum_x2 * sum_x3) + sum_x2 * (sum_x * sum_x3 - sum_x2 * sum_x2); + + if(MathAbs(D) < 1e-10) + return; // Should not happen for N >= 3 + + for(int i = loop_start; i < rates_total; i++) + { + double sum_y=0, sum_xy=0, sum_x2y=0; + + // Inner loop over the window [i - period + 1 ... i] for(int j = 0; j < m_period; j++) { double x = j; double y = m_price[i - m_period + 1 + j]; - sum_x += x; sum_y += y; - sum_x2 += x*x; sum_xy += x*y; - sum_x3 += x*x*x; - sum_x4 += x*x*x*x; sum_x2y += x*x*y; } - double b=0, c=0; - double n = m_period; - - double D = n * (sum_x2 * sum_x4 - sum_x3 * sum_x3) - sum_x * (sum_x * sum_x4 - sum_x2 * sum_x3) + sum_x2 * (sum_x * sum_x3 - sum_x2 * sum_x2); - if(MathAbs(D) < 1e-10) - continue; - double Db = n * (sum_xy * sum_x4 - sum_x2y * sum_x3) - sum_x * (sum_y * sum_x4 - sum_x2 * sum_x2y) + sum_x2 * (sum_y * sum_x3 - sum_x2 * sum_xy); double Dc = n * (sum_x2 * sum_x2y - sum_x3 * sum_xy) - sum_x * (sum_x * sum_x2y - sum_x2 * sum_xy) + sum_y * (sum_x * sum_x3 - sum_x2 * sum_x2); - b = Db / D; - c = Dc / D; + double b = Db / D; + double c = Dc / D; - //--- Calculate the slope at the current bar (x = n - 1) + //--- Calculate the slope (1st derivative) at the current bar (x = n - 1) + // y = a + bx + cx^2 + // y' = b + 2cx double x_current = n - 1; slope_buffer[i] = b + 2 * c * x_current; } } - //+------------------------------------------------------------------+ -//| | +//| Prepare Price (Standard - Optimized) | //+------------------------------------------------------------------+ -bool CPolynomialRegressionSlopeCalculator::PreparePriceSeries(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) +bool CPolynomialRegressionSlopeCalculator::PreparePriceSeries(int rates_total, int start_index, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) { - if(ArraySize(m_price) != rates_total) - if(ArrayResize(m_price, rates_total) != rates_total) - return false; - - switch(price_type) + for(int i = start_index; i < rates_total; i++) { - 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