HMA_Color_v02b
Download scriptThis script implements the Hull Moving Average (HMA), a sophisticated technical analysis tool designed to track market trends with high responsiveness. Unlike standard moving averages, which often suffer from significant "lag" (the delay between a price change and the indicator's reaction), the HMA uses a unique mathematical approach to smooth out price data while keeping the line closely aligned with current market movements.
How the Logic Works
The script processes market data through a multi-layered calculation to achieve its results:
- Weighted Smoothing: The logic first calculates two separate weighted averages based on the user-defined period—one representing the full period and one representing half of that period.
- Difference Calculation: By subtracting the full average from twice the half-average, the script captures the "momentum" or the immediate velocity of the price. This step is what allows the indicator to react much faster than a traditional moving average.
- Final Smoothing: To ensure the resulting line isn't too erratic or "noisy," the script applies a final smoothing pass based on the square root of the period. This creates a balance between speed and stability, providing a clean visual trend.
Visual Representation
The script is designed to provide clear, actionable visual cues on your trading chart:
- Trend Tracking: The primary output is a smooth line that follows price action. It helps traders identify the prevailing direction of the market (upward or downward).
- Directional Color Changes: To make the indicator even more intuitive, the script includes logic to detect changes in direction. When the trend shifts, the colors change dynamically:
- Lime Green: Generally signifies an upward bullish trend.
- Red: Generally signifies a downward bearish trend.
- Yellow/Neutral Transitions: Helps highlight moments where the trend is shifting or consolidating.
Summary for the User
In simple terms, this tool acts as a "fast-acting" trend guide. It takes the raw price data and filters out minor market noise to show you the core direction of the move. Because it uses weighted calculations, it tries to stay as close to the current price as possible, helping you identify trend reversals more quickly than standard moving averages would allow.
//+----------------+
//| HMA.mq4 by Ron|
//+----------------+
/*
MetaStock Formula
period:=Input("Period",1,200,20) ;
sqrtperiod:=Input("Square Root of Period",1,20,4);
Mov(2*(Mov(C,period/2,W))-Mov(C,period,W),sqrtperiod,W);
SuperCharts Formula
Input: period (Default value 20)
waverage(2*waverage(close,period/2)-waverage(close,period), SquareRoot(Period))
Added color on direction change
*/
#property copyright "Ron Thompson"
#property link "http://www.metaquotes.net/"
//---- indicator settings
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 LimeGreen
#property indicator_color2 Yellow
#property indicator_color3 Red
//User input
extern int HMA_Period=14;
//---- indicator buffers
double ind_buffer0[];
double ind_buffer1[];
double ind_buffer2[];
double buffer[];
int draw_begin0;
//Custom init
int init()
{
//---- indicator buffers mapping
IndicatorBuffers(4);
if( !SetIndexBuffer(0,ind_buffer0)
&& !SetIndexBuffer(1,ind_buffer1)
&& !SetIndexBuffer(2,ind_buffer2)
&& !SetIndexBuffer(3, buffer))
Print("cannot set indicator buffers!");
// ArraySetAsSeries(ind_buffer1,true);
//---- drawing settings
SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,2);
SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,2);
SetIndexStyle(2,DRAW_LINE,STYLE_SOLID,2);
draw_begin0=HMA_Period+MathFloor(MathSqrt(HMA_Period));
SetIndexDrawBegin(0,draw_begin0);
SetIndexDrawBegin(1,draw_begin0);
SetIndexDrawBegin(2,draw_begin0);
IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS)+1);
//---- name for DataWindow and indicator subwindow label
IndicatorShortName("HMA("+HMA_Period+")");
SetIndexLabel(0,"Hull Moving Average");
}
// Main Program loop
int start()
{
int limit,i;
int counted_bars=IndicatorCounted();
double tmp, tmpPrevious;
double fullMA;
double halfMA;
int fullPeriod = HMA_Period;
int halfPeriod = HMA_Period/2;
int sqrtPeriod = MathFloor(MathSqrt(HMA_Period*1.00));
//---- check for possible errors
if(counted_bars<1)
{
for(i=1;i<=draw_begin0;i++)
{
buffer[Bars-i]=0;
}
for(i=1;i<=fullPeriod;i++)
{
ind_buffer0[Bars-i]=0;
ind_buffer1[Bars-i]=0;
ind_buffer2[Bars-i]=0;
}
}// if counted
//---- last counted bar will be recounted
if(counted_bars>0)
{
counted_bars--;
}
limit=Bars-counted_bars;
//---- MA difference counted in the 1-st buffer
for(i=0; i<limit; i++)
{
halfMA=iMA(NULL,0,halfPeriod,0,MODE_LWMA,PRICE_OPEN,i)*2;
fullMA=iMA(NULL,0,fullPeriod,0,MODE_LWMA,PRICE_OPEN,i);
buffer[i]=halfMA-fullMA;
}
//---- HMA counted in the 0-th buffer
tmp=iMAOnArray(buffer,0,MathFloor(MathSqrt(HMA_Period)),0,MODE_LWMA,0);
for(i=1; i<limit; i++)
{
tmpPrevious=iMAOnArray(buffer,0,MathFloor(MathSqrt(HMA_Period)),0,MODE_LWMA,i);
if (tmpPrevious > tmp)
{
ind_buffer0[i] = EMPTY_VALUE;
ind_buffer1[i] = EMPTY_VALUE;
ind_buffer2[i] = tmpPrevious;
ind_buffer2[i-1] = tmp; // !
}
else if (tmpPrevious < tmp)
{
ind_buffer0[i] = tmpPrevious;
ind_buffer0[i-1] = tmp; // !
ind_buffer1[i] = EMPTY_VALUE;
ind_buffer2[i] = EMPTY_VALUE;
}
else
{
ind_buffer0[i] = CLR_NONE;
ind_buffer1[i] = tmpPrevious;
ind_buffer2[i-1] = tmp; // !
ind_buffer2[i] = CLR_NONE;
}
tmp = tmpPrevious;
}//for
}
Comments