Advertisement IC Markets

Demystifying the Hull Moving Average (HMA) – A Beginner's Guide + Free MT4 Code!

Discuss 1-minute to 15-minute price action setups, fading intraday momentum, key support/resistance zones, and proven short-term trading methodologies.
Post Reply
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Demystifying the Hull Moving Average (HMA) – A Beginner's Guide + Free MT4 Code!

Post by PTScalper »

Hi Scalpers,

i hope everybody is fine and enjoy summer with at least some good profitable trades :-)

If you are new to trading, you have probably already experimented with Simple Moving Averages (SMA) or Exponential Moving Averages (EMA). They are great for identifying trends, but they all share one frustrating problem: lag.

By the time a traditional moving average crosses or changes direction, the price has often already made its big move.

Enter the Hull Moving Average (HMA).

What is the Hull Moving Average?
Its created by Australian trader Alan Hull in 2005, the HMA was designed to solve the age-old dilemma of moving averages: How do you make a line that reacts quickly to current price changes, but remains smooth enough to filter out market noise?

Alan Hull cracked the code by using a clever mathematical formula involving Weighted Moving Averages (WMA) and square roots. You don't need to be a math genius to use it, but the result is a moving average that practically hugs the price action and drastically reduces lag.

Why Newbies Love the HMA
Speed: It reacts to price reversals much faster than an SMA or EMA.

Smoothness: Despite its speed, it doesn't get "choppy" or give as many false signals during small price spikes.

Simplicity: It is incredibly easy to read. You trade based on the slope of the line.

How to Trade with the HMA
As a beginner, keep it simple. The most common way to use the HMA is as a directional filter:

Uptrend: When the HMA turns upwards, the trend is generally bullish (look for buy setups).
Downtrend: When the HMA turns downwards, the trend is generally bearish (look for sell setups).
Exit/Caution: When the HMA flattens out or flips direction, it’s a strong early warning that the current trend is losing momentum.
Important Note: No indicator is a crystal ball! Never trade solely on an HMA changing direction. Combine it with price action, support/resistance, or another indicator (like RSI or MACD) to confirm your entries.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Recommended broker for automated trading & scalping IC Markets
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Demystifying the Hull Moving Average (HMA) – A Beginner's Guide + Free MT4 Code!

Post by PTScalper »

Your Free MT4 (MQL4) Code

MT4 doesn't come with the HMA built-in by default, so I’ve written a clean, lightweight custom indicator for you.

How to install it:

1.) Open MT4 and press F4 to open the MetaEditor.

2.) Click New -> Custom Indicator -> click Next until you finish (don't worry about the inputs, we will overwrite them).

3.) Delete all the default code that appears.

4.) Copy and paste the code below into the blank editor.

5.) Click Compile (or press F7).

6.) Restart MT4 or refresh your Navigator panel, and drag the "Hull Moving Average" onto your chart!

Code: Select all

//+------------------------------------------------------------------+
//|                                           HullMovingAverage.mq4  |
//|                                    Beginner Friendly HMA Script  |
//+------------------------------------------------------------------+
#property copyright "Forum Community"
#property link      ""
#property version   "1.00"
#property strict

// Let MT4 know this indicator goes on the main chart
#property indicator_chart_window 

// We need 2 buffers (one for the final line, one for background math)
#property indicator_buffers 2 

// Customize the visual look of the HMA line
#property indicator_color1 clrDodgerBlue
#property indicator_width1 2
#property indicator_style1 STYLE_SOLID

//--- User Inputs (You can change these in MT4 settings)
input int HMAPeriod = 14;                                // HMA Period
input ENUM_APPLIED_PRICE PriceType = PRICE_CLOSE;        // Applied Price

//--- Indicator Buffers
double HMABuffer[];    // The line you see on the chart
double DiffBuffer[];   // Hidden buffer for math calculations

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Setup the visible HMA line
   SetIndexBuffer(0, HMABuffer);
   SetIndexStyle(0, DRAW_LINE);
   SetIndexLabel(0, "HMA(" + IntegerToString(HMAPeriod) + ")");
   
   // Setup the hidden math buffer
   SetIndexBuffer(1, DiffBuffer);
   SetIndexStyle(1, DRAW_NONE); // Keeps it invisible

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   // Math setup for HMA formula
   int halfPeriod = (int)MathFloor(HMAPeriod / 2.0);
   int sqrtPeriod = (int)MathFloor(MathSqrt(HMAPeriod));

   // Calculate how many bars we need to update
   int limit = rates_total - prev_calculated;
   
   // If it's the very first time loading, calculate everything (minus the periods we need for math)
   if(prev_calculated == 0) limit = rates_total - HMAPeriod - sqrtPeriod - 1;
   if(limit < 0) return 0;
   
   // If we are just updating live ticks, only recalculate the current bar and previous bar
   if(prev_calculated > 0) limit++; 

   // STEP 1: Calculate the difference between the Half WMA and Full WMA
   for(int i = limit; i >= 0; i--)
     {
      double wmaHalf = iMA(NULL, 0, halfPeriod, 0, MODE_LWMA, PriceType, i);
      double wmaFull = iMA(NULL, 0, HMAPeriod, 0, MODE_LWMA, PriceType, i);
      
      // HMA Formula part 1: (2 * WMA(n/2)) - WMA(n)
      DiffBuffer[i] = (2.0 * wmaHalf) - wmaFull;
     }

   // STEP 2: Calculate the WMA of the difference using the Square Root of the period
   for(int i = limit; i >= 0; i--)
     {
      double sum = 0.0;
      double weightSum = 0.0;
      
      // Manual WMA calculation on our DiffBuffer
      for(int j = 0; j < sqrtPeriod; j++)
        {
         int weight = sqrtPeriod - j;
         if((i + j) < rates_total) // Prevent out-of-bounds errors
           {
            sum += DiffBuffer[i + j] * weight;
            weightSum += weight;
           }
        }
        
      // HMA Formula part 2: The final smoothed result!
      if(weightSum > 0) HMABuffer[i] = sum / weightSum;
     }

   return(rates_total);
  }
//+------------------------------------------------------------------+
I hope this helps some of you clear up the lag on your charts! Feel free to ask if you have any questions about how to read it or how to install the code.
What currency pairs or timeframes are you planning to test the HMA out on first?
Take a care.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
LondonScalper
Posts: 770
Joined: Sat Sep 05, 2026 7:54 am

Re: Demystifying the Hull Moving Average (HMA) – A Beginner's Guide + Free MT4 Code!

Post by LondonScalper »

PTScalper wrote:By the time a traditional moving average crosses or changes direction, the price has often already made its big move. Enter the Hull Moving Average (HMA).
HMA’s pitch is familiar: less lag, still smooth. Sometimes that’s true enough to be useful; sometimes it’s just a faster way to whip you in chop.

On M1 scalping I treat any MA — Hull included — as a visual bias, not a cross-triggered ATM. Faster response helps in clean trends and hurts when gold or a major is mean-reverting every twenty seconds. Lag isn’t only a bug; it’s also a filter.

Practical stance:
  • Use HMA slope/location for context, not every colour flip as an order
  • Compare against a dumb EMA on the same cost-adjusted forward window before declaring victory
  • Beware stacking HMA + three other “low lag” tools — correlated noise
Alan Hull’s idea earned its popularity. Just don’t confuse a prettier line with a complete method.

Do you mainly trade HMA crosses, or price reacting at a Hull dynamic level?
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Demystifying the Hull Moving Average (HMA) – A Beginner's Guide + Free MT4 Code!

Post by PTScalper »

LondonScalper wrote: Fri Sep 11, 2026 9:08 pm
PTScalper wrote:By the time a traditional moving average crosses or changes direction, the price has often already made its big move. Enter the Hull Moving Average (HMA).
HMA’s pitch is familiar: less lag, still smooth. Sometimes that’s true enough to be useful; sometimes it’s just a faster way to whip you in chop.

On M1 scalping I treat any MA — Hull included — as a visual bias, not a cross-triggered ATM. Faster response helps in clean trends and hurts when gold or a major is mean-reverting every twenty seconds. Lag isn’t only a bug; it’s also a filter.

Practical stance:
  • Use HMA slope/location for context, not every colour flip as an order
  • Compare against a dumb EMA on the same cost-adjusted forward window before declaring victory
  • Beware stacking HMA + three other “low lag” tools — correlated noise
Alan Hull’s idea earned its popularity. Just don’t confuse a prettier line with a complete method.

Do you mainly trade HMA crosses, or price reacting at a Hull dynamic level?
Hi LondonScalper,

You hit the nail perfectly on the head: lag is a structural filter against the noise. The moment you strip away too much lag, you stop tracking the trend and start tracking the chop.

To answer your question directly: I strictly trade price reacting at a Hull dynamic level, never the crosses.

Trading an M1 HMA color flip or a fast/slow HMA cross is a guaranteed way to suffer death by a thousand cuts during lunchtime lulls or Asian session consolidation. The Hull is too responsive; it will excitedly tell you the trend has shifted when all that happened was a three-pip mean-reversion blip.

Instead, the HMA excels as a dynamic, flowing support/resistance level when paired with a slower, dumber baseline. You let a high-period EMA dictate the macro bias, and you use the HMA as the "rubber band." You wait for price to pull back to the HMA, test it, and reject it in the direction of the overarching trend.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Demystifying the Hull Moving Average (HMA) – A Beginner's Guide + Free MT4 Code!

Post by PTScalper »

Here is a Pine Script (v5) built exactly on the practical stance you outlined. It plots an HMA for slope/context, compares it against a "dumb EMA" for the baseline, and flags setups where price physically reacts to the HMA as a dynamic boundary rather than plotting naive crosses.

Code: Select all

//@version=5
indicator("HMA Context & Dynamic Reaction [Scalp]", overlay=true)

// =========================================================================
// INPUTS
// =========================================================================
hmaLength = input.int(55, title="Hull MA Length (Dynamic Level)", group="Settings")
emaLength = input.int(200, title="Dumb EMA Length (Macro Filter)", group="Settings")

// =========================================================================
// CALCULATIONS
// =========================================================================
hma = ta.hma(close, hmaLength)
ema = ta.ema(close, emaLength)

// Determine HMA slope for visual context
hmaSlopeUp = hma > hma[1]
hmaColor   = hmaSlopeUp ? color.new(color.teal, 0) : color.new(color.maroon, 0)

// =========================================================================
// PLOTTING
// =========================================================================
// Plot the slow, dumb EMA as the anchor
plot(ema, title="Baseline EMA", color=color.new(color.gray, 50), linewidth=2)

// Plot the HMA as the dynamic action zone
plot(hma, title="HMA", color=hmaColor, linewidth=2)

// =========================================================================
// REACTION LOGIC (Not Crosses)
// =========================================================================
// Bullish Setup: 
// 1. Macro trend is up (Close > EMA)
// 2. HMA is sloping up (Context)
// 3. Price pulled back to touch/pierce the HMA (Low <= HMA)
// 4. Price rejected the HMA and closed back above it (Close > HMA)
bullishReaction = (close > ema) and hmaSlopeUp and (low <= hma) and (close > hma)

// Bearish Setup:
// 1. Macro trend is down (Close < EMA)
// 2. HMA is sloping down (Context)
// 3. Price rallied to touch/pierce the HMA (High >= HMA)
// 4. Price rejected the HMA and closed back below it (Close < HMA)
bearishReaction = (close < ema) and not hmaSlopeUp and (high >= hma) and (close < hma)

// =========================================================================
// SIGNALS
// =========================================================================
plotshape(bullishReaction, title="Bullish Rejection", style=shape.triangleup, location=location.belowbar, color=color.teal, size=size.small)
plotshape(bearishReaction, title="Bearish Rejection", style=shape.triangledown, location=location.abovebar, color=color.maroon, size=size.small)
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Demystifying the Hull Moving Average (HMA) – A Beginner's Guide + Free MT4 Code!

Post by PTScalper »

How this script applies your philosophy:

Ignores the chop: It won't print signals just because the HMA changes color.

Respects the baseline: The "dumb EMA" (default 200) acts as your anchor. If price is above the EMA, it will only look for long bounces off the Hull.

Trades the reaction: The logic requires a physical touch of the HMA (low <= hma or high >= hma) followed by a close that rejects the level. You are trading the failure to break the dynamic level, entering right as momentum aligns back with the macro trend.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Demystifying the Hull Moving Average (HMA) – A Beginner's Guide + Free MT4 Code!

Post by PTScalper »

To upgrade this from a solid retail concept to a professional-grade algorithmic tool, we need to address three harsh realities of live markets:

Single MAs are a retail trap: Markets don't react to exact lines to the decimal; they react to liquidity zones. A pro script wraps the HMA in a volatility-adjusted (ATR) band to create a "Value Area."

Touches aren't triggers: Just touching a line means nothing if momentum carries right through it. We need price action confirmation (a sweep into the zone followed by a structural rejection).

No signal is complete without risk parameters: A professional indicator provides an objective, mathematically sound invalidation point (Stop Loss) the moment a setup fires.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Demystifying the Hull Moving Average (HMA) – A Beginner's Guide + Free MT4 Code!

Post by PTScalper »

Here is the "Pro" version. It upgrades the HMA into a Dynamic Volatility Zone, requires price-action confluence, draws precise stop-loss levels, and includes JSON-formatted alerts for automated execution routing.

Code: Select all

//@version=5
indicator("HMA Volatility Zone & Institutional Sweeps", overlay=true, max_lines_count=100)

// =========================================================================
// 1. INPUTS & PARAMETERS
// =========================================================================
// Trend Regime
grp_trend = "Macro Regime Filter"
emaLength = input.int(200, "Baseline EMA", group=grp_trend, tooltip="Defines the overarching market regime.")

// Dynamic Value Area
grp_hma = "HMA Volatility Zone"
hmaLength = input.int(55, "HMA Period", group=grp_hma)
atrLength = input.int(14, "ATR Period (Volatility)", group=grp_hma)
atrMult   = input.float(0.75, "ATR Band Multiplier", step=0.25, group=grp_hma, tooltip="Width of the HMA support/resistance zone.")

// Risk Management
grp_risk = "Risk Management"
slAtrMult = input.float(1.5, "Stop Loss ATR Multiplier", step=0.1, group=grp_risk, tooltip="Buffer for stop loss placement below/above the sweep candle.")

// =========================================================================
// 2. CORE CALCULATIONS
// =========================================================================
// Regime
baselineEma = ta.ema(close, emaLength)

// Value Area (HMA + Volatility Bands)
hmaCore = ta.hma(close, hmaLength)
atr     = ta.atr(atrLength)

hmaUpper = hmaCore + (atr * atrMult)
hmaLower = hmaCore - (atr * atrMult)

// Market State
bullRegime = close > baselineEma and hmaCore > baselineEma
bearRegime = close < baselineEma and hmaCore < baselineEma

// =========================================================================
// 3. PRICE ACTION LOGIC (THE "SWEEP")
// =========================================================================
// A valid setup requires price to sweep into the volatility band, grab liquidity, 
// and then close strongly back over the core HMA, proving institutional defense.

bullishSweep = bullRegime and (low <= hmaLower) and (close > hmaCore) and (close > open)
bearishSweep = bearRegime and (high >= hmaUpper) and (close < hmaCore) and (close < open)

// =========================================================================
// 4. VISUALS & UI
// =========================================================================
// Plot Macro Baseline
plot(baselineEma, "Macro Baseline", color=color.new(color.white, 50), linewidth=2)

// Plot HMA Volatility Zone (The "River")
pHmaU = plot(hmaUpper, "HMA Upper Band", color=color.new(color.gray, 80))
pHmaL = plot(hmaLower, "HMA Lower Band", color=color.new(color.gray, 80))
fill(pHmaU, pHmaL, color=bullRegime ? color.new(color.teal, 85) : bearRegime ? color.new(color.maroon, 85) : color.new(color.gray, 85), title="HMA Zone")

// Plot Core HMA
plot(hmaCore, "HMA Core", color=bullRegime ? color.teal : bearRegime ? color.maroon : color.gray, linewidth=2)

// Setup Highlights
plotshape(bullishSweep, "Long Trigger", style=shape.triangleup, location=location.belowbar, color=color.teal, size=size.small)
plotshape(bearishSweep, "Short Trigger", style=shape.triangledown, location=location.abovebar, color=color.maroon, size=size.small)

// Bar Colors to highlight setups
barcolor(bullishSweep ? color.aqua : bearishSweep ? color.fuchsia : na)

// =========================================================================
// 5. RISK MANAGEMENT (STOP LOSS GENERATION)
// =========================================================================
// Draw a strict invalidation line based on volatility when a signal fires
if bullishSweep
    slLevel = low - (atr * slAtrMult)
    line.new(bar_index, slLevel, bar_index + 5, slLevel, color=color.red, width=2, style=line.style_solid)
    label.new(bar_index + 5, slLevel, "SL", color=color.new(color.red, 80), style=label.style_label_left, textcolor=color.white, size=size.tiny)

if bearishSweep
    slLevel = high + (atr * slAtrMult)
    line.new(bar_index, slLevel, bar_index + 5, slLevel, color=color.red, width=2, style=line.style_solid)
    label.new(bar_index + 5, slLevel, "SL", color=color.new(color.red, 80), style=label.style_label_left, textcolor=color.white, size=size.tiny)

// =========================================================================
// 6. ALERTS (JSON PAYLOADS FOR AUTOMATION)
// =========================================================================
if bullishSweep
    alert('{"action": "long", "symbol": "' + syminfo.ticker + '", "price": ' + str.tostring(close) + ', "sl": ' + str.tostring(low - (atr * slAtrMult)) + '}', alert.freq_once_per_bar_close)

if bearishSweep
    alert('{"action": "short", "symbol": "' + syminfo.ticker + '", "price": ' + str.tostring(close) + ', "sl": ' + str.tostring(high + (atr * slAtrMult)) + '}', alert.freq_once_per_bar_close)
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Demystifying the Hull Moving Average (HMA) – A Beginner's Guide + Free MT4 Code!

Post by PTScalper »

The "Pro" Upgrades Explained:

The Volatility Zone (The River): Instead of a single HMA line, the script calculates a dynamic upper and lower band based on current ATR. Markets are messy; support is an area, not a pixel.

The Liquidity Sweep Trigger: The logic (low <= hmaLower and close > hmaCore) guarantees you are only entering when price has "swept" the extremes of the value zone but failed to hold there, forcing a close back into the safety of the trend. This filters out weak, choppy consolidation touches.

Dynamic Trade Management: When a signal fires, the script instantly calculates a volatility-adjusted Stop Loss (Signal Candle Low/High ± 1.5 ATR) and prints a short horizontal red line on your chart. You know exactly where your trade is invalidated the millisecond you enter.

Institutional JSON Alerts: Standard alertcondition() is for manual traders. The alert() function here pushes a JSON string containing the action, ticker, entry price, and exact stop-loss price. This can be directly ingested by tools like 3Commas, PineConnector, or custom Python webhooks.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
LondonScalper
Posts: 770
Joined: Sat Sep 05, 2026 7:54 am

Re: Demystifying the Hull Moving Average (HMA) – A Beginner's Guide + Free MT4 Code!

Post by LondonScalper »

Reaction at the line with a slow baseline behind it is the version of Hull I'd actually use, so no disagreement on the approach.

Two notes on the scripts. The first version flags a setup on any bar where the low touches the HMA and the close finishes back above it. On M1 in a trend that condition is met constantly, so it will paint far more signals than anyone should take. I'd require the previous two or three bars to have closed clear of the line first, so it's a genuine pullback into it rather than price riding along it.

The ATR band in the pro version helps, but the multiplier matters more than it looks. Too wide and every candle sweeps the lower band; too narrow and you're back to a single line. I'd run it over a few London sessions and count signals per morning before believing any win rate. If it produces more than three or four a session on one pair, the filter is too loose for scalping.
Post Reply