From cd1cee2bcc262ba3f2822aa71ce69ba49fe940b6 Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Sun, 16 Nov 2025 21:59:35 +0100 Subject: [PATCH] new files added --- .../Stochastic_DoubleSmoothed_Calculator.mqh | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 Include/MyIncludes/Stochastic_DoubleSmoothed_Calculator.mqh diff --git a/Include/MyIncludes/Stochastic_DoubleSmoothed_Calculator.mqh b/Include/MyIncludes/Stochastic_DoubleSmoothed_Calculator.mqh new file mode 100644 index 0000000..06040cb --- /dev/null +++ b/Include/MyIncludes/Stochastic_DoubleSmoothed_Calculator.mqh @@ -0,0 +1,185 @@ +//+------------------------------------------------------------------+ +//| Stochastic_DoubleSmoothed_Calculator.mqh | +//| VERSION 1.10: Corrected EMA calculation chain logic. | +//| Copyright 2025, xxxxxxxx | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, xxxxxxxx" + +#include +#include + +//+==================================================================+ +class CStochasticDoubleSmoothedCalculator + { +protected: + int m_q, m_r, m_s, m_signal_p; + double m_high[], m_low[], m_close[]; + + virtual bool PrepareSourceData(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[]); + //--- UPDATED: Helper now accepts a starting position --- + void CalculateEMA(int rates_total, int period, const double &source[], double &dest[], int start_pos); + +public: + CStochasticDoubleSmoothedCalculator(void) {}; + virtual ~CStochasticDoubleSmoothedCalculator(void) {}; + + bool Init(int q, int r, int s, int signal_p); + void Calculate(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], + double &k_buffer[], double &d_buffer[]); + }; + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +class CStochasticDoubleSmoothedCalculator_HA : public CStochasticDoubleSmoothedCalculator + { +private: + CHeikinAshi_Calculator m_ha_calculator; +protected: + virtual bool PrepareSourceData(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[]) override; + }; + +//+==================================================================+ +//| METHOD IMPLEMENTATIONS | +//+==================================================================+ + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool CStochasticDoubleSmoothedCalculator::Init(int q, int r, int s, int signal_p) + { + m_q = (q < 1) ? 1 : q; + m_r = (r < 1) ? 1 : r; + m_s = (s < 1) ? 1 : s; + m_signal_p = (signal_p < 1) ? 1 : signal_p; + return true; + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void CStochasticDoubleSmoothedCalculator::Calculate(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], + double &k_buffer[], double &d_buffer[]) + { + if(rates_total < m_q + m_r + m_s) + return; + if(!PrepareSourceData(rates_total, open, high, low, close)) + return; + + double num_raw[], den_raw[]; + ArrayResize(num_raw, rates_total); + ArrayResize(den_raw, rates_total); + + for(int i = m_q - 1; i < rates_total; i++) + { + double highest = m_high[i], lowest = m_low[i]; + for(int j = 1; j < m_q; j++) + { + highest = MathMax(highest, m_high[i-j]); + lowest = MathMin(lowest, m_low[i-j]); + } + num_raw[i] = m_close[i] - lowest; + den_raw[i] = highest - lowest; + } + + double num_ema1[], num_ema2[], den_ema1[], den_ema2[]; + ArrayResize(num_ema1, rates_total); + ArrayResize(num_ema2, rates_total); + ArrayResize(den_ema1, rates_total); + ArrayResize(den_ema2, rates_total); + +//--- CORRECTED: Chaining the calculations with proper start positions --- + int start_pos1 = m_q + m_r - 2; + CalculateEMA(rates_total, m_r, num_raw, num_ema1, start_pos1); + CalculateEMA(rates_total, m_r, den_raw, den_ema1, start_pos1); + + int start_pos2 = start_pos1 + m_s - 1; + CalculateEMA(rates_total, m_s, num_ema1, num_ema2, start_pos2); + CalculateEMA(rates_total, m_s, den_ema1, den_ema2, start_pos2); + + for(int i = 0; i < rates_total; i++) + { + if(i < start_pos2) + k_buffer[i] = EMPTY_VALUE; + else + if(den_ema2[i] > 0.000001) + k_buffer[i] = 100.0 * num_ema2[i] / den_ema2[i]; + else + k_buffer[i] = (i > 0) ? k_buffer[i-1] : 50.0; + } + + int start_pos_signal = start_pos2 + m_signal_p - 1; + CalculateEMA(rates_total, m_signal_p, k_buffer, d_buffer, start_pos_signal); + } + +//--- UPDATED: Helper now uses the provided start_pos --- +void CStochasticDoubleSmoothedCalculator::CalculateEMA(int rates_total, int period, const double &source[], double &dest[], int start_pos) + { + if(rates_total <= start_pos) + return; + double pr = 2.0 / (double)(period + 1.0); + + for(int i=0; i 0) + dest[start_pos] = sum / count; + else + dest[start_pos] = EMPTY_VALUE; + + for(int i = start_pos + 1; i < rates_total; i++) + { + if(source[i] != EMPTY_VALUE && dest[i-1] != EMPTY_VALUE) + dest[i] = source[i] * pr + dest[i-1] * (1.0 - pr); + else + if(dest[i-1] != EMPTY_VALUE) + dest[i] = dest[i-1]; + else + dest[i] = EMPTY_VALUE; + } + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool CStochasticDoubleSmoothedCalculator::PrepareSourceData(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[]) + { + ArrayResize(m_high, rates_total); + ArrayResize(m_low, rates_total); + ArrayResize(m_close, rates_total); + ArrayCopy(m_high, high, 0, 0, rates_total); + ArrayCopy(m_low, low, 0, 0, rates_total); + ArrayCopy(m_close, close, 0, 0, rates_total); + return true; + } + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +bool CStochasticDoubleSmoothedCalculator_HA::PrepareSourceData(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[]) + { + double ha_open[], ha_high[], ha_low[], ha_close[]; + ArrayResize(ha_open, rates_total); + ArrayResize(ha_high, rates_total); + ArrayResize(ha_low, rates_total); + ArrayResize(ha_close, rates_total); + m_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close); + + ArrayResize(m_high, rates_total); + ArrayResize(m_low, rates_total); + ArrayResize(m_close, rates_total); + ArrayCopy(m_high, ha_high, 0, 0, rates_total); + ArrayCopy(m_low, ha_low, 0, 0, rates_total); + ArrayCopy(m_close, ha_close, 0, 0, rates_total); + return true; + } +//+------------------------------------------------------------------+ +//+------------------------------------------------------------------+