From 5cddbdc76b9aa2ed34766e014f50abf8f205cc92 Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Tue, 16 Dec 2025 17:43:12 +0100 Subject: [PATCH] refactor: Optimized for incremental calculation --- Include/MyIncludes/CMO_Calculator.mqh | 228 +++++++++++++++----------- 1 file changed, 134 insertions(+), 94 deletions(-) diff --git a/Include/MyIncludes/CMO_Calculator.mqh b/Include/MyIncludes/CMO_Calculator.mqh index 285824d..f02c6a1 100644 --- a/Include/MyIncludes/CMO_Calculator.mqh +++ b/Include/MyIncludes/CMO_Calculator.mqh @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ //| CMO_Calculator.mqh | -//| Calculation engine for Standard and Heikin Ashi CMO. | +//| VERSION 2.00: Optimized for incremental calculation. | //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" @@ -8,28 +8,35 @@ #include //+==================================================================+ -//| | //| CLASS 1: CCMOCalculator (Base Class) | -//| | //+==================================================================+ class CCMOCalculator { protected: int m_cmo_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: CCMOCalculator(void) {}; virtual ~CCMOCalculator(void) {}; bool Init(int cmo_p); - void Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &cmo_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 &cmo_buffer[]); + + //--- NEW: Helper to get a single CMO value + // This assumes m_price is already prepared! + double GetCMOValue(int index); }; //+------------------------------------------------------------------+ -//| CCMOCalculator: Initialization | +//| Init | //+------------------------------------------------------------------+ bool CCMOCalculator::Init(int cmo_p) { @@ -38,129 +45,162 @@ bool CCMOCalculator::Init(int cmo_p) } //+------------------------------------------------------------------+ -//| CCMOCalculator: Main Calculation Method (Shared Logic) | +//| Main Calculation (Optimized) | //+------------------------------------------------------------------+ -void CCMOCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &cmo_buffer[]) +void CCMOCalculator::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 &cmo_buffer[]) { if(rates_total <= m_cmo_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; - for(int i = m_cmo_period; i < rates_total; i++) - { - double sum_up = 0.0, sum_down = 0.0; - for(int j = 0; j < m_cmo_period; j++) - { - double diff = m_price[i - j] - m_price[i - j - 1]; - if(diff > 0.0) - sum_up += diff; - else - sum_down += (-diff); - } +//--- 4. Calculate CMO (Incremental Loop) + int loop_start = MathMax(m_cmo_period, start_index); - double total_sum = sum_up + sum_down; - if(total_sum == 0.0) - cmo_buffer[i] = 0.0; - else - cmo_buffer[i] = 100.0 * (sum_up - sum_down) / total_sum; + for(int i = loop_start; i < rates_total; i++) + { + cmo_buffer[i] = GetCMOValue(i); } } //+------------------------------------------------------------------+ -//| CCMOCalculator: Prepares the standard source price. | +//| Helper: Calculate Single CMO Value | //+------------------------------------------------------------------+ -bool CCMOCalculator::PreparePriceSeries(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) +double CCMOCalculator::GetCMOValue(int index) { - ArrayResize(m_price, rates_total); - switch(price_type) + double sum_up = 0.0, sum_down = 0.0; + + for(int j = 0; j < m_cmo_period; j++) { - 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 0.0) + sum_up += diff; + else + sum_down += (-diff); + } + + double total_sum = sum_up + sum_down; + if(total_sum == 0.0) + return 0.0; + else + return 100.0 * (sum_up - sum_down) / total_sum; + } + +//+------------------------------------------------------------------+ +//| Prepare Price (Standard - Optimized) | +//+------------------------------------------------------------------+ +bool CCMOCalculator::PreparePriceSeries(int rates_total, int start_index, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) + { +// Optimized copy loop + for(int i = start_index; i < rates_total; i++) + { + switch(price_type) + { + case PRICE_CLOSE: + m_price[i] = close[i]; + break; + case PRICE_OPEN: + m_price[i] = open[i]; + break; + case PRICE_HIGH: + m_price[i] = high[i]; + break; + case PRICE_LOW: + m_price[i] = low[i]; + break; + case PRICE_MEDIAN: m_price[i] = (high[i]+low[i])/2.0; - break; - case PRICE_TYPICAL: - for(int i=0; i