From f76d6c4d61c775cf1ad2522e1940a0115ac4581d Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Fri, 22 May 2026 12:48:12 +0200 Subject: [PATCH] refactor: Validated: Pure DMI-based Adaptivity with Kaufman Inversion --- .../Stochastic_Adaptive_on_DMI_Calculator.mqh | 53 +++++++++++-------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/Include/MyIncludes/Stochastic_Adaptive_on_DMI_Calculator.mqh b/Include/MyIncludes/Stochastic_Adaptive_on_DMI_Calculator.mqh index 4d25975..99ee86c 100644 --- a/Include/MyIncludes/Stochastic_Adaptive_on_DMI_Calculator.mqh +++ b/Include/MyIncludes/Stochastic_Adaptive_on_DMI_Calculator.mqh @@ -1,10 +1,11 @@ //+------------------------------------------------------------------+ //| Stochastic_Adaptive_on_DMI_Calculator.mqh | //| Engine: Adaptive Stochastic applied to DMI Oscillator. | -//| VERSION 2.00: ER Calculated on DMI (Pure Logic). | +//| VERSION 2.10: ER Calculated on DMI (Pure Logic). | //| Copyright 2026, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, xxxxxxxx" +#property version "2.10" // Validated: Pure DMI-based Adaptivity with Kaufman Inversion #include #include @@ -19,6 +20,8 @@ enum ENUM_DMI_OSC_TYPE { OSC_PDI_MINUS_NDI, OSC_NDI_MINUS_PDI }; //+==================================================================+ //| CLASS: CStochAdaptiveOnDMICalculator | +//| PURPOSE: Calculates an adaptive stochastic oscillator based on | +//| DMI output, ensuring O(1) incremental performance. | //+==================================================================+ class CStochAdaptiveOnDMICalculator { @@ -30,19 +33,19 @@ protected: int m_min_stoch_p; int m_max_stoch_p; - // Engines + // Mathematical Engines (Stateful for O(1) recursion) CDMIEngine *m_dmi_engine; CMovingAverageCalculator m_slowing_engine; CMovingAverageCalculator m_signal_engine; - // Buffers + // Persistent Buffers for internal states double m_pDI[], m_nDI[]; - double m_dmi_osc[]; // DMI Oscillator + double m_dmi_osc[]; // DMI Oscillator Data double m_er_buffer[]; // Efficiency Ratio of DMI - double m_nsp_buffer[]; // Dynamic Period + double m_nsp_buffer[]; // Dynamic Stochastic Period (Lookback) double m_raw_k[]; // Raw Adaptive %K - // Factory Method + // Factory Method for Engine instantiation virtual void CreateDMIEngine(); public: @@ -51,6 +54,7 @@ public: bool Init(int dmi_p, ENUM_DMI_OSC_TYPE osc_type, int er_p, int min_p, int max_p, int slow_p, ENUM_MA_TYPE slow_ma, int d_p, ENUM_MA_TYPE d_ma); + // CRITICAL: Calculates state incrementally based on prev_calculated void Calculate(int rates_total, int prev_calculated, const double &open[], const double &high[], const double &low[], const double &close[], @@ -58,7 +62,7 @@ public: }; //+------------------------------------------------------------------+ -//| Constructor | +//| Constructor & Destructor | //+------------------------------------------------------------------+ CStochAdaptiveOnDMICalculator::CStochAdaptiveOnDMICalculator() : m_dmi_engine(NULL) {} @@ -80,7 +84,7 @@ void CStochAdaptiveOnDMICalculator::CreateDMIEngine() } //+------------------------------------------------------------------+ -//| Init | +//| Initialization phase | //+------------------------------------------------------------------+ bool CStochAdaptiveOnDMICalculator::Init(int dmi_p, ENUM_DMI_OSC_TYPE osc_type, int er_p, int min_p, int max_p, int slow_p, ENUM_MA_TYPE slow_ma, int d_p, ENUM_MA_TYPE d_ma) { @@ -91,6 +95,7 @@ bool CStochAdaptiveOnDMICalculator::Init(int dmi_p, ENUM_DMI_OSC_TYPE osc_type, m_max_stoch_p = max_p; CreateDMIEngine(); + if(!m_dmi_engine.Init(m_dmi_p)) return false; if(!m_slowing_engine.Init(slow_p, slow_ma)) @@ -102,7 +107,7 @@ bool CStochAdaptiveOnDMICalculator::Init(int dmi_p, ENUM_DMI_OSC_TYPE osc_type, } //+------------------------------------------------------------------+ -//| Main Calculation | +//| Main Calculation (O(1) Engine) | //+------------------------------------------------------------------+ void CStochAdaptiveOnDMICalculator::Calculate(int rates_total, int prev_calculated, const double &open[], const double &high[], @@ -112,9 +117,10 @@ void CStochAdaptiveOnDMICalculator::Calculate(int rates_total, int prev_calculat if(rates_total < m_dmi_p + m_er_p + m_max_stoch_p) return; +// O(1) Pointer int start_index = (prev_calculated > 0) ? prev_calculated - 1 : 0; -// 1. Resize Buffers +// 1. Dynamic Buffer Resizing if(ArraySize(m_pDI) != rates_total) { ArrayResize(m_pDI, rates_total); @@ -125,10 +131,10 @@ void CStochAdaptiveOnDMICalculator::Calculate(int rates_total, int prev_calculat ArrayResize(m_raw_k, rates_total); } -// 2. Calculate Base DMI +// 2. Base DMI Calculation via encapsulated Engine m_dmi_engine.Calculate(rates_total, prev_calculated, open, high, low, close, m_pDI, m_nDI); -// 3. Calculate DMI Oscillator +// 3. DMI Oscillator Line int loop_start_dmi = MathMax(m_dmi_p, start_index); for(int i = loop_start_dmi; i < rates_total; i++) { @@ -138,9 +144,8 @@ void CStochAdaptiveOnDMICalculator::Calculate(int rates_total, int prev_calculat m_dmi_osc[i] = m_nDI[i] - m_pDI[i]; } -// 4. Calculate Efficiency Ratio (ER) on DMI OSCILLATOR (Pure Logic) +// 4. Efficiency Ratio (ER) based strictly on DMI volatility int loop_start_er = MathMax(m_dmi_p + m_er_p, start_index); - for(int i = loop_start_er; i < rates_total; i++) { double direction = MathAbs(m_dmi_osc[i] - m_dmi_osc[i - m_er_p]); @@ -151,15 +156,19 @@ void CStochAdaptiveOnDMICalculator::Calculate(int rates_total, int prev_calculat m_er_buffer[i] = (volatility > 1.0e-9) ? direction / volatility : 0.0; } -// 5. Calculate Adaptive Period (NSP) +// 5. Adaptive Period (NSP) Calculation (THE WINNING LOGIC) +// Inverse logic: High ER (Trend) = Short Period; Low ER (Chop) = Long Period for(int i = loop_start_er; i < rates_total; i++) { - m_nsp_buffer[i] = (int)MathRound(m_min_stoch_p + (1.0 - m_er_buffer[i]) * (m_max_stoch_p - m_min_stoch_p)); + // Using MathRound for accuracy instead of rough casting + m_nsp_buffer[i] = MathRound(m_min_stoch_p + (1.0 - m_er_buffer[i]) * (m_max_stoch_p - m_min_stoch_p)); + + // Safety Limit: Stochastic mathematically breaks if period < 2 (Div by Zero) if(m_nsp_buffer[i] < 2) m_nsp_buffer[i] = 2; } -// 6. Calculate Raw %K on DMI Oscillator +// 6. Raw %K on DMI Oscillator using dynamic lookback (NSP) int stoch_start = m_dmi_p + m_er_p + m_max_stoch_p - 1; int loop_start_k = MathMax(stoch_start, start_index); @@ -172,7 +181,7 @@ void CStochAdaptiveOnDMICalculator::Calculate(int rates_total, int prev_calculat for(int k = 1; k < current_nsp; k++) { if(i-k < 0) - break; + break; // Safety if(m_dmi_osc[i-k] > highest) highest = m_dmi_osc[i-k]; if(m_dmi_osc[i-k] < lowest) @@ -183,10 +192,10 @@ void CStochAdaptiveOnDMICalculator::Calculate(int rates_total, int prev_calculat if(range > 1.0e-9) m_raw_k[i] = 100.0 * (m_dmi_osc[i] - lowest) / range; else - m_raw_k[i] = (i > 0) ? m_raw_k[i-1] : 50.0; + m_raw_k[i] = (i > 0) ? m_raw_k[i-1] : 50.0; // Flatline prevention fallback } -// 7. Smoothing +// 7. Final Smoothing (Engine handles O(1) internally) m_slowing_engine.CalculateOnArray(rates_total, prev_calculated, m_raw_k, out_k, stoch_start); int d_offset = stoch_start + m_slowing_engine.GetPeriod() - 1; @@ -194,15 +203,15 @@ void CStochAdaptiveOnDMICalculator::Calculate(int rates_total, int prev_calculat } //+==================================================================+ -//| CLASS: CStochAdaptiveOnDMICalculator_HA (Heikin Ashi) | +//| CLASS: CStochAdaptiveOnDMICalculator_HA (Heikin Ashi Support) | //+==================================================================+ class CStochAdaptiveOnDMICalculator_HA : public CStochAdaptiveOnDMICalculator { protected: virtual void CreateDMIEngine() override { + // Injects the HA version of the DMI engine (Polymorphism) m_dmi_engine = new CDMIEngine_HA(); } }; //+------------------------------------------------------------------+ -//+------------------------------------------------------------------+