Create Custom Index (from specified tickers)

I am trying to create a custom index (weighted by trading value) from says 10 tickers which are stored in a watchlist. The code below is just the example of calculation total summation of trading value of those tickers in a watchlist.

The range of index I want to create is 5 years, however some tickers has just started trading 1 years ago, hence the code below can generate only 1 year data. I want to ignore the ticker that doesn't have data ( equal to zero) and produce the summation of trading value for 5 years. Can you please advise if there is any other way ?

count = 0;
s=0;

procedure CreateIndexesValue( ) 
{
  global List;
  local Symbol,n;
  wlnum = 0; 
  x=0;
  count =0;
  List = CategoryGetSymbols( categoryWatchlist, wlnum ) ;
     
  for( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++ )
    {
		count = count+1;
        SetForeign( Symbol ); 
        x= C*V;
        s=s+x;
        RestorePriceArrays( True );
    }
}

CreateIndexesValue();
resultS = s;

Filter = resultS;
AddColumn(resultS,"Value",1.1);

@tanaponpukwattana there are probably several ways, like try only counting a stock if it's Close (or perhaps Volume) is greater than zero and similarly only do your calculation on stocks that have a Close great than zero.

Another possibility is using StaticVarAdd. I've coded up a quick example that seems to work for me.

// Using StaticVarAdd and run EXPLORE

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

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

    for( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++ )
    {

        SetForeign( symbol );

        // my data has too many digits to be significant so I divided by 100k
        StaticVarAdd( "~CustomCalculation", C * V / 100000 );
        StaticVarAdd( "~SymbolCount", C != 0 ); // don't count a stock that isn't trading
        // StaticVarAdd converts Nulls to zero's, so I'm not sure that there isn't a better way to code that C!=0

        RestorePriceArrays();
    }
}

svCustomCalculation = StaticVarGet( "~CustomCalculation" );
svSymbolCount = StaticVarGet( "~SymbolCount" );
CustomIndex = svCustomCalculation / svSymbolCount; // take the average to create your custom index

///////////////
// Explore
///////////////
Filter = 1;
AddColumn( svSymbolCount, "Number of Stocks", 1.0 );
AddColumn( svCustomCalculation, "Total Calculation", 1.2 );
AddColumn( CustomIndex, "Custom Index", 1.2 );

///////////////
// Chart
///////////////
Plot( CustomIndex, "Custom Index", colorRed, styleThick );

I must admit the idea for your index using Close*Volume is a bit troublesome. In my database the Volume is usually fairly large for securities I am interested in trading. So our calculation runs into trouble getting past the 7 significant digit problem.

3 Likes

Need some help in bit of variation form the subject. I wish to create a 'Equal Weighted Index' which means if watclist has 50 stocks each stock will be assigned a 2% weight while if it has 500 stocks it has 0.2% weight.

Reproducing the logic : Equal Weighted Index
An equal-weighted index is one in which all stocks included in the index have the same
weightage. The number of shares of each stock is adjusted in such a way that the weight
of each stock in the index is the same. Subsequently, if there is any change in the market
price of each stock, the weight of each stock will change. In order to maintain the same
equal weights as earlier, the fund manager needs to sell those stocks that have
increased in price and buy the stocks that have fallen in price.

While we have 'svSymbolCount' so the weight maybe defined. How do we define base date for the index and assign a value to say 100 and then dynamically change the number of shares (here V is used in above afl) for each scrip in the watchlist.

Subsequently the 'Custom Index' gets created based on watchlist selected and plotted.

@pushkan similar question has been answered before. Also the above code that I wrote was using StaticVarAdd in a way that is computationally inefficient. So search the forum for better methodology.

Also recent versions of Ami have built in "Easy Sequencing" that allows for example single click two-step analysis runs creating composites or static variables in first step and using them in second step.

1 Like

You should use non loop code

1 Like

Correct code for version 6.40. Press "RUN SEQUENCE" to use it.

// the statement below defines sequence of actions 
#pragma sequence(scan,explore) 

Version( 6.40 ); // requires version 6.40.4


if( Status("action") == actionScan ) 
{ 
   AddToComposite( C * V / 100000 , "~MyIndex", "X" ); 
   AddToComposite( 1, "~MyIndex", "V");
   _exit(); // quick exit in scan mode 
} 

CustomCalculation = Foreign( "~MyIndex", "C" );
SymbolCount = Foreign( "~MyIndex", "V" );
CustomIndex = CustomCalculation / SymbolCount; // take the average to create your custom index

///////////////
// Explore
///////////////
Filter = 1;
AddColumn( SymbolCount, "Number of Stocks", 1.0 );
AddColumn( CustomCalculation, "Total Calculation", 1.2 );
AddColumn( CustomIndex, "Custom Index", 1.2 );

Note that this function uses AddToComposite, not static variables, as visible composites in forms of special symbols that are present in the "Symbols" list (here composite is present in form of ~MyIndex ticker) are easier to understand, display and handle for beginners than somewhat "hidden" static variables, that you don't easily see.

5 Likes