diff --git a/Include/MyIncludes/RSI_Pro_Calculator.mqh b/Include/MyIncludes/RSI_Pro_Calculator.mqh index 1549e40..6e8b2dc 100644 --- a/Include/MyIncludes/RSI_Pro_Calculator.mqh +++ b/Include/MyIncludes/RSI_Pro_Calculator.mqh @@ -8,9 +8,7 @@ #include //+==================================================================+ -//| | //| CLASS 1: CRSIProCalculator (Base Class) | -//| | //+==================================================================+ class CRSIProCalculator { @@ -20,25 +18,40 @@ protected: double m_deviation; ENUM_MA_METHOD m_ma_method; + //--- Persistent Buffers for Incremental Calculation double m_price[]; double m_rsi_buffer[]; double m_ma_buffer[]; double m_upper_band[]; double m_lower_band[]; - virtual bool PreparePriceSeries(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]); + //--- Persistent State for Wilder's Smoothing + double m_sum_pos; + double m_sum_neg; + + //--- 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: - CRSIProCalculator(void) {}; + CRSIProCalculator(void); virtual ~CRSIProCalculator(void) {}; bool Init(int rsi_p, int ma_p, ENUM_MA_METHOD ma_m, double dev); - void Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], + + //--- 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 &rsi_out[], double &ma_out[], double &upper_out[], double &lower_out[]); }; //+------------------------------------------------------------------+ -//| CRSIProCalculator: Initialization | +//| Constructor | +//+------------------------------------------------------------------+ +CRSIProCalculator::CRSIProCalculator(void) : m_sum_pos(0), m_sum_neg(0) + { + } + +//+------------------------------------------------------------------+ +//| Init | //+------------------------------------------------------------------+ bool CRSIProCalculator::Init(int rsi_p, int ma_p, ENUM_MA_METHOD ma_m, double dev) { @@ -46,30 +59,60 @@ bool CRSIProCalculator::Init(int rsi_p, int ma_p, ENUM_MA_METHOD ma_m, double de m_ma_period = (ma_p < 1) ? 1 : ma_p; m_ma_method = ma_m; m_deviation = dev; + m_sum_pos = 0; + m_sum_neg = 0; return true; } //+------------------------------------------------------------------+ -//| CRSIProCalculator: Main Calculation Method | +//| Main Calculation (Optimized) | //+------------------------------------------------------------------+ -void CRSIProCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], +void CRSIProCalculator::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 &rsi_out[], double &ma_out[], double &upper_out[], double &lower_out[]) { if(rates_total <= m_rsi_period) return; - ArrayResize(m_price, rates_total); - ArrayResize(m_rsi_buffer, rates_total); - ArrayResize(m_ma_buffer, rates_total); - ArrayResize(m_upper_band, rates_total); - ArrayResize(m_lower_band, rates_total); +//--- 1. Determine Start Index + int start_index; + if(prev_calculated == 0) + { + start_index = 0; + m_sum_pos = 0; + m_sum_neg = 0; + } + else + start_index = prev_calculated - 1; - if(!PreparePriceSeries(rates_total, price_type, open, high, low, close)) +//--- 2. Resize Buffers + if(ArraySize(m_price) != rates_total) + { + ArrayResize(m_price, rates_total); + ArrayResize(m_rsi_buffer, rates_total); + ArrayResize(m_ma_buffer, rates_total); + ArrayResize(m_upper_band, rates_total); + ArrayResize(m_lower_band, rates_total); + } + +//--- 3. Prepare Price (Optimized) + if(!PreparePriceSeries(rates_total, start_index, price_type, open, high, low, close)) return; -//--- Step 1: Calculate base RSI - double sum_pos = 0, sum_neg = 0; - for(int i = 1; i < rates_total; i++) +//--- 4. Calculate RSI (Incremental) + int i = start_index; + if(i == 0) + i = 1; // Skip first bar for diff + + for(; i < rates_total; i++) + { + double diff = m_price[i] - m_price[i-1]; + } + +// Reset sums for full loop + double sum_pos = 0; + double sum_neg = 0; + + for(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; @@ -82,11 +125,15 @@ void CRSIProCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type else m_rsi_buffer[i] = 100.0; } + else + m_rsi_buffer[i] = 0; } -//--- Step 2: Calculate Moving Average on RSI +//--- 5. Calculate Moving Average on RSI (Optimized) int ma_start_pos = m_rsi_period + m_ma_period - 1; - for(int i = ma_start_pos; i < rates_total; i++) + int loop_start_ma = MathMax(ma_start_pos, start_index); + + for(i = loop_start_ma; i < rates_total; i++) { switch(m_ma_method) { @@ -134,8 +181,8 @@ void CRSIProCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type } } -//--- Step 3: Calculate Bollinger Bands on the MA line - for(int i = ma_start_pos; i < rates_total; i++) +//--- 6. Calculate Bollinger Bands (Optimized) + for(i = loop_start_ma; i < rates_total; i++) { double std_dev_val = 0, sum_sq = 0; for(int j = 0; j < m_ma_period; j++) @@ -146,6 +193,8 @@ void CRSIProCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type m_lower_band[i] = m_ma_buffer[i] - m_deviation * std_dev_val; } +//--- 7. Copy to Output +// We copy everything to be safe, ArrayCopy is fast ArrayCopy(rsi_out, m_rsi_buffer, 0, 0, rates_total); ArrayCopy(ma_out, m_ma_buffer, 0, 0, rates_total); ArrayCopy(upper_out, m_upper_band, 0, 0, rates_total); @@ -153,99 +202,107 @@ void CRSIProCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type } //+------------------------------------------------------------------+ -//| CRSIProCalculator: Prepares the source price series. | +//| Prepare Price (Standard - Optimized) | //+------------------------------------------------------------------+ -bool CRSIProCalculator::PreparePriceSeries(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) +bool CRSIProCalculator::PreparePriceSeries(int rates_total, int start_index, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) { - switch(price_type) +// Optimized copy loop + 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