This script is a specialized technical indicator designed to help traders identify the strength and direction of market trends. It builds upon the standard Average Directional Index (ADX) but introduces specific mathematical refinements to smooth out the data, making it easier to read on a price chart.
Core Functionality
The logic operates by analyzing price movements over a specific timeframe (determined by the user's period setting) and breaking those movements down into three distinct components:
1. Movement Tracking (+DI and -DI) The script first looks at the high and low prices of each candle compared to the previous ones. It calculates two primary metrics:
- Positive Movement: Measures how much the price is pushing upward.
- Negative Movement: Measures how much the price is pushing downward. By comparing these movements against the total range of the candle (the "True Range"), the script creates two separate values (+DI and -DI). These represent the relative strength of buyers versus sellers at any given moment.
2. Trend Magnitude (DX Calculation) Once the script has determined the relative strength of the upward and downward moves, it calculates a "Directional Index" (DX). This value represents the difference between the positive and negative forces. If one force is significantly stronger than the other, the DX value rises; if they are balanced, the value remains lower.
3. Smoothing and Weighted Averaging (The WMA Modification) This is where the script differs from standard tools. Instead of using a simple average, it applies two layers of smoothing:
- Exponential Smoothing: The initial +DI and -DI values are smoothed using an Exponential Moving Average (EMA). This helps filter out "noise" or minor price flickers that don't represent a real trend.
- Weighted Moving Average (WMA): Finally, the script applies a weighted calculation to the DX value to produce the final ADX line. By weighting the data, the indicator prioritizes more recent price action, allowing it to react more intelligently to new market trends while maintaining a smooth visual flow.
Summary for the Trader
In practical terms, this tool tells you two things:
- Direction: By observing the +DI and -DI lines, you can see which side (buyers or sellers) is currently in control.
- Strength: The final ADX line indicates how powerful that trend is. Because of the Weighted Moving Average logic, the resulting line is designed to be more responsive to current market shifts than a standard indicator, providing a clearer picture of whether a trend is gaining momentum or losing steam.
/*-----------------------------+
| |
| Shared by www.Aptrafx.com |
| |
+------------------------------*/
//+------------------------------------------------------------------------+
//| ADX-WMA-version.mq4 |
//|Copyright © 2004, MetaQuotes Software Corp. modified by Pascal Le Clech |
//| http://www.forex-trading-chart.com |
//+------------------------------------------------------------------------+
#property copyright "Copyright © 2004, MetaQuotes Software Corp. modified by Pascal Le Clech"
#property link "http://www.forex-trading-chart.com"
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 Blue
#property indicator_color2 Green
#property indicator_color3 Red
//---- input parameters
extern int ADXPeriod=14;
//---- buffers
double ADXBuffer[];
double PlusDiBuffer[];
double MinusDiBuffer[];
double PlusSdiBuffer[];
double MinusSdiBuffer[];
double TempBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- 3 additional buffers are used for counting.
IndicatorBuffers(6);
//---- indicator buffers
SetIndexBuffer(0,ADXBuffer);
SetIndexBuffer(1,PlusDiBuffer);
SetIndexBuffer(2,MinusDiBuffer);
SetIndexBuffer(3,PlusSdiBuffer);
SetIndexBuffer(4,MinusSdiBuffer);
SetIndexBuffer(5,TempBuffer);
//---- name for DataWindow and indicator subwindow label
IndicatorShortName("ADX("+ADXPeriod+")");
SetIndexLabel(0,"ADX");
SetIndexLabel(1,"+DI");
SetIndexLabel(2,"-DI");
//----
SetIndexDrawBegin(0,ADXPeriod);
SetIndexDrawBegin(1,ADXPeriod);
SetIndexDrawBegin(2,ADXPeriod);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Average Directional Movement Index |
//+------------------------------------------------------------------+
int start()
{
double pdm,mdm,tr;
double price_high,price_low;
int starti,i,counted_bars=IndicatorCounted();
//----
i=Bars-2;
PlusSdiBuffer[i+1]=0;
MinusSdiBuffer[i+1]=0;
if(counted_bars>=i) i=Bars-counted_bars-1;
starti=i;
//----
while(i>=0)
{
price_low=Low[i];
price_high=High[i];
//----
pdm=price_high-High[i+1];
mdm=Low[i+1]-price_low;
if(pdm<0) pdm=0; // +DM
if(mdm<0) mdm=0; // -DM
if(pdm==mdm) { pdm=0; mdm=0; }
else if(pdm<mdm) pdm=0;
else if(mdm<pdm) mdm=0;
//---- âû÷èñëÿåì èñòèííûé èíòåðâàë
double num1=MathAbs(price_high-price_low);
double num2=MathAbs(price_high-Close[i+1]);
double num3=MathAbs(price_low-Close[i+1]);
tr=MathMax(num1,num2);
tr=MathMax(tr,num3);
//---- counting plus/minus direction
if(tr==0) { PlusSdiBuffer[i]=0; MinusSdiBuffer[i]=0; }
else { PlusSdiBuffer[i]=100.0*pdm/tr; MinusSdiBuffer[i]=100.0*mdm/tr; }
//----
i--;
}
//---- last counted bar will be recounted
if(counted_bars>0) counted_bars--;
int limit=Bars-counted_bars;
//---- apply EMA to +DI
for(i=0; i<=limit; i++)
PlusDiBuffer[i]=iMAOnArray(PlusSdiBuffer,Bars,ADXPeriod,0,MODE_EMA,i);
//---- apply EMA to -DI
for(i=0; i<=limit; i++)
MinusDiBuffer[i]=iMAOnArray(MinusSdiBuffer,Bars,ADXPeriod,0,MODE_EMA,i);
//---- Directional Movement (DX)
i=Bars-2;
TempBuffer[i+1]=0;
i=starti;
while(i>=0)
{
double div=MathAbs(PlusDiBuffer[i]+MinusDiBuffer[i]);
if(div==0.00) TempBuffer[i]=0;
else TempBuffer[i]=100*(MathAbs(PlusDiBuffer[i]-MinusDiBuffer[i])/div);
i--;
}
// Modification with WMA by Pascal Le Clech
int cnt=Bars;
if(counted_bars>=cnt)
cnt=Bars-counted_bars-1;
//----
// if Bars < Period then no calculation
if(limit>0){
while(cnt>=0){
if(cnt>Bars-ADXPeriod){
ADXBuffer[cnt]=TempBuffer[cnt]/cnt+(cnt-1)*ADXBuffer[cnt+1]/cnt;
}
else{
ADXBuffer[cnt]=TempBuffer[cnt]/ADXPeriod+(ADXPeriod-1)*ADXBuffer[cnt+1]/ADXPeriod;
}
cnt--;
}
}
else{
return (0);
}
//
//---- ADX is exponential moving average on DX
/* for(i=0; i<limit; i++)
ADXBuffer[i]=iMAOnArray(TempBuffer,Bars,ADXPeriod,0,MODE_EMA,i);
*/
//----
return(0);
}
//+------------------------------------------------------------------+
Comments