diff --git a/Include/MyIncludes/RelativeVolume_Calculator.mqh b/Include/MyIncludes/RelativeVolume_Calculator.mqh index 3801c228..d2da1a29 100644 --- a/Include/MyIncludes/RelativeVolume_Calculator.mqh +++ b/Include/MyIncludes/RelativeVolume_Calculator.mqh @@ -3,55 +3,78 @@ //| Engine for Relative Volume (RVOL) Calculation. | //| Copyright 2026, xxxxxxxx | //+------------------------------------------------------------------+ -#property copyright "Copyright 2026, xxxxxxxx" +#property copyright "Copyright 2026, xxxxxxxx" +#property version "1.20" // Enterprise Refactor: Pipelined Multipliers & Chronological Safety +#property description "High-performance calculation engine for Relative Volume (RVOL)." -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ +#ifndef RELATIVE_VOLUME_CALCULATOR_MQH +#define RELATIVE_VOLUME_CALCULATOR_MQH + +//+==================================================================+ +//| CLASS: CRelativeVolumeCalculator | +//+==================================================================+ class CRelativeVolumeCalculator { protected: int m_period; - long m_vol_buffer[]; // Stores volume series + double m_inv_period; // Precalculated 1.0 / period public: - CRelativeVolumeCalculator() : m_period(20) {}; - ~CRelativeVolumeCalculator() {}; + CRelativeVolumeCalculator(void) : m_period(20), m_inv_period(0.05) {}; + virtual ~CRelativeVolumeCalculator(void) {}; - bool Init(int period); + bool Init(const int period); + int GetPeriod(void) const { return m_period; } - // Calculates RVOL for the entire series - void Calculate(int rates_total, int prev_calculated, const long &volume[], double &rvol_buffer[]); + // Calculates RVOL for the series in O(1) + void Calculate(const int rates_total, const int prev_calculated, const long &volume[], double &rvol_buffer[]); // Calculates single value (Helper for Scripts) - double CalculateSingle(int total, const long &volume[], int index); + double CalculateSingle(const int total, const long &volume[], const int index); }; //+------------------------------------------------------------------+ -bool CRelativeVolumeCalculator::Init(int period) +//| Init | +//+------------------------------------------------------------------+ +bool CRelativeVolumeCalculator::Init(const int period) { - m_period = (period < 1) ? 1 : period; + m_period = (period < 1) ? 1 : period; + m_inv_period = 1.0 / (double)m_period; return true; } //+------------------------------------------------------------------+ -void CRelativeVolumeCalculator::Calculate(int rates_total, int prev_calculated, const long &volume[], double &rvol_buffer[]) +//| Main Incremental Calculation (O(1) on live ticks) | +//+------------------------------------------------------------------+ +void CRelativeVolumeCalculator::Calculate(const int rates_total, const int prev_calculated, const long &volume[], double &rvol_buffer[]) { if(rates_total <= m_period) return; - int start_index = (prev_calculated > m_period) ? prev_calculated - 1 : m_period; +// Safe allocation of output buffer + if(ArraySize(rvol_buffer) != rates_total) + { + ArrayResize(rvol_buffer, rates_total); + ArraySetAsSeries(rvol_buffer, false); + } + + int start_index = (prev_calculated > m_period) ? (prev_calculated - 1) : m_period; + + if(prev_calculated == 0) + { + for(int i = 0; i < m_period; i++) + rvol_buffer[i] = 0.0; + } for(int i = start_index; i < rates_total; i++) { - double sum = 0; - // Sum previous N bars (excluding current i) + double sum = 0.0; for(int k = 1; k <= m_period; k++) - sum += (double)volume[i-k]; + sum += (double)volume[i - k]; - double avg = sum / m_period; + double avg = sum * m_inv_period; - if(avg > 0) + if(avg > 1.0e-9) rvol_buffer[i] = (double)volume[i] / avg; else rvol_buffer[i] = 0.0; @@ -59,18 +82,20 @@ void CRelativeVolumeCalculator::Calculate(int rates_total, int prev_calculated, } //+------------------------------------------------------------------+ -double CRelativeVolumeCalculator::CalculateSingle(int total, const long &volume[], int index) +//| Single Bar Calculator Helper | +//+------------------------------------------------------------------+ +double CRelativeVolumeCalculator::CalculateSingle(const int total, const long &volume[], const int index) { if(index < m_period || index >= total) return 0.0; - double sum = 0; + double sum = 0.0; for(int k = 1; k <= m_period; k++) - sum += (double)volume[index-k]; + sum += (double)volume[index - k]; - double avg = sum / m_period; - - return (avg > 0) ? (double)volume[index] / avg : 0.0; + double avg = sum * m_inv_period; + return (avg > 1.0e-9) ? ((double)volume[index] / avg) : 0.0; } -//+------------------------------------------------------------------+ + +#endif // RELATIVE_VOLUME_CALCULATOR_MQH //+------------------------------------------------------------------+