From 659c64167f2f6a425ea70746fd704ca1aba81ec7 Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Tue, 21 Oct 2025 10:57:16 +0200 Subject: [PATCH] refactor: Added optional Noise Elimination Technology (NET) --- Include/MyIncludes/RSIH_Calculator.mqh | 75 ++++++++++++++++---------- 1 file changed, 46 insertions(+), 29 deletions(-) diff --git a/Include/MyIncludes/RSIH_Calculator.mqh b/Include/MyIncludes/RSIH_Calculator.mqh index f289dab..d9af203 100644 --- a/Include/MyIncludes/RSIH_Calculator.mqh +++ b/Include/MyIncludes/RSIH_Calculator.mqh @@ -1,6 +1,7 @@ //+------------------------------------------------------------------+ //| RSIH_Calculator.mqh | -//| Calculation engine for Ehlers' RSI with Hann Windowing. | +//| Calculation engine for Ehlers' RSI with Hann Windowing (RSIH) | +//| and Noise Elimination Technology (NET). | //| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" @@ -15,7 +16,8 @@ class CRSIHCalculator { protected: - int m_period; + int m_period_rsi; + int m_period_net; 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[]); @@ -24,57 +26,72 @@ public: CRSIHCalculator(void) {}; virtual ~CRSIHCalculator(void) {}; - bool Init(int period); - void Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &rsih_buffer[]); + bool Init(int rsi_period, int net_period); + void Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], + double &rsih_buffer[], double &net_buffer[]); }; //+------------------------------------------------------------------+ -bool CRSIHCalculator::Init(int period) +bool CRSIHCalculator::Init(int rsi_period, int net_period) { - m_period = (period < 2) ? 2 : period; + m_period_rsi = (rsi_period < 2) ? 2 : rsi_period; + m_period_net = (net_period < 2) ? 2 : net_period; return true; } //+------------------------------------------------------------------+ -//| RESTORED: Original, definition-true FIR-based calculation | -//| based on Ehlers' EasyLanguage code. | -//+------------------------------------------------------------------+ -void CRSIHCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &rsih_buffer[]) +void CRSIHCalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], + double &rsih_buffer[], double &net_buffer[]) { - if(rates_total < m_period + 1) + if(rates_total < m_period_rsi + 1) return; if(!PreparePriceSeries(rates_total, price_type, open, high, low, close)) return; -// Full recalculation for stability - for(int i = m_period; i < rates_total; i++) +// --- Step 1: Calculate the base RSIH indicator --- + for(int i = m_period_rsi; i < rates_total; i++) { - double cu = 0.0; - double cd = 0.0; - - // Inner loop to calculate Hann-windowed CU and CD over the lookback period - for(int j = 1; j <= m_period; j++) + double cu = 0.0, cd = 0.0; + for(int j = 1; j <= m_period_rsi; j++) { - // Ehlers' EasyLanguage: Close[count-1] - Close[count] - // In our chronological array (non-timeseries), this corresponds to: - // count=1 -> m_price[i-1] - m_price[i] (most recent) - // count=m_period -> m_price[i-m_period] - m_price[i-m_period-1] (oldest) - // Let's use a consistent diff: m_price[i-j+1] - m_price[i-j] double diff = m_price[i - j + 1] - m_price[i - j]; - - // Hann Windowing Weight, where j corresponds to Ehlers' 'count' - double weight = 1.0 - cos(2 * M_PI * j / (m_period + 1.0)); - + double weight = 1.0 - cos(2 * M_PI * j / (m_period_rsi + 1.0)); if(diff > 0) cu += diff * weight; else cd += -diff * weight; } - if(cu + cd > 0) rsih_buffer[i] = (cu - cd) / (cu + cd); else - rsih_buffer[i] = (i > 0) ? rsih_buffer[i-1] : 0.0; // Fallback to previous or 0 + rsih_buffer[i] = (i > 0) ? rsih_buffer[i-1] : 0.0; + } + +// --- Step 2: Apply Noise Elimination Technology (NET) --- + if(m_period_net > 0) + { + double denominator = 0.5 * m_period_net * (m_period_net - 1); + if(denominator <= 0) + return; + + for(int i = m_period_rsi + m_period_net; i < rates_total; i++) + { + double numerator = 0; + // Double loop for Kendall correlation + for(int j = 1; j < m_period_net; j++) + { + for(int k = 0; k < j; k++) + { + // Ehlers' simplified formula is Num = Num - Sign(X[count] - X[K]) + // This implies adding the sign of (X[fresher] - X[older]) + // In our arrays, i-k is fresher than i-j + double diff = rsih_buffer[i-k] - rsih_buffer[i-j]; + // CORRECTED: Use addition instead of subtraction to match Ehlers' logic + numerator += (diff > 0 ? 1 : (diff < 0 ? -1 : 0)); + } + } + net_buffer[i] = numerator / denominator; + } } }