AMA - Kaufman’s Adaptive Moving Average Formula in C#

So I have not been posting as much lately, as I have been working on an Auto Trading System, and after spending far too much time researching signal formulas, I thought I would being to post the implementations of various signals I am using in my ATS.

The Kaufman Adaptive Moving Average is a great low latency moving average filter. It technically has an infinite tail, but cleverly weights the amount of signal for each new bar based on the historical trendiness. If the past data has been choppy, then each new bar is weighed very low in the average, however if the past data has offered a strong direction (regardless of magnitude) then the average weighs new signal very heavily.

There aren’t too many sites discussing the actual formula - I based my implementation on the MetaStock code found here.

I started writing this post in windows Live Writer, and found that it does not keep Visual Studio’s source formatting, so I will try to post this from Word 2007. Word is much better at formatting, but terrible with images, while Live is great with images and managing the site, but terrible with formatting.

//Direction is just present over previous price

double direction = cBar.Close - BarHistory[timePeriod][BarHistory[timePeriod].Count - cnt].Close;

double vol = 0;

//Vol is the sum of all differences in the past period

for (int ix = 1; ix < cnt; ix++)

{

vol +=

Math.Abs(BarHistory[timePeriod][BarHistory[timePeriod].Count - ix - 0].Close -

BarHistory[timePeriod][BarHistory[timePeriod].Count - ix - 1].Close);

}

//if not enough data, or there has been no price change, then AMA is price.

if ((direction == 0 && vol == 0) || cnt == 1)

{

sig.Ama = cBar.Close;

}

else

{

//Elastic ratio

double ER = Math.Abs(direction/vol);

double FastSC = 2/(calc.AMAFastEMA + 1);

double SlowSC = 2/(calc.AMASlowEMA + 1);

double SSC = ER*(FastSC - SlowSC) + SlowSC;

//This is the magic scaling/smoothing constant.

double conC = SSC*SSC;

if (cnt == 2)

{

sig.Ama = BarHistory[timePeriod][0].Close + conC*(cBar.Close - BarHistory[timePeriod][1].Close);

}

else if (cnt > 2)

{

sig.Ama = BarHistory[timePeriod][barHistory[timePeriod].Count - 2].Close +

conC*(cBar.Close - BarHistory[timePeriod][barHistory[timePeriod].Count - 2].Close);

}

}

This is easily my favorite indicator, and with a lot of tweaking can actually be made to have a lot lower latency. The key thing about noise removal, is that signals are noisiest when their trending derivative is lowest. This fact allows a lot of clever hacks to lower the latency of filters like the ATX. That being said, it is often important to use an indicator unscathed, as so much of the market uses it, its performance is a self fulfilling prophesy.

9 Responses to “AMA - Kaufman’s Adaptive Moving Average Formula in C#”


  1. 1 Paul

    I did some backtesting in Tradestation on the AMA but not nearly enough to figure out whether it was a very useful tool. Have you found it to be extremely useful in your trading systems?

  2. 2 Karl

    Extremely useful - you can make some mod’s to the AMA to get it to move really fast, and given the nature of moving averages, this signal can speed up nearly any technical indicator (they all use an average in them…)

  3. 3 Paul

    Yeah I see what you mean. You could modify bollinger bands or any other technical indicators that use averages. Hadn’t thought of that. Thanks for the tip.

  4. 4 Paul

    You always consult Kaufman’s book: “Smarter Trading” where he lays out the formula but it looks like you found it with Go-Go-Gadget Google.

  5. 5 Subhasish Mitra

    How the period number(n) afftect the prediction of AMA?

  6. 6 Karl

    Ama does not use prediction, the number(n) affects the number of periods that are averaged to determine the smoothing constant.

    Thanks,

    -Karl

  7. 7 James

    ADAPTIVE MOVING AVERAGE

    Is any one able to supply me with the formula for the above for Microsoft Excel or Lotus 123.

    Thanks

  8. 8 Navin

    PROBLEM IN SOURCE CODE

    The efficiency ratio ER
    (double ER = direction/vol;)

    should be absolute value and hence should be calculated as Abs(direction/vol).

    alternatively you can do Abs(direction)

  9. 9 Karl

    Thanks Navin,

    I just updated this in the source.

Leave a Reply