So in my continuing series of C# implementations of common indicators, I spent all of yesterday working out the ADX. The ADX was originally developed by J. Welles Wilder and published in his book New Concepts in Technical Trading Systems, June 1978.

Various sites report implementations, but always define it in terms of indicators which have varying definitions. Namely FxStreet defines the general concept here, but only in terms of DI+/-, TR and DM+/-, each of which has varying definitions. ForexReal defines ADX here, but uses a completely different concept of TR. Stockwiz has a good overview of all of the variables used (at least they define all of their variables) here. I will be defining the ADX all the way down to price action (what you need when you are coding this…) as best I can to the original definition by J Welles Wilder.

Lets start by defining the Directional Move indicators

## Directional Move Indicator

= the Positive Direction Movement Indicator

= the Negative Direction Movement Indicator

We use two helper variables to track the delta extreme price changes from yesterday

If today’s range is entirely within yesterday’s range, or the range is the same, then there has been no directional movement.

If the range moved up, then there has been a positive directional move.

If the range moved down, then there has been a negative directional move.

## Average Directional Move Indicator

= the Average Positive Direction Movement Indicator for N periods

= the Average Negative Direction Movement Indicator for N periods

The Welles Wilder Average is used here to stay true to form, but this average introduces a lot of latency, so I will also implement an exponential moving average.

Alternatively, the formula for the ADM with an exponential moving average is shown below.

## True Range

is the true range for a given period. It is a measure of volatility and takes into account any overnight gap in the period’s price.

## Average True Range

is the average true range for N periods.

The Welles Wilder Average is used here again to stay true to form, but for my C# implementation I will be using the exponential moving average.

Alternatively the ATR can be calculated with the exponential moving average as shown below.

## Directional Index

is the average positive directional movement indicator normalized by the average true range.

is the average negative directional movement indicator normalized by the average true range.

The directional index calculation is very straight forward and shown below.

## Directional Movement Index

– the directional movement index is the difference of the directional indices over the sum directional indices.

## Average Directional Movement Index

is the average directional movement calculated over N periods.

Staying true to form again, the Welles Wilder Average is used below.

Again, you can alternatively use the exponential moving average as shown below.

## C# implementation

So after the laborious research to determine exactly what the ADX is and should be (exponential vs Welles Wilder Average), here is the C# implementation of this indicator.

//The Average Directional Indicator

if(barHistory[timePeriod].Count > 1)

{

//Directional Movement Indicator

double deltaHigh = cBar.High – barHistory[timePeriod][barHistory[timePeriod].Count – 2].High;

double deltaLow = barHistory[timePeriod][barHistory[timePeriod].Count – 2].Low – cBar.Low;

if((deltaHigh < 0 && deltaLow < 0) || (deltaHigh == deltaLow))

{

sig.DmPlus = 0;

sig.DmMinus = 0;

}

else

if(deltaHigh > deltaLow)

{

sig.DmPlus = deltaHigh;

sig.DmMinus = 0;

}

else

if (deltaHigh < deltaLow)

{

sig.DmPlus = 0;

sig.DmMinus = deltaLow;

}

//Average Directional Movement Indicator

if(barHistory[timePeriod].Count <= 2)

{

sig.AdmPlus = sig.DmPlus;

sig.AdmMinus = sig.DmMinus;

}

else

{

double a = (double) 2/(double) (calc.DMIPeriod + 1);

sig.AdmPlus = sig.DmPlus * a +

symbolHistory[timePeriod][symbolHistory[timePeriod].Count-2].AdmPlus * (1-a);

sig.AdmMinus = sig.DmMinus * a +

symbolHistory[timePeriod][symbolHistory[timePeriod].Count – 2].AdmMinus * (1 – a);

}

//True Range Indicator

sig.TrueRange = Math.Max(Math.Abs(cBar.High – cBar.Low),

Math.Max(

Math.Abs(cBar.High – barHistory[timePeriod][barHistory[timePeriod].Count – 2].Close),

Math.Abs(barHistory[timePeriod][barHistory[timePeriod].Count – 2].Close – cBar.Low)));

//Average True Range Indicator

if(barHistory[timePeriod].Count <= 2)

{

sig.AverageTrueRange = sig.TrueRange;

}

else

{

double a = (double)2 / (double)(calc.ADXPeriod + 1);

sig.AverageTrueRange = sig.TrueRange * a +

symbolHistory[timePeriod][symbolHistory[timePeriod].Count – 2].AverageTrueRange * (1 – a);

}

//Directional index Indicator

if (sig.TrueRange != 0)

{

sig.DiPlus = 100 * sig.AdmPlus/sig.TrueRange;

sig.DiMinus = 100 * sig.AdmMinus/sig.TrueRange;

}

else

{

sig.DiPlus = symbolHistory[timePeriod][symbolHistory[timePeriod].Count – 2].DiPlus;

sig.DiMinus = symbolHistory[timePeriod][symbolHistory[timePeriod].Count – 2].DiMinus;

}

//Directional Movement Index Indicator

if ((sig.DiPlus + sig.DiMinus) != 0)

sig.Dx = Math.Abs((sig.DiPlus – sig.DiMinus)) / (sig.DiPlus + sig.DiMinus) * 100;

else

sig.Dx = symbolHistory[timePeriod][symbolHistory[timePeriod].Count – 2].Dx;

//Average Directional Movement Indicator

if (barHistory[timePeriod].Count <= 2)

{

sig.Adx = sig.Dx;

}

else

{

double a = (double)2 / (double)(calc.DMIPeriod + 1);

sig.Adx = sig.Dx * a +

symbolHistory[timePeriod][symbolHistory[timePeriod].Count – 2].Adx * (1 – a);

}

}

## Sample Data

This is a sample data set consisting of the NYSE A/D 1-min bar data (“Close”) from August 28, 2007 and the 14 period ADX in red.

Hola, muy buena argumentacion respaldada por su respectiva implementacion en C#, solo me queda una duda,

puede que en esta parte:

Average Directional Movement Index

is the average directional movement calculated over N periods.

Staying true to form again, the Welles Wilder Average is used below.

se te halla pasado y colocaste el calculo del indicador True Range en Lugar de DX ?

Saludos.

Wow, this is awesome, exactly what I was looking for. Thank you.

At 14:24, the ADX takes off and climbs to .35 while the price barely moves. Shouldn’t the ADX be falling during this period?

Ah, I see now that you are comparing it w/ the NYSE A/D 1-min bar data.

I have not been able to get this formulas equal to the Marketscope ADX values. For some reason the first adx calculated is equal, but from the 2nd Adx it is not getting equal. Did you check the values that your formulas calculate against any other tool? It seems that it’s something about the Average Directional Movement Indicator, because the ATR i’m getting through your formulas is accurate against de Marketscope ATR.

Anyway your post has been so helpfull, but I want to get values that match exactly compared to the marketscope tool so I can verify more clearly my strategy.

The ADX formula is wrong. Replace the TR with DX and it works fine for me. Besides that, GREAT work

Great work – I’ve been struggling to build this myself due to the complexity of the indicator. This helped me a lot and is the best explanation I’ve seen on the web. Thanks!

I did it this way (for DMI and -DMI only). I didn’t really get ur method (iam not that good at math lol)

Used a array for the Low,High,Close data’s named Quotes. Any feedback is welcome =)

private void CalcDMI()

{

decimal TR = 0;

decimal DMP = 0;

decimal DMM = 0;

for (int x = 0; x 0 && HD > LD) ? HD : 0;

DMM = (LD > 0 && LD > HD) ? LD : 0;

}

PDI = (DMP * 100) / TR;

MDI = (DMM * 100) / TR;

}

hmm my reply is all f*cked up =( guess i cant post that many chars, nvermind than xD. srry!

Hi,

ultimately which indicator do you recomend between the exponential MA and the Welles Wilder Avergae ? It seems to me that the 14 days Wilder average is like a 27 exponential moving average … but i’d like to get a confirmation on what to use …

TKs a lot for all the formula though !

@cdm: yes, the length ‘n’ wilder average is just a length ‘2n-1’ EMA.

Thanks a bunch! This formula was just what I needed for my school report.

ciao,

q.

Thanks for a detailed explanation on ADX, it was quite informative. Thanks again for the good work

Great Work, I implemented the same but in a much more gruesome brute force kinda manner. Knowing the formula helps and simplifies it a lot.

Do you have the src for this available? if not then its fine.

Thanks anyways

Hello everyone… how exactly should i get the Previous parameters (t-1)? e.g. when the formula says: PlusADM(t) = PlusADM(t-1)*(1-n/n)+(PlusDM(t))*(1/n) ; when the PlusADM(t-1) should come from? if i starts by the order from the begining, and i have only current and historical data for open, close, high, and low parameters so when High(t) means the high for November 5 then high(t-1) means high of november 4, it’s makes sense for PlusDM and MinusDM since they depend only on the parameters of open and close data and we can get them, but the PlusADM(t=Nov5 for example) defined with the previous PlusADM in it [PlusADM(Nov4)] so where it’s should starts from (and if you can get the historical PlusADM (for Nov4) then what’s the point in all that formula?), i don’t have the Nov4 PlusADM so assuming i start the application on Nov5 the current PlusADM cannot be defined right? what i miss here?

thanx alot.

Can you send me all source code of you class please. It’ll be very helpful.

Thanks.

what values do you take for t-1 when considering calculations for the first day? Do caclulations really only start on Day 2 since that is only when one has previouos days’ data to use in calc?

Very rapidly this web site will be famous amid all blogging people, due to

it’s nice articles

多くの方法前記達成夢中時計それらテレビことがなくに従うことその剛体機会スケジュール。選択することができるかどうかyoud好む朝または午後のスロット。

http://必要なを許可するように夢中この時計完全ビデオのためをすべてを持っています基本的な食材に楽しませて。あなたもすることができます夢中時計すべてのチャンネルすべての場合無料。会社になると取りつかれているこの特定のミッションの開発スクラッチプルーフ夢中夢中時計。

Hey

How would you modify the code if you were to apply this indicator on some other indicator( or time series)instead of bar data.

Regards

Maddy

Apart from all these perks that include unswerving gratitude, tax exemption

is amongst the greatest. However, buying gold along with other precious metals takes knowledge plus

a plan. plus a one-time account setup fee (that also includes

commission) that is usually about 10%. Having that

in mind, this unstable marketplace is leading us to rethink how we can still be

at the solid investment in the midst of the market’s challenges.

It allows you in order to save the value of the hard earned money to the future.

For that demonstration singularly, it’s important to be superbly schooled

on the codes of conducts that are invoked inside the Lubbock county jail in Lubbock Texas,

survey your sayings, ally with you’re your own genre and be informed of the arranged regiments inside the Lubbock county jail in Lubbock Texas as they sketch the priority.

External doors and windows are double glazed with.

1 Construction Equipment Consumption Value

Review.

My web site :: despacho de arquitectos df

Awesome website you have here but I was wanting to know

if you knew of any message boards that cover the

same topics discussed in this article? I’d really like

to be a part of group where I can get responses

from other experienced people that share the same interest.

If you have any suggestions, please let me

know. Thanks!

Aw, this was a very good post. Taking the time and actual

effort to generate a superb article… but what can I say… I

hesitate a whole lot and never seem to get anything done.

Your own info with suggestions vastly within reach if you ask me.

Thank you especially much before hand. Your current acquaintance on this area is fantastic,

I’m glad so as to this is stumble on. Thank you once more!

There are a lot of people that will not complete online surveys

because they have to give the companies too much person information,

and for good reason. A good online research will surely help you find companies that are honestly willing to pay you for your

valuable feedback. The landlord initially carries the

deposit as a liability.

I like what you guys are usually up too. This type of clever work and

coverage! Keep up the terrific works guys I’ve added you guys

to my personal blogroll.

I really like it when folks get together and share ideas.

Great site, stick with it!

Most of the times the surveys are carried out for some manufacturing or service company.

Surveymonkey provides a host of functionality such as selecting the background

theme, creating new pages, and selecting the type of questions.

If you are looking for a website to start with this money making tactic, then visit australianfreepaidsurveys.

get paid to post

Thanks for your personal marvelous posting! I quite

enjoyed reading it, you are a great author. I will always

bookmark your blog and will come back down the road.

I want to encourage you to continue your great posts,

have a nice day!

Hello there, just became aware of your blog

through Google, and found that it’s really informative.

I’m gonna watch out for brussels. I’ll appreciate if you continue this in future.

Many people will be benefited from your writing.

Cheers!

Кids right now watch tv for exttended hours.

Here is mʏ web-site: ρunch tv network (Elida)

Thankfulness to my father who shared with me regarding this web site, this weblog is truly amazing.

Genuinely no matter if someone doesn’t be aware of afterward its up to other

users that they will help, so here it takes place.

What’s Happening i am new to this, I stumbled upon this I’ve found It positively useful and it has helped me out loads.

I am hoping to give a contribution & aid

other users like its helped me. Great job.

Thanks for your comments. This arlicte is an example of how to use such indicators to build a strategy that works. You are right, we can do some back-test and optimization using in-sample data and apply the optimized strategy to out-sample data. However, in my opinion, the optimization procedure is much crucial to the model-based strategy. For example, in RIZM, one of our model-based strategies is pairs trading. We use in-sample data to find the optimal pairs, and apply and backtest them to the out-sample data. For those indicator strategy, for sure, we can optimize the indicator’s parameters and generate much better result. But we have no intention to do it here since everyone favors different parameters of technical indicators that they want to use. We came up with the parameters that are based on our intuition and observations. Since there are no optimization procedures here, you can treat the backtest result as the one generated from the out-sample data already. Of course, when you do the real-time trading, you will incur some issues like transaction fee, slippage, or order execution speed. That’s always the gap between real-time trading and backtesting. To partially solve these issues, in your backtesting procedure, you can try to make the result as close as the one in real-time by raising your transaction cost assumption. And, after the backtesting, we encourage you to do the paper trade to fill the gap. Hope these make sense.