From fcdfc0bc47f32d4c7ae4f7421ec220fc0d0d0322 Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Fri, 28 Nov 2025 19:42:44 +0100 Subject: [PATCH] refactor: Optimized for incremental calculation --- .../MyIncludes/Laguerre_RSI_Calculator.mqh | 156 ++++++++---------- 1 file changed, 70 insertions(+), 86 deletions(-) diff --git a/Include/MyIncludes/Laguerre_RSI_Calculator.mqh b/Include/MyIncludes/Laguerre_RSI_Calculator.mqh index 6372bb1..f39b598 100644 --- a/Include/MyIncludes/Laguerre_RSI_Calculator.mqh +++ b/Include/MyIncludes/Laguerre_RSI_Calculator.mqh @@ -1,12 +1,12 @@ //+------------------------------------------------------------------+ //| Laguerre_RSI_Calculator.mqh | -//| VERSION 1.10: Added optional signal line. | +//| VERSION 1.20: Optimized for incremental calculation. | //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" #include -#include // For ENUM_MA_TYPE +#include //+==================================================================+ class CLaguerreRSICalculator @@ -16,46 +16,92 @@ protected: int m_signal_period; ENUM_MA_TYPE m_signal_ma_type; - void CalculateMA(const double &source_array[], double &dest_array[], int period, ENUM_MA_TYPE method, int start_pos); + //--- Internal MA Calculator for Signal Line (Optimization) + CMovingAverageCalculator *m_ma_calculator; public: - CLaguerreRSICalculator(void) { m_engine = new CLaguerreEngine(); }; - virtual ~CLaguerreRSICalculator(void) { if(CheckPointer(m_engine) != POINTER_INVALID) delete m_engine; }; + CLaguerreRSICalculator(void); + virtual ~CLaguerreRSICalculator(void); bool Init(double gamma, int signal_p, ENUM_MA_TYPE signal_ma); - 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 &lrsi_buffer[], double &signal_buffer[]); }; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CLaguerreRSICalculator::CLaguerreRSICalculator(void) + { + m_engine = new CLaguerreEngine(); + m_ma_calculator = new CMovingAverageCalculator(); + } + +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CLaguerreRSICalculator::~CLaguerreRSICalculator(void) + { + if(CheckPointer(m_engine) != POINTER_INVALID) + delete m_engine; + if(CheckPointer(m_ma_calculator) != POINTER_INVALID) + delete m_ma_calculator; + } + +//+------------------------------------------------------------------+ +//| Init | //+------------------------------------------------------------------+ bool CLaguerreRSICalculator::Init(double gamma, int signal_p, ENUM_MA_TYPE signal_ma) { m_signal_period = (signal_p < 1) ? 1 : signal_p; m_signal_ma_type = signal_ma; - return m_engine.Init(gamma, SOURCE_PRICE); + + if(!m_engine.Init(gamma, SOURCE_PRICE)) + return false; + if(!m_ma_calculator.Init(m_signal_period, m_signal_ma_type)) + return false; + + return true; } //+------------------------------------------------------------------+ -void CLaguerreRSICalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], +//| Main Calculation (Optimized) | +//+------------------------------------------------------------------+ +void CLaguerreRSICalculator::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 &lrsi_buffer[], double &signal_buffer[]) { if(rates_total < 2) return; - double L0[], L1[], L2[], L3[], dummy_filt[]; - m_engine.CalculateFilter(rates_total, price_type, open, high, low, close, L0, L1, L2, L3, dummy_filt); +//--- 1. Calculate Laguerre Components (Incremental) + double dummy_filt[]; // We don't use the filter output here, just internal state + m_engine.CalculateFilter(rates_total, prev_calculated, price_type, open, high, low, close, dummy_filt); - for(int i = 1; i < rates_total; i++) +//--- 2. Retrieve L0..L3 buffers + double L0[], L1[], L2[], L3[]; + m_engine.GetLBuffers(L0, L1, L2, L3); + +//--- 3. Calculate LRSI (Incremental Loop) + int start_index = (prev_calculated > 0) ? prev_calculated - 1 : 1; + if(start_index < 1) + start_index = 1; + + for(int i = start_index; i < rates_total; i++) { double cu = 0.0, cd = 0.0; + if(L0[i] >= L1[i]) cu = L0[i] - L1[i]; else cd = L1[i] - L0[i]; + if(L1[i] >= L2[i]) cu += L1[i] - L2[i]; else cd += L2[i] - L1[i]; + if(L2[i] >= L3[i]) cu += L2[i] - L3[i]; else @@ -65,90 +111,27 @@ void CLaguerreRSICalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price if(cu + cd > 0.0) lrsi_value = 100.0 * cu / (cu + cd); else - lrsi_value = (i > 0) ? lrsi_buffer[i-1] : 50.0; + lrsi_value = (i > 0) ? lrsi_buffer[i-1] : 50.0; // Fallback to previous or neutral + // Clamp if(lrsi_value > 100.0) lrsi_value = 100.0; if(lrsi_value < 0.0) lrsi_value = 0.0; + lrsi_buffer[i] = lrsi_value; } -//--- Step 2: Calculate Signal Line on the LRSI buffer --- - int signal_start = m_signal_period + 1; // LRSI starts at index 1, so we need more bars - CalculateMA(lrsi_buffer, signal_buffer, m_signal_period, m_signal_ma_type, signal_start); - } - -//+------------------------------------------------------------------+ -void CLaguerreRSICalculator::CalculateMA(const double &source_array[], double &dest_array[], int period, ENUM_MA_TYPE method, int start_pos) - { - for(int i = start_pos; i < ArraySize(source_array); i++) - { - switch(method) - { - case EMA: - case SMMA: - if(i == start_pos) - { - double sum=0; - int count=0; - for(int j=0; j 0) - dest_array[i]=sum/count; - } - else - { - if(method==EMA) - { - double pr=2.0/(period+1.0); - dest_array[i]=source_array[i]*pr+dest_array[i-1]*(1.0-pr); - } - else - dest_array[i]=(dest_array[i-1]*(period-1)+source_array[i])/period; - } - break; - case LWMA: - { - double sum=0, w_sum=0; - for(int j=0; j0) - dest_array[i]=sum/w_sum; - } - break; - default: // SMA - { - double sum=0; - int count=0; - for(int j=0; j 0) - dest_array[i]=sum/count; - } - break; - } - } +//--- 4. Calculate Signal Line (Using Optimized Engine) +// We pass lrsi_buffer as the 'close' price for the MA calculator. +// The other arrays (open, high, low) are dummy, but we pass lrsi_buffer to be safe. + m_ma_calculator.Calculate(rates_total, prev_calculated, PRICE_CLOSE, + lrsi_buffer, lrsi_buffer, lrsi_buffer, lrsi_buffer, + signal_buffer); } +//+==================================================================+ +//| CLASS 2: CLaguerreRSICalculator_HA | //+==================================================================+ class CLaguerreRSICalculator_HA : public CLaguerreRSICalculator { @@ -158,7 +141,8 @@ public: if(CheckPointer(m_engine) != POINTER_INVALID) delete m_engine; m_engine = new CLaguerreEngine_HA(); + + // m_ma_calculator is already created in base constructor }; }; //+------------------------------------------------------------------+ -//+------------------------------------------------------------------+