diff --git a/Include/MyIncludes/VIDYA_RSI_Calculator.mqh b/Include/MyIncludes/VIDYA_RSI_Calculator.mqh index 0b40e49..25d56d9 100644 --- a/Include/MyIncludes/VIDYA_RSI_Calculator.mqh +++ b/Include/MyIncludes/VIDYA_RSI_Calculator.mqh @@ -1,70 +1,126 @@ //+------------------------------------------------------------------+ //| VIDYA_RSI_Calculator.mqh | -//| Calculation engine for VIDYA based on RSI. | +//| VERSION 2.00: Integrated with RSI Engine. | //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" #include +#include +//+==================================================================+ +//| CLASS 1: CVIDYARSICalculator (Base Class) | //+==================================================================+ class CVIDYARSICalculator { protected: int m_rsi_period, m_ema_period; - 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[]); + //--- Composition: Use dedicated RSI engine + CRSIProCalculator *m_rsi_calculator; + + //--- Persistent Buffers + double m_price[]; + double m_rsi_buffer[]; // Internal buffer for RSI values + + //--- 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[]); + + //--- Factory Method for RSI Engine + virtual void CreateRSIEngine(void); public: - CVIDYARSICalculator(void) {}; - virtual ~CVIDYARSICalculator(void) {}; + CVIDYARSICalculator(void); + virtual ~CVIDYARSICalculator(void); bool Init(int rsi_p, int ema_p); - void Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &vidya_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 &vidya_buffer[]); }; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CVIDYARSICalculator::CVIDYARSICalculator(void) + { + m_rsi_calculator = NULL; + } + +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CVIDYARSICalculator::~CVIDYARSICalculator(void) + { + if(CheckPointer(m_rsi_calculator) != POINTER_INVALID) + delete m_rsi_calculator; + } + +//+------------------------------------------------------------------+ +//| Factory Method | +//+------------------------------------------------------------------+ +void CVIDYARSICalculator::CreateRSIEngine(void) + { + m_rsi_calculator = new CRSIProCalculator(); + } + +//+------------------------------------------------------------------+ +//| Init | //+------------------------------------------------------------------+ bool CVIDYARSICalculator::Init(int rsi_p, int ema_p) { m_rsi_period = (rsi_p < 1) ? 1 : rsi_p; m_ema_period = (ema_p < 1) ? 1 : ema_p; + + CreateRSIEngine(); +// Init RSI with dummy MA params (1, SMA, 2.0) as we only need the RSI line + if(CheckPointer(m_rsi_calculator) == POINTER_INVALID || !m_rsi_calculator.Init(m_rsi_period, 1, SMA, 2.0)) + return false; + return true; } //+------------------------------------------------------------------+ -void CVIDYARSICalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &vidya_buffer[]) +//| Main Calculation (Optimized) | +//+------------------------------------------------------------------+ +void CVIDYARSICalculator::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 &vidya_buffer[]) { int start_pos = m_rsi_period + m_ema_period; if(rates_total <= start_pos) return; - if(!PreparePriceSeries(rates_total, price_type, open, high, low, close)) + + int start_index; + if(prev_calculated == 0) + start_index = 0; + else + start_index = prev_calculated - 1; + +// Resize Buffers + if(ArraySize(m_price) != rates_total) + ArrayResize(m_price, rates_total); + if(ArraySize(m_rsi_buffer) != rates_total) + ArrayResize(m_rsi_buffer, rates_total); + +// 1. Prepare Price (for VIDYA calculation) + if(!PreparePriceSeries(rates_total, start_index, price_type, open, high, low, close)) return; - double rsi_buffer[]; - ArrayResize(rsi_buffer, rates_total); +// 2. Calculate RSI (Delegated to Engine) +// Note: RSI engine handles its own price preparation internally! +// We pass the raw OHLC arrays and price_type. + double dummy1[], dummy2[], dummy3[]; + m_rsi_calculator.Calculate(rates_total, prev_calculated, price_type, open, high, low, close, + m_rsi_buffer, dummy1, dummy2, dummy3); -//--- STEP 1: Calculate RSI (Wilder's smoothing) - Logic from RSI_Pro_Calculator - double sum_pos = 0, sum_neg = 0; - for(int i = 1; i < rates_total; i++) - { - double diff = m_price[i] - m_price[i-1]; - sum_pos = (sum_pos * (m_rsi_period - 1) + (diff > 0 ? diff : 0)) / m_rsi_period; - sum_neg = (sum_neg * (m_rsi_period - 1) + (diff < 0 ? -diff : 0)) / m_rsi_period; - if(i >= m_rsi_period) - { - if(sum_neg > 0) - rsi_buffer[i] = 100.0 - (100.0 / (1.0 + (sum_pos / sum_neg))); - else - rsi_buffer[i] = 100.0; - } - } - -//--- STEP 2: Calculate VIDYA using RSI as volatility factor +// 3. Calculate VIDYA (Incremental Loop) double alpha = 2.0 / (m_ema_period + 1.0); - for(int i = 1; i < rates_total; i++) + int loop_start = MathMax(start_pos, start_index); + + for(int i = loop_start; i < rates_total; i++) { - if(i == start_pos) + if(i == start_pos) // Initialization { double sum=0; for(int j=0; j start_pos) - { - //--- CRITICAL: Create volatility factor from RSI's distance from 50 - double rsi_volatility = MathAbs(rsi_buffer[i] - 50.0) / 50.0; - vidya_buffer[i] = m_price[i] * alpha * rsi_volatility + vidya_buffer[i-1] * (1 - alpha * rsi_volatility); - } + + // Use pre-calculated RSI from buffer + // Volatility factor: distance from 50 (0..50), normalized to 0..1 + double rsi_volatility = MathAbs(m_rsi_buffer[i] - 50.0) / 50.0; + + // Recursive calculation uses vidya_buffer[i-1] which is persistent + vidya_buffer[i] = m_price[i] * alpha * rsi_volatility + vidya_buffer[i-1] * (1 - alpha * rsi_volatility); } } -// ... (A PreparePriceSeries és a _HA osztály PONTOSAN UGYANAZ MARAD, mint a VIDYA_Calculator-ban) ... -bool CVIDYARSICalculator::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 CVIDYARSICalculator::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