Introduction
Average True Range (ATR) is an indicator that measures volatility. As with most of his indicators, Wilder designed ATR with commodities and daily prices in mind. Commodities are frequently more volatile than stocks. They were are often subject to gaps and limit moves, which occur when a commodity opens up or down its maximum allowed move for the session. A volatility formula based only on the high-low range would fail to capture volatility from gap or limit moves. Wilder created Average True Range to capture this "missing" volatility. It is important to remember that ATR does not provide an indication of price direction, just volatility.
In ATR we have conception called True Range (TR), which is defined as the greatest of the following:
Absolute values are used to insure positive numbers. After all, Wilder was interested in measuring the distance between two points, not the direction. If the current high-low range is large, chances are it will be used as the True Range. If the current high-low range is small, one of the other two methods would likely be used to calculate the True Range. The last two possibilities usually arise when the previous close is greater than the current high (signaling a potential gap down or limit move) or the previous close is lower than the current low (signaling a potential gap up or limit move). The high-low range is used as the TR for day one because it is impossible to use the previous close for the first day.
ATR is not a directional indicator, such as MACD or RSI. Instead, ATR is a unique volatility indicator that reflects the degree of interest or disinterest in a move. Strong moves, in either direction, are often accompanied by large ranges, or large True Ranges. This is especially true at the beginning of a move. Uninspiring moves can be accompanied by relatively narrow ranges. As such, ATR can be used to validate the enthusiasm behind a move or breakout. A bullish reversal with an increase in ATR would show strong buying pressure and reinforce the reversal. A bearish support break with an increase in ATR would show strong selling pressure and reinforce the support break.
using System; using System.Collections; using System.Collections.Generic; using System.Text; using PTLRuntime.NETScript; using System.Drawing; namespace ind { //--------------------------------------------------- // Project: AveTrueRange // Type: Indicator // Author: PFSoft LLC // Company: PFSoft LLC /www.pfsoft.com/ // Copyright: (C) PFSoft LLC Dnepropetrovsk. Ukraine // Created: Nov, 28,2006 //--------------------------------------------------- public class ATR : NETIndicator { public ATR() : base() { ProjectName = "Average True Range"; Comments = "Measures market volatility"; SetIndicatorLine("line1", Color.Blue, 1, LineStyle.SimpleChart); SeparateWindow = true; } [InputParameter("Period of Moving Average", 0)] public int MAPeriod = 13; [InputParameter("Type of Moving Average", 1, new object[] { "Simple", "SMA", "Exponential", "EMA", "Modified", "MMA", "Linear Weighted", "LWMA"} )] public string MAType = "SMA"; public override void OnQuote() { int count; count = platform.BarsCount(platform.Symbol, platform.Period); if(count>MAPeriod) { switch(MAType) { case "SMA": platform.SetValue(0, 0, GetSMA(count)); break; case "EMA": platform.SetValue(0, 0, GetEMA(count)); break; case "MMA": platform.SetValue(0, 0, GetMMA(count)); break; case "LWMA": platform.SetValue(0, 0, GetLWMA(count)); break; } } } public double GetSMA(int count) { int i = 0; // Usual counter double summa = 0.0; // Sum of prices int period = 0; // period counter // Loop of calculation. The loop skips empty bars while( (period<MAPeriod) && (i<count) ) { // Chiking, if the current bar is empty if(!ptl.IsEmpty(i)) { // Bar is not empty, adding it's price to the summa summa += ptl.TrueRange[i]; // increment of period counter period++; }; // going to the next bar i++; } // Returning current value of the SMA return summa/MAPeriod; } public double GetEMA(int count) { // Calculation of a coefficient double k = 2.0/(MAPeriod + 1); // Getting current price double price = ptl.Array[1]; // Calculation of current EMA price = price + k*(ptl.TrueRange - price); // Saving it in the buffer ptl.Array[0] = price; // Returning value return price; } public double GetMMA(int count) { int i = 0; // Usual counter double mma; mma = ptl.TrueRange; // Current price int period = 0; // period counter double k = 1.0/MAPeriod; // coefficient // Loop of calculation. The loop skips empty bars while( (period<MAPeriod) && (i<count) && (mma>0.0) ) { // Chiking, if the current bar is empty if(!ptl.IsEmpty(i)) { // Bar is not empty, adding it's price to the summa double price; price = ptl.TrueRange[i]; mma = price*k + mma*(1.0 - k); // increment of period counter period++; } // going to the next bar i++; } // Returning of mma return mma; } public double GetLWMA(int count) { int i = 0; // Usual counter double numerator = 0.0; // Numerator of the rate double denominator = 0.0; // Denominator of the rate int period = MAPeriod; // period counter double k = 1.0/MAPeriod; // coefficient // Loop of calculation. The loop skips empty bars while( (period>0) && (i<count) ) { // Chiking, if the current bar is empty if(!ptl.IsEmpty(i)) { // Bar is not empty, adding it's price to the summa numerator += period*ptl.TrueRange[i]; denominator += period; // increment of period counter period--; }; // going to the next bar i++; }; // returning current value if(denominator>0.0) return numerator/denominator; else return 0.0; } } }
Comments