User login

  

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.

True Range

In ATR we have conception called True Range (TR), which is defined as the greatest of the following:

  • Current High less the current Low
  • Current High less the previous Close (absolute value)
  • Current Low less the previous Close (absolute value)

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.

Conclusions

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.

 

Display/hide source code
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;    
                }
    }    
}
12345

Comments