Files
mql5/Include/MyIncludes/RelativeVolume_Calculator.mqh
T

102 lines
3.7 KiB
Plaintext

//+------------------------------------------------------------------+
//| RelativeVolume_Calculator.mqh |
//| Engine for Relative Volume (RVOL) Calculation. |
//| 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;
double m_inv_period; // Precalculated 1.0 / period
public:
CRelativeVolumeCalculator(void) : m_period(20), m_inv_period(0.05) {};
virtual ~CRelativeVolumeCalculator(void) {};
bool Init(const int period);
int GetPeriod(void) const { return m_period; }
// 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(const int total, const long &volume[], const int index);
};
//+------------------------------------------------------------------+
//| Init |
//+------------------------------------------------------------------+
bool CRelativeVolumeCalculator::Init(const int period)
{
m_period = (period < 1) ? 1 : period;
m_inv_period = 1.0 / (double)m_period;
return true;
}
//+------------------------------------------------------------------+
//| 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;
// 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.0;
for(int k = 1; k <= m_period; k++)
sum += (double)volume[i - k];
double avg = sum * m_inv_period;
if(avg > 1.0e-9)
rvol_buffer[i] = (double)volume[i] / avg;
else
rvol_buffer[i] = 0.0;
}
}
//+------------------------------------------------------------------+
//| 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.0;
for(int k = 1; k <= m_period; k++)
sum += (double)volume[index - k];
double avg = sum * m_inv_period;
return (avg > 1.0e-9) ? ((double)volume[index] / avg) : 0.0;
}
#endif // RELATIVE_VOLUME_CALCULATOR_MQH
//+------------------------------------------------------------------+