From 7a2e518c32abd353446d515bb97c725f9769c89f Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Wed, 31 Dec 2025 18:25:35 +0100 Subject: [PATCH] refactor(indicators): Optimized for incremental calculation --- Include/MyIncludes/CHO_Calculator.mqh | 166 +++++++++----------------- 1 file changed, 57 insertions(+), 109 deletions(-) diff --git a/Include/MyIncludes/CHO_Calculator.mqh b/Include/MyIncludes/CHO_Calculator.mqh index 0ccecd3..7f6630f 100644 --- a/Include/MyIncludes/CHO_Calculator.mqh +++ b/Include/MyIncludes/CHO_Calculator.mqh @@ -1,63 +1,66 @@ //+------------------------------------------------------------------+ //| CHO_Calculator.mqh | //| Calculation engine for Standard and Heikin Ashi CHO. | +//| VERSION 3.00: Optimized for incremental calculation. | //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" -//--- Re-use the AD calculator we built previously --- #include +#include //+==================================================================+ -//| | //| CLASS 1: CCHOCalculator (Base Class) | -//| | //+==================================================================+ class CCHOCalculator { protected: int m_fast_period; int m_slow_period; - ENUM_MA_METHOD m_ma_method; - ENUM_APPLIED_VOLUME m_volume_type; - //--- It contains a pointer to a base AD calculator + //--- Composition: AD Calculator + 2 MA Engines CADCalculator *m_ad_calculator; + CMovingAverageCalculator m_fast_ma_engine; + CMovingAverageCalculator m_slow_ma_engine; + + //--- Persistent Buffers for Incremental Calculation + double m_adl_buffer[]; + double m_fast_ma_buffer[]; + double m_slow_ma_buffer[]; public: CCHOCalculator(void); virtual ~CCHOCalculator(void); - //--- Public methods - bool Init(int fast_p, int slow_p, ENUM_MA_METHOD ma_m, ENUM_APPLIED_VOLUME vol_t); + //--- Init now takes ENUM_MA_TYPE + bool Init(int fast_p, int slow_p, ENUM_MA_TYPE ma_m, ENUM_APPLIED_VOLUME vol_t); int GetSlowPeriod(void) const { return m_slow_period; } - //--- CORRECTED: Added 'open' array to the signature - void Calculate(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], double &cho_buffer[]); + + //--- Updated: Accepts prev_calculated + void Calculate(int rates_total, int prev_calculated, const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], ENUM_APPLIED_VOLUME volume_type, double &cho_buffer[]); }; //+------------------------------------------------------------------+ -//| CCHOCalculator: Constructor | +//| Constructor | //+------------------------------------------------------------------+ CCHOCalculator::CCHOCalculator(void) { -//--- The base class creates a standard AD calculator instance m_ad_calculator = new CADCalculator(); } //+------------------------------------------------------------------+ -//| CCHOCalculator: Destructor | +//| Destructor | //+------------------------------------------------------------------+ CCHOCalculator::~CCHOCalculator(void) { -//--- Clean up the contained object if(CheckPointer(m_ad_calculator) != POINTER_INVALID) delete m_ad_calculator; } //+------------------------------------------------------------------+ -//| CCHOCalculator: Initialization | +//| Init | //+------------------------------------------------------------------+ -bool CCHOCalculator::Init(int fast_p, int slow_p, ENUM_MA_METHOD ma_m, ENUM_APPLIED_VOLUME vol_t) +bool CCHOCalculator::Init(int fast_p, int slow_p, ENUM_MA_TYPE ma_m, ENUM_APPLIED_VOLUME vol_t) { m_fast_period = (fast_p < 1) ? 1 : fast_p; m_slow_period = (slow_p < 1) ? 1 : slow_p; @@ -69,109 +72,60 @@ bool CCHOCalculator::Init(int fast_p, int slow_p, ENUM_MA_METHOD ma_m, ENUM_APPL m_slow_period = temp; } - m_ma_method = ma_m; - m_volume_type = vol_t; +// Initialize MA Engines + if(!m_fast_ma_engine.Init(m_fast_period, ma_m)) + return false; + if(!m_slow_ma_engine.Init(m_slow_period, ma_m)) + return false; return (CheckPointer(m_ad_calculator) != POINTER_INVALID); } //+------------------------------------------------------------------+ -//| CCHOCalculator: Main Calculation Method | +//| Main Calculation (Optimized) | //+------------------------------------------------------------------+ -void CCHOCalculator::Calculate(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], double &cho_buffer[]) +void CCHOCalculator::Calculate(int rates_total, int prev_calculated, const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], ENUM_APPLIED_VOLUME volume_type, double &cho_buffer[]) { if(rates_total < m_slow_period || CheckPointer(m_ad_calculator) == POINTER_INVALID) return; -//--- Internal buffers - double adl[], fast_ma[], slow_ma[]; - ArrayResize(adl, rates_total); - ArrayResize(fast_ma, rates_total); - ArrayResize(slow_ma, rates_total); - -//--- STEP 1: Calculate ADL using the contained calculator -//--- CORRECTED: Pass the 'open' array to the AD calculator - m_ad_calculator.Calculate(rates_total, open, high, low, close, tick_volume, volume, m_volume_type, adl); - -//--- STEP 2: Calculate Fast MA on ADL - for(int i = m_fast_period - 1; i < rates_total; i++) +// Resize internal buffers + if(ArraySize(m_adl_buffer) != rates_total) { - switch(m_ma_method) - { - case MODE_EMA: - case MODE_SMMA: - if(i == m_fast_period - 1) - { - double sum=0; - for(int j=0; j0) fast_ma[i]=lwma_sum/weight_sum;} - break; - default: - {double sum=0; for(int j=0; j0) slow_ma[i]=lwma_sum/weight_sum;} - break; - default: - {double sum=0; for(int j=0; j 0) ? prev_calculated - 1 : 0; + int loop_start = MathMax(m_slow_period - 1, start_index); + + if(prev_calculated == 0) + ArrayInitialize(cho_buffer, EMPTY_VALUE); + + for(int i = loop_start; i < rates_total; i++) { - cho_buffer[i] = fast_ma[i] - slow_ma[i]; + if(m_fast_ma_buffer[i] != EMPTY_VALUE && m_slow_ma_buffer[i] != EMPTY_VALUE) + cho_buffer[i] = m_fast_ma_buffer[i] - m_slow_ma_buffer[i]; + else + cho_buffer[i] = EMPTY_VALUE; } } //+==================================================================+ -//| | -//| CLASS 2: CCHOCalculator_HA (Heikin Ashi) | -//| | +//| CLASS 2: CCHOCalculator_HA (Heikin Ashi) | //+==================================================================+ class CCHOCalculator_HA : public CCHOCalculator { @@ -180,26 +134,20 @@ public: }; //+------------------------------------------------------------------+ -//| CCHOCalculator_HA: Constructor | +//| | //+------------------------------------------------------------------+ CCHOCalculator_HA::CCHOCalculator_HA(void) { -//--- Clean up the base class's standard calculator first if(CheckPointer(m_ad_calculator) != POINTER_INVALID) delete m_ad_calculator; - -//--- The derived class creates a Heikin Ashi AD calculator instance instead +// Use HA version of AD calculator m_ad_calculator = new CADCalculator_HA(); } //+==================================================================+ -//| | -//| CLASS 3: CCHOCalculator_Std (Standard) | -//| | +//| CLASS 3: CCHOCalculator_Std (Standard) | //+==================================================================+ -// This is just for consistency in naming, it inherits everything from the base. class CCHOCalculator_Std : public CCHOCalculator { }; //+------------------------------------------------------------------+ -//+------------------------------------------------------------------+