From 0903f0391b0a3241c3095e2152dff92b723aafa2 Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Wed, 20 Aug 2025 10:54:32 +0200 Subject: [PATCH] refactor: fully manual, self-contained, and accurate --- Indicators/MyIndicators/HMA.mq5 | 123 +++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 42 deletions(-) diff --git a/Indicators/MyIndicators/HMA.mq5 b/Indicators/MyIndicators/HMA.mq5 index fb8866e..570efe6 100644 --- a/Indicators/MyIndicators/HMA.mq5 +++ b/Indicators/MyIndicators/HMA.mq5 @@ -5,11 +5,9 @@ //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" #property link "" -#property version "2.00" // Refactored to use direct calculation, no handles +#property version "3.00" // Fully manual, self-contained, and accurate #property description "Hull Moving Average (HMA)" -#include - //--- Indicator Window and Plot Properties --- #property indicator_chart_window #property indicator_buffers 4 // HMA, and 3 calculation buffers @@ -31,33 +29,32 @@ double BufferHMA[]; double BufferWMA_Half[]; double BufferWMA_Full[]; double BufferRawHMA[]; -double BufferPrice[]; // Buffer for the source price data //--- Global Variables --- -int ExtPeriodHMA; +int g_ExtPeriodHMA; //+------------------------------------------------------------------+ //| Custom indicator initialization function. | //+------------------------------------------------------------------+ -void OnInit() +int OnInit() { - ExtPeriodHMA = (InpPeriodHMA < 1) ? 1 : InpPeriodHMA; + g_ExtPeriodHMA = (InpPeriodHMA < 1) ? 1 : InpPeriodHMA; SetIndexBuffer(0, BufferHMA, INDICATOR_DATA); SetIndexBuffer(1, BufferWMA_Half, INDICATOR_CALCULATIONS); SetIndexBuffer(2, BufferWMA_Full, INDICATOR_CALCULATIONS); SetIndexBuffer(3, BufferRawHMA, INDICATOR_CALCULATIONS); - SetIndexBuffer(4, BufferPrice, INDICATOR_CALCULATIONS); ArraySetAsSeries(BufferHMA, false); ArraySetAsSeries(BufferWMA_Half, false); ArraySetAsSeries(BufferWMA_Full, false); ArraySetAsSeries(BufferRawHMA, false); - ArraySetAsSeries(BufferPrice, false); IndicatorSetInteger(INDICATOR_DIGITS, _Digits); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, ExtPeriodHMA + (int)MathFloor(MathSqrt(ExtPeriodHMA)) - 1); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HMA(%d)", ExtPeriodHMA)); + PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtPeriodHMA + (int)MathFloor(MathSqrt(g_ExtPeriodHMA)) - 2); + IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HMA(%d)", g_ExtPeriodHMA)); + + return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ @@ -74,48 +71,90 @@ int OnCalculate(const int rates_total, const long &volume[], const int &spread[]) { - if(rates_total < ExtPeriodHMA) + int start_pos = g_ExtPeriodHMA + (int)MathFloor(MathSqrt(g_ExtPeriodHMA)) - 2; + if(rates_total <= start_pos) return(0); -//--- STEP 1: Get the source price data --- -// This replaces the iMA handle logic - switch(InpAppliedPrice) +//--- STEP 1: Prepare the source price array + double price_source[]; + ArrayResize(price_source, rates_total); + for(int i=0; i= period_half - 1) - BufferWMA_Half[i] = LinearWeightedMA(i, period_half, BufferPrice); - if(i >= ExtPeriodHMA - 1) - BufferWMA_Full[i] = LinearWeightedMA(i, ExtPeriodHMA, BufferPrice); - } +//--- STEP 2: Calculate all HMA components + int period_half = (int)MathMax(1, MathRound(g_ExtPeriodHMA / 2.0)); + int period_sqrt = (int)MathMax(1, MathRound(MathSqrt(g_ExtPeriodHMA))); -//--- STEP 3: Calculate the raw HMA data - for(int i = ExtPeriodHMA - 1; i < rates_total; i++) +// --- First Pass: Calculate base WMAs and Raw HMA --- + for(int i = g_ExtPeriodHMA - 1; i < rates_total; i++) { + // Manual WMA for half period + double lwma_sum_half = 0; + double weight_sum_half = 0; + for(int j=0; j 0) + BufferWMA_Half[i] = lwma_sum_half / weight_sum_half; + + // Manual WMA for full period + double lwma_sum_full = 0; + double weight_sum_full = 0; + for(int j=0; j 0) + BufferWMA_Full[i] = lwma_sum_full / weight_sum_full; + + // Calculate Raw HMA BufferRawHMA[i] = 2 * BufferWMA_Half[i] - BufferWMA_Full[i]; } -//--- STEP 4: Smooth the raw HMA with the final WMA - int period_sqrt = (int)MathMax(1, MathRound(MathSqrt(ExtPeriodHMA))); - for(int i = ExtPeriodHMA + period_sqrt - 2; i < rates_total; i++) +// --- Second Pass: Calculate final HMA --- + for(int i = start_pos; i < rates_total; i++) { - BufferHMA[i] = LinearWeightedMA(i, period_sqrt, BufferRawHMA); + // Manual WMA for sqrt period on Raw HMA data + double lwma_sum_sqrt = 0; + double weight_sum_sqrt = 0; + for(int j=0; j 0) + BufferHMA[i] = lwma_sum_sqrt / weight_sum_sqrt; } return(rates_total);