diff --git a/Indicators/MyIndicators/Holt_MA.mq5 b/Indicators/MyIndicators/Holt_MA.mq5 new file mode 100644 index 0000000..43d49d4 --- /dev/null +++ b/Indicators/MyIndicators/Holt_MA.mq5 @@ -0,0 +1,208 @@ +//+------------------------------------------------------------------+ +//| Holt_MA.mq5 | +//| Copyright 2025, xxxxxxxx| +//| | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, xxxxxxxx" +#property version "1.00" +#property description "Holt's Linear Trend Method (Double Exponential Smoothing)." +#property description "Provides a smoothed line with a 1-bar forecast." + +#property indicator_chart_window +#property indicator_buffers 1 +#property indicator_plots 1 + +//--- Plot 1: Holt MA Forecast Line +#property indicator_label1 "Holt MA" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrMediumSeaGreen +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +//--- Input Parameters --- +input int InpPeriod = 20; // Period for initialization +input double InpAlpha = 0.1; // Alpha (Level smoothing factor, 0 < a < 1) +input double InpBeta = 0.05; // Beta (Trend smoothing factor, 0 < b < 1) +input ENUM_APPLIED_PRICE InpSourcePrice = PRICE_CLOSE; // Source Price + +//--- Indicator Buffers --- +double BufferHoltMA[]; + +//+------------------------------------------------------------------+ +//| CLASS: CHoltMACalculator | +//| Encapsulates the Double Exponential Smoothing logic. | +//+------------------------------------------------------------------+ +class CHoltMACalculator + { +private: + //--- Parameters + int m_period; + double m_alpha; + double m_beta; + + //--- Internal calculation buffers + double m_price[]; + double m_level[]; + double m_trend[]; + double m_forecast[]; + +public: + CHoltMACalculator(void); + ~CHoltMACalculator(void) {}; + + bool Init(int period, double alpha, double beta); + void Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], + double &holt_ma_out[]); + }; + +//+------------------------------------------------------------------+ +//| CHoltMACalculator: Constructor | +//+------------------------------------------------------------------+ +CHoltMACalculator::CHoltMACalculator(void) : m_period(0), m_alpha(0.1), m_beta(0.05) + { + } + +//+------------------------------------------------------------------+ +//| CHoltMACalculator: Initialization | +//+------------------------------------------------------------------+ +bool CHoltMACalculator::Init(int period, double alpha, double beta) + { + m_period = (period < 2) ? 2 : period; + +//--- Constrain alpha and beta to be between 0 and 1 + m_alpha = (alpha <= 0) ? 0.0001 : (alpha >= 1) ? 0.9999 : alpha; + m_beta = (beta <= 0) ? 0.0001 : (beta >= 1) ? 0.9999 : beta; + + return true; + } + +//+------------------------------------------------------------------+ +//| CHoltMACalculator: Main Calculation Method | +//+------------------------------------------------------------------+ +void CHoltMACalculator::Calculate(int rates_total, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], + double &holt_ma_out[]) + { + if(rates_total < m_period) + return; + +//--- Resize internal buffers + ArrayResize(m_price, rates_total); + ArrayResize(m_level, rates_total); + ArrayResize(m_trend, rates_total); + ArrayResize(m_forecast, rates_total); + +//--- Step 1: Prepare the source price series + PriceSeries(price_type, rates_total, open, high, low, close, m_price); + +//--- Step 2: Robust Initialization of the first Level and Trend + m_level[0] = m_price[0]; + m_trend[0] = m_price[1] - m_price[0]; // Initial trend estimate + m_forecast[0] = m_level[0] + m_trend[0]; + m_forecast[1] = m_forecast[0]; // To avoid zero value at the start + +//--- Step 3: Recursive calculation for the rest of the series + for(int i = 2; i < rates_total; i++) + { + //--- Calculate Level + m_level[i] = m_alpha * m_price[i] + (1 - m_alpha) * (m_level[i-1] + m_trend[i-1]); + + //--- Calculate Trend + m_trend[i] = m_beta * (m_level[i] - m_level[i-1]) + (1 - m_beta) * m_trend[i-1]; + + //--- Calculate 1-bar ahead Forecast (this is the plotted line) + m_forecast[i] = m_level[i] + m_trend[i]; + } + +//--- Copy final results to the output buffer + ArrayCopy(holt_ma_out, m_forecast, 0, 0, rates_total); + } + +//+------------------------------------------------------------------+ +//| Helper function to get the selected price series. | +//+------------------------------------------------------------------+ +void PriceSeries(ENUM_APPLIED_PRICE type, int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], double &dest_buffer[]) + { + switch(type) + { + case PRICE_CLOSE: + ArrayCopy(dest_buffer, close, 0, 0, rates_total); + break; + case PRICE_OPEN: + ArrayCopy(dest_buffer, open, 0, 0, rates_total); + break; + case PRICE_HIGH: + ArrayCopy(dest_buffer, high, 0, 0, rates_total); + break; + case PRICE_LOW: + ArrayCopy(dest_buffer, low, 0, 0, rates_total); + break; + case PRICE_MEDIAN: + for(int i=0; i