From b18512c092908aa50d4a0310a8edfa9a708a820d Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Mon, 5 Jan 2026 10:01:22 +0100 Subject: [PATCH] refactor(indicators): Optimized for incremental calculation --- Include/MyIncludes/MADH_Calculator.mqh | 185 +++++++++++++++---------- 1 file changed, 112 insertions(+), 73 deletions(-) diff --git a/Include/MyIncludes/MADH_Calculator.mqh b/Include/MyIncludes/MADH_Calculator.mqh index b6beae8..54bbac3 100644 --- a/Include/MyIncludes/MADH_Calculator.mqh +++ b/Include/MyIncludes/MADH_Calculator.mqh @@ -1,6 +1,7 @@ //+------------------------------------------------------------------+ //| MADH_Calculator.mqh | //| Calculation engine for the John Ehlers' MADH indicator. | +//| VERSION 2.00: Optimized for incremental calculation. | //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" @@ -8,30 +9,35 @@ #include //+==================================================================+ -//| | //| CLASS 1: CMADHCalculator (Base Class) | -//| | //+==================================================================+ class CMADHCalculator { protected: int m_short_len; int m_dom_cycle; + + //--- Persistent Buffer for Incremental Calculation double m_price[]; // Helper function to calculate a Hann-windowed Moving Average double CalcHWMA(int position, int period, const double &price_array[]); - 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: CMADHCalculator(void) {}; virtual ~CMADHCalculator(void) {}; bool Init(int short_len, int dom_cycle); - void Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &madh_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 &madh_buffer[]); }; +//+------------------------------------------------------------------+ +//| Init | //+------------------------------------------------------------------+ bool CMADHCalculator::Init(int short_len, int dom_cycle) { @@ -51,10 +57,12 @@ double CMADHCalculator::CalcHWMA(int position, int period, const double &price_a double sum = 0; double coef_sum = 0; +// Optimization: Pre-calculate weights in Init? +// Since period can be different (short vs long), we keep it local or use a map. +// For typical periods, local calculation is fast enough. + for(int i = 0; i < period; i++) { - // Ehlers' code uses count from 1 to Length, accessing Close[count-1]. - // This corresponds to i from 0 to period-1, accessing price[position-i]. double weight = 1.0 - cos(2 * M_PI * (i + 1.0) / (period + 1.0)); sum += weight * price_array[position - i]; coef_sum += weight; @@ -67,15 +75,33 @@ double CMADHCalculator::CalcHWMA(int position, int period, const double &price_a } //+------------------------------------------------------------------+ -void CMADHCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &madh_buffer[]) +//| Main Calculation (Optimized) | +//+------------------------------------------------------------------+ +void CMADHCalculator::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 &madh_buffer[]) { int long_len = m_short_len + (int)round(m_dom_cycle / 2.0); if(rates_total < long_len) 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; - for(int i = long_len - 1; i < rates_total; i++) +//--- 4. Calculate MADH (Incremental Loop) + int loop_start = MathMax(long_len - 1, start_index); + + for(int i = loop_start; i < rates_total; i++) { // Step 1 & 2: Calculate the two HWMA filters double filt1 = CalcHWMA(i, m_short_len, m_price); @@ -86,94 +112,107 @@ void CMADHCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, { madh_buffer[i] = 100.0 * (filt1 - filt2) / filt2; } + else + { + madh_buffer[i] = 0; + } } } //+------------------------------------------------------------------+ -bool CMADHCalculator::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 CMADHCalculator::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); - 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