Average ATR values for stocks in an index

Can anyone tell me how to calculate the average ATR% for all stocks in an index? I want to use this in my position sizing.

ATR% = ATR(30)/C

I would like to know what the average ATR% is across all stocks in a particular index.

thanks, Tim.

@timhopson I'm not sure if this is the only method or even exactly if it suits your need, but using StaticVarAdd you can loop through the symbols in your Watch List (your Index) and calculate an average. There is probably a simpler method though I am familiar with building composites this way so it was quick for me to post.

// Building a composite ATR reading for a WL using StaticVarAdd 

// pick watchlist in AA window, run EXPLORE
wlnum = GetOption( "FilterIncludeWatchlist" );
List = CategoryGetSymbols( categoryWatchlist, wlnum );

if( Status( "stocknum" ) == 0 )
{
    // cleanup variables created in previous runs
    StaticVarRemove( "~SymbolCount*" );
    StaticVarRemove( "~ATRtotal*" );

    for( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++ )
    {
        SetForeign( symbol );
        ATRVal = ATR( 30 );
        StaticVarAdd("~SymbolCount", 1);
        StaticVarAdd( "~ATRtotal", ATRVal );

        RestorePriceArrays();
    }
}

svATRtotal= StaticVarGet( "~ATRtotal" );
svSymbolCount = StaticVarGet( "~SymbolCount" );
AveATRofIndexConstituents = svATRtotal/svSymbolCount;

///////////////////////////////////////////////////
// Explore, let's display the whole WL and confirm
///////////////////////////////////////////////////
Filter = 1;
AddColumn(ATR(30), "ATR(30)");
AddColumn( svATRtotal , "svATRtotal", 1.2 );
AddColumn( svSymbolCount, "Total Number of Stocks", 1.0 );
AddColumn( AveATRofIndexConstituents , "AveATRofIndexConstituents ", 1.2 );


///////////////
// Chart
///////////////
Plot( AveATRofIndexConstituents, "AveATRofIndexConstituents", colorAqua, styleThick );

image

4 Likes

Well if a symbol does not have data for a bar then it should not be included into symbol count.

So here is another way.

Set chart symbol to index your symbols belong too.
Make sure index symbol's price data is up to date.
Assign watchlist number your symbols belong to to 'listnum' variable
Open Parameter window and click "CLICK HERE".

/// Set chart symbol to index your symbols belong too
/// Make sure index symbol's price data is up to date
/// Assign watchlist number your symbols belong to to 'listnum' variable
/// Open Parameter window and click "CLICK HERE"
///
function Average_ATR_Category ( category, listnum, fixup ) {
   /// @link https://forum.amibroker.com/t/average-atr-values-for-stocks-in-an-index/11006/3
   /// retrieve comma-separated list of symbols in watch list
    list = CategoryGetSymbols( category, listnum );
    sumarray = count = 0; // initialize
    for ( i = 0; ( sym = StrExtract( list, i ) ) != ""; i++ ) {
        // see fixup options 0 to 2 in manual of Foreign() 
        /// @link https://www.amibroker.com/guide/afl/foreign.html 
        SetForeign( sym, fixup );   
			array = ATR(30)/C;
			sumarray += Nz( array );			
			count += NOT IsNull( C );
        RestorePriceArrays();
    }    
    return sumarray / count; // multi symbol average
}

listnum = 0; // watchlist number

/// @link https://www.amibroker.com/guide/afl/setbarsrequired.html
/// if you want to disable QuickAFL then uncomment
//SetBarsRequired(sbrall);

// some time consuming calculation executed by some trigger
if ( ParamTrigger( "Create Avgerage", "CLICK HERE" ) ) {	
    x = Average_ATR_Category ( categoryWatchlist, listnum, fixup = 0 );
    // store time consuming variables as static variables
    StaticVarSet( "AvgATR", x, persistentstorage = False );
}

x = StaticVarGet( "AvgATR" );

if ( LastValue( Cum(x) ) == 0 && Status( "actionex" ) != actionExEditVerifyFormula )
	Error( "Open Parameter window (CTRL+R) and click 'Click HERE'!" );

Plot( x, "AvgATR", colorRed, styleLine );

57

1 Like

Thanks guys. These two solutions are amazing, just what I need. Very good of you to respond so quickly, thanks again.
regards, Tim.

2 Likes

@timhopson,

I had to make small fix to upper code because of the way ATR is calculated. Since I use fixup = 0 to recognize symbols having no data at a bar (returning null then) I had to set HLC to zero before ATR assignment in new code. Otherwise if not doing so on "null days" sumarray variable would return very large number after null day(s).

So here is a fix (and including a basic exploration output).
You can see below in the picture that I removed price data of a few symbols at the last two bars of data. And it is recognized by the code and only array elements existing are taken into account of calculation and ATR not returning large number.

408

  1. Set chart symbol to index your symbols belong too
  2. Assign watchlist number your symbols belong to to 'listnum' variable of line 27
  3. Make sure index symbol's price data and WL data are up to date
  4. Open Parameter window and click "CLICK HERE" or apply analysis 'Explore'
/// Set chart symbol to index your symbols belong too
/// Assign watchlist number your symbols belong to to 'listnum' variable of line 27
/// Make sure index symbol's price data and WL data are up to date
/// Open Parameter window and click "CLICK HERE" or apply analysis 'Explore'
function Average_ATR_Category ( ATRperiod, category, listnum, fixup ) {
  /// @link https://forum.amibroker.com/t/average-atr-values-for-stocks-in-an-index/11006/3
  /// retrieve comma-separated list of symbols in watch list
  list = CategoryGetSymbols( category, listnum );
  sumarray = count = 0; // initialize
  for ( i = 0; ( sym = StrExtract( list, i ) ) != ""; i++ ) {
     // see fixup options 0 to 2 in manual of Foreign() 
     /// @link https://www.amibroker.com/guide/afl/foreign.html 
     SetForeign( sym, fixup );   
        notnull = NOT IsNull(C);
        H = Nz(H);// used by ATR(), and if fixup == 0 then convert Null to zero
        L = Nz(L);// used by ATR(), and if fixup == 0 then convert Null to zero
        C = Nz(C);// used by ATR(), and if fixup == 0 then convert Null to zero
        // sum up only if bar data exists
        sumarray += IIf(notnull, ATR(ATRperiod)/(C+1e-9), 0 );
        count += notnull;
     RestorePriceArrays();// restores to orignal symbol as well as restores HLC
  } 
  VarSet( "symcount", count);   
  return sumarray / count; // multi symbol average
}

listnum = 0; // set watchlist number
ATRperiod = 30;

/// @link https://www.amibroker.com/guide/afl/setbarsrequired.html
/// if you want to disable QuickAFL then uncomment
//SetBarsRequired(sbrall);

// some time consuming calculation
explore = Status( "action" ) == actionExplore;
trigger = ParamTrigger( "Create Average", "CLICK HERE" ) OR explore;
if ( trigger ) {   
   x = Average_ATR_Category( ATRperiod, categoryWatchlist, listnum, fixup = 0 );
   // store time consuming work to static variables
   StaticVarSet( "AvgATR", x, persistentstorage = False );
   StaticVarSet( "SymCount", VarGet( "symcount" ), persistentstorage );
}

x = StaticVarGet( "AvgATR" );

if ( LastValue(x) == 0 && Status( "actionex" ) != actionExEditVerifyFormula && ! explore )
  Error( "Open Parameter window (CTRL+R) and click 'Click HERE'!" );

Plot( x, "AvgATR", colorRed, styleLine );

Filter = 1;
AddTextColumn(CategoryGetName(categoryWatchlist,listnum), "WatchList Name", 1 );
AddColumn( StaticVarGet( "SymCount" ), "symcount", 1 );
AddColumn( x, "Avg ATR%", 1.6 );

7 Likes

Thanks again for taking the trouble with this. Much appreciated.