Calculation of ADX

Discussion in 'Technical Analysis' started by prisma, Apr 11, 2003.

  1. prisma



    I try to calculate ADX(14) manually but so far I did not succeed in reproducing the values of chartprograms like WealthLab.

    Which formula is th one I need and what periods are normally used ?

    Thanks !

  2. Not sure why you would want to calculate this by hand. There is no simple formula. If you are truly interested in how most technical indicators are calculated, I would suggest that you get the book "Trading for a Living" by Dr. Alexander Elder. You will find the ADX calculation method in pages 135-139. Or, you can get "New Concepts in Technical Trading Systems" by J. Welles Wilder, who developed the idea of ADX.

    The calculation method is simply too lenthy to reproduce here.

    You can use any time period that you want, but most use a 14 period calculation.

  3. agrau


    The following post appeared on the xltrader list on 08-08-2001. I don't know if the statements and the code are correct, but it may help you anyway.


    +++ Snip +++

    I discovered, in dissecting the ADX algorithm, that Welles Wilder
    isn't as smart as he thinks. Either that or he diliberately
    incorporated True Range to ADX confuse or impress people.

    You see, with all his talk about discovering True Range and what a
    deep market truth it is, and after developing his ADX indicator that
    has True Range as part of the calculation, he doesn't seem to realize
    that ALL the True Range terms cancel out! Do the math, or test it
    yourself. You can substitute random numbers and get identital

    Here's the VB source. Note the final calculation for DX uses terms
    which are all ratios having ATR in the denominator, and they all
    cancel out.


    Option Explicit

    'Exponential moving average
    'Closely approximates true moving average
    ' last_ema = previous period's ema result
    ' a = new value to incorporate into ema
    ' n = number of periods
    'Return value: current ema

    Function ema(ByVal last_ema As Double, ByVal a As Double, ByVal n As
    Integer) As Double
    Dim w As Double
    w = 2# / (n + 1)
    ema = (1# - w) * last_ema + w * a
    End Function

    'Wilder's ADX
    ' last_adx = value of ADX from previous period
    ' n = number of periods to use
    ' init = initialize averages (set to TRUE on 1st call)
    ' H, L = current high and low
    ' Hp, Lp, Cp = previous high, low, close
    'Return value: current ADX

    Function ADX(last_adx As Double, n As Integer, init As Boolean, _
    H As Double, L As Double, _
    Hp As Double, Lp As Double, Cp As Double) As Double

    Dim i As Integer, tmp1 As Double, tmp2 As Double, TR As Double
    Dim PDM As Double, MDM As Double, PDI As Double, MDI As Double
    Dim DX As Double
    Static ATR As Double, APDM As Double, AMDM As Double 'averages

    If init Then ATR = 0#: APDM = 0#: AMDM = 0#

    'step 1: calculation of directional movements
    ' DM is the largest part of the current trading range that
    ' is outside the previous trading range
    ' PDM = max(0, H - Hp) (plus direction movment)
    ' MDM = min(0, L - Lp) (minus direction movment)
    'For an outside day:
    ' if |PDM| < |MDM| then PDM=0
    ' if |PDM| > |MDM| then MDM=0
    ' else PDM=MDM=0
    'Here's a better alternative that works just as well or better:
    'tmp1 = (H - Hp + L - Lp) / 2#
    'If tmp1 > 0# Then PDM = tmp1: MDM = 0# Else MDM = tmp1: PDM = 0#
    '...but we'll use Wilder's way for now.

    PDM = Application.WorksheetFunction.Max(0, H - Hp)
    MDM = Application.WorksheetFunction.Min(0, L - Lp)
    tmp1 = Abs(PDM): tmp2 = Abs(MDM)
    If tmp1 < tmp2 Then
    PDM = 0#
    ElseIf tmp2 < tmp1 Then
    MDM = 0#
    PDM = 0#: MDM = 0# 'inside day
    End If

    'step 2: calculation of true range (TR)
    ' TR = max(H-L, Cp-L, H-Cp) where Cp=previous close

    TR = Application.WorksheetFunction.Max(H - L, Cp - L, H - Cp)

    'step 3: plus and minus directional indicators PDI and MDI
    ' The average plus and minus directional movement values are
    ' divided by the average TR to get PDI and MDI. An exponential
    ' moving average closely approximates the true average.
    ' ema(|PDM|, n) ema(|MDM|, n)
    ' PDI = ------------- MDI = -------------
    ' ema(TR, n) ema(TR, n)

    ATR = ema(ATR, TR, n) 'average true range
    If ATR = 0# Then 'special case ATR=0
    PDI = APDM: MDI = AMDM 'use previous average values
    APDM = ema(APDM, Abs(PDM), n)
    AMDM = ema(AMDM, Abs(MDM), n)
    PDI = APDM / ATR
    MDI = AMDM / ATR
    End If

    'step 4: calculation of direction movement index DX
    ' Step 3 isn't necessary for calculation of DX, because the
    ' ATR term cancels out here. Then PDI=APDM and MDI=AMDM.
    ' PDI - MDI
    ' DX = ----------- '* 100
    ' PDI + MDI
    ' we won't multiply by 100, so our ADX will be from 0 to 1.

    tmp1 = PDI + MDI
    If tmp1 = 0# Then
    DX = last_adx
    DX = Abs(PDI - MDI) / tmp1
    End If

    'step 5: calculation of average directional movement index ADX
    ' ADX = ema(|DX|, n)

    ADX = ema(last_adx, Abs(DX), n)
    End Function

    +++ End Snip +++
  4. prisma



    I would like a VisualBasic-program to give me my trading-signals and one of the conditions involves the ADX(14).

    Don't you know of any web-site, which describes the formula in detail ?

  5. prisma



    thanks a lot !!! (Danke !)

    I will try to implement it in my program.

  6. Http:// has a library of indicators and the explanations of there "typical uses." More importantly, they often include the math for how they are calculated. I've used it for this purpose many times.
  7. Here is some VB code I wrote a couple of years ago to calculate ADX/DMI. It is based on the formula in the Achelis "Technical Analysis from A to Z". If you are serious about programming your own formulas, I would suggest getting the companion spreadsheet at

    I don't have time to go through and document this code snippet, but if you have specific questions, let me know. Basically, you load up the structure with your data and it calculates it.
  8. agrau


    From the Metastock list sometime in May 1999. This may speed up your calculation time, in case it matters.


    N.B. Ref(C,-1) means previous day's Close

    +++ Snip +++


    A friend showed that TrueRange required no comparisons; the algorithm in MS'ese is

    TR = (H - L + Abs(H - Ref(C,-1)) + Abs(L - Ref(C,-1)) )/2


    +++ End Snip +++
  9. Try "Trading for a Living" by Dr. Alexander Elder. He outlines the formula step by step - Page 135 - 139.