Calculating Standard Deviation across a Watchlist and Related afl Challenge

I am attempting to code a ranking/rotation strategy that uses a form of probability momentum. The concept is:

  1. CAR/SD = % chg (lookback) / Relative standard deviation (close, lookback)
  2. Normdist (CAR/SD)
  3. Normdist ((ticker CAR - Average Sector CAR)/Standard Deviation (Average CAR of sector))
  4. Rank Score averages 3+4

My apologies for again asking the incredibly generous folks of this forum for their guidance. In spite of rereading documentation+ other forum posts, I am stuck in two areas.
a) Using the "if ( Status( "stocknum" ) == 0 )" and inner watchlist loop
"for( i = 0; ( symbol= StrExtract( symlist, i ) ) != ""; i++ ) " , some steps require creating averages & totals, then working off those intermediate summation measures within the next steps. I am struggling to understand best practice in storing/retrieving these measurements – where in the loop structure, as the “final” results only occur after the last symbol is complete, but those measures are needed in the subsequent calculation steps for each symbol. In the pasted code I calculate the # of active tickers per bar (StaticVarAdd( "~Symctact", Symctact ), and total ROC (StaticVarAdd( "~Roc1fil", Roc1fil )), and use that to calc average ROC across all symbols that bar. I use the StaticVarGet within the loop as this seems to grab the “final totals” results accurate, but not sure why/how. Problem: I attempt to staticvarset & StaticVarGet the core variable “~PctAvgROCx” (where x is different attempt types), however values are not getting extracted. Viewing the trace, I see the values are getting set here, so I need to change something.
b) The formula I am working towards calls for calculating Standard Deviation across the different tickers, bar by bar. I can’t figure out how to load in a cross sectional array of values to feed into Standard Deviation. I suspect a custom loop is needed – any examples would be appreciated.

Thank again.
Scott

_SECTION_BEGIN("Rank Loop"); 
	symlist=WatchLSz = NoS  = numberOfSymbols = Symctact= 0; 

// ---------------------------------------------------------------------------------------------- 
	wlist = GetOption("FilterIncludeWatchlist"); 
			symlist = CategoryGetSymbols( categoryWatchlist, wlist ) ; 
			numberOfSymbols = StrCount( symlist, "," ) + 1;
			WatchLSz = NoS  = numberOfSymbols; 
 
// "stocknum" - gives you the ordinal number of currently analyzed symbol - hence runs on once at start of backtest only 
if ( Status( "stocknum" ) == 0 )    
	{  	
	
		  ProbLB=CondOptimize("Prob Lookback",60,5,80,5);

		
		// fill input static arrays Every symbol in watchlist --------------------------------
	for( i = 0; ( symbol= StrExtract( symlist, i ) ) != ""; i++ ) // Here i=1 symbol - looping through every symbol in watchlist of symbols
		{ 
		SetForeign(symbol); 
		
		// ---------------------
		StaticVarAdd( "~SymbolCount", 1 );  // Should be same as WatchLSz  = "~SymbolCount" is new static variable, Counting # of active symbols on 1 bar 
		 
   		 Symctact = iif(V>0,1,0);  // Testing for activity V = volume C= CLOSE = closing price
		 StaticVarAdd( "~Symctact", Symctact );  // # active ticker on that bar = works
		 
		 ROClb = ROC(C,ProbLB);  // Individual CAR - roc = rate of change = 20 day % chg
		 
		 StDevval = (stdev( close, ProbLB )/ma(close,ProbLB))*100;  // Individual Relative SD %		 
		 
		 CARSD = ROClb/StDevval;// Individual CAR/SD
		
		 NDCARSD = NormDist(CARSD, 0, 1, True );  // IND Norm Dist of CAR/SD = indicatical to Excel  = time array		 
		 	 
		 Roc1fil = iif(V>0,ROClb,0); // filtered individual CAR
		 StaticVarAdd( "~Roc1fil", Roc1fil );  // store Total ROC of tickers in watchlist
		 
		 SDfil = iif(V>0,StDevval,0); // filtered ind SD
		 StaticVarAdd( "~SDfil", SDfil );  // store Total SD 
		 	 
		 ActiveTicka = StaticVarGet ( "~Symctact" );  // get # active tickers
		 ROC1TOTa = StaticVarGet ( "~Roc1fil" );  // get Total filtered ROC
			if( DBVOn ) _TRACE(" ROC1TOTa + sym " + ROC1TOTa + " " +  symbol);
		 PctAvgROCnoget = (Roc1fil/Symctact) ; 
		 if( DBVOn ) _TRACE(" PctAvgROCnoget + sym " + PctAvgROCnoget + " " +  symbol);
		 PctAvgROC = (ROC1TOTa/ActiveTicka) ;  // % AVg ROC for the watchlist that day  - This seems to work, as CARDIFF seems right - but can't get this to output
		 if( DBVOn ) _TRACE(" PctAvgROC + sym " + PctAvgROC + " " +  symbol);
		 
		staticvarset("~PctAvgROC3 "  ,PctAvgROC);
		
		 CARDiff = ROClb - PctAvgROC; // Ind Car diff vs the avg ROC
	 
		 SDAVGROC = stdev( (PctAvgROC) , ProbLB); // Std Dev of Avg ROC time array but not between tickers/symbols	 		 
		 
		 NDProbM= NormDist( (CARDiff/SDAVGROC) , 0, 1, True );  // IND Norm Dist			
		 
		 Ratingf =  round((NDProbM + NDCARSD)/2 )*10;
			
	
		/*  Objective:
			SDWLROC = stdev(ROClb OR Roc1fil, across/between all tickers in the watchlist loop);
			How to read in each ticker value in current bar as an array? 
			Is matrix processing necessary here?
			Matrix = mult dimensional			*/
							
		
		RestorePriceArrays(); 
	
		 staticvarset("~PctAvgROC " ,PctAvgROC);  // all symbols store % AVg ROC 
		staticvarset("~PctAvgROCg "  +  symbol ,PctAvgROC);  // all symbols store % AVg ROC

			
			staticvarset("~ROClb" +  symbol,ROClb);  // Individual CAR
			staticvarset("~StDevval"  +  symbol ,StDevval);  // Individual SD
			staticvarset("~CARSD"  +  symbol,CARSD);  // Individual CAR/SD
			staticvarset("~NDCARSD" +  symbol,NDCARSD);  // IND Norm Dist of CAR/SD 
	
			staticvarset("~CARDiff" +  symbol,CARDiff);  // store CAR Diff vs avg
			staticvarset("~SDAVGROC" +  symbol,SDAVGROC);  // Std Dev of Avg ROC
			staticvarset("~NDProbM" +  symbol,NDProbM);  // store Norm Dist of Car 
			staticvarset("~RatingP"  +  symbol,RatingP);  //
			staticvarset("~Ratingf"  +  symbol,Ratingf);  //
		
			StaticVarSet(  "Ratingf"  +  symbol, Ratingf);    
			
			
	} 
			StaticVarGenerateRanks( "rank","Ratingf", 0, 1224 );    
		 
	}  
_SECTION_END(); 
// ============================== end of Rank Loop ===================================== 
 
_SECTION_BEGIN("Extract & Manage Ranks"); 
	symbol = Name();  
	
	 SymbolCountg = StaticVarGet ( "~SymbolCount" );
	 Symctactg = StaticVarGet ( "~Symctact" );
	 ROCLBg = StaticVarGet ( "~ROClb" +  symbol );
	 StDevvalg = StaticVarGet ( "~StDevval" +  symbol );
	 CARSDg = StaticVarGet ( "~CARSD" +  symbol );
	 NDCARSDg = StaticVarGet ( "~NDCARSD" +  symbol );  
	 ROC1TOTa2 = StaticVarGet ( "~Roc1fil" );
	 PctAvgROC2 = StaticVarGet ( "~PctAvgROC" );  
		 PctAvgROCg = StaticVarGet ( "~PctAvgROCg" +  symbol  ); 	
		PctAvgROC3 = StaticVarGet ( "~PctAvgROC3"  );
	  NDProbMg = StaticVarGet ( "~NDProbM" +  symbol );
	  CARDiffg = StaticVarGet ( "~CARDiff" +  symbol );
	  SDAVGROCg = StaticVarGet ( "~SDAVGROC"  +  symbol);
	  Ratingpg = StaticVarGet ( "~Ratingp"  +  symbol);
	  Ratingfg = StaticVarGet ( "~Ratingf" +  symbol );
	  	 
	Var1 = StaticVarGet ( "Ratingf"+  symbol ); 

	// extract rank value 
	rank1o = StaticVarGet ( "rankRatingf"+  symbol ); 

	rank1 = (WatchLSz +1) - rank1o;  
	
_SECTION_END(); 

@swalk10 I doubt that I will come up with answers but I was making an attempt to look over your code. The sample you provided had several syntax errors so I couldn't really assess.

So perhaps these small suggestions will help someone else have a good look,

No definition of

if( DBVOn )

So at the top I added,

DBVOn = ParamToggle( "Trace", "No|Yes", 0 );

You have a line that makes no sense (to me at least)

 ProbLB=CondOptimize("Prob Lookback",60,5,80,5);

Perhaps a remnant of your misspent youth using different software? Were you intending something like this?

ProbLB = Optimize( "Prob Lookback", 60, 5, 80, 5 );

And after those I still get this one, which if cleaned up might enable a user on the forum to really dig into this (someone better than me)
image

Lastly, I don't think I understood point (b), were you looking to calculate the standard deviation of each symbol in your watch list or deviation between tickers?

Good luck, it looks interesting. Is it related to the "Livermore Index" ?

Thanks, sorry - I will repost to make it easier - forgot to remove a couple of functions calls.

DBVon allows turning on/off trace all at one.

DBVOn = ParamToggle("DebugView","OFF|ON", 0);

CondOptimize turns on/off via settings individual optimizations - very handy - use in replace of optimization

function CondOptimize( Var, def, start, end, inc )
 { 
	Option = ParamToggle( "Optimize - " + Var, "No,Yes", 0 );
 	// If option, optimize the designated variable 
	// Else return the default 
	if ( Option ) res = Optimize( Var, def, start, end,inc ); 
	else res = Param( Var, def, start, end,inc );
	 return res;
}

Yes - standard deviation between the symbols - rather than "normal" deviation over time array.

Not directly related to Livermore, however, some of the idea did come from the same source :).

Cleaner code

_SECTION_BEGIN("Rank Loop"); 
	symlist=WatchLSz = NoS  = numberOfSymbols = Symctact= 0; 

// ---------------------------------------------------------------------------------------------- 
	wlist = GetOption("FilterIncludeWatchlist"); 
			symlist = CategoryGetSymbols( categoryWatchlist, wlist ) ; 
			numberOfSymbols = StrCount( symlist, "," ) + 1;
			WatchLSz = NoS  = numberOfSymbols; 
 
// "stocknum" - gives you the ordinal number of currently analyzed symbol - hence runs on once at start of backtest only 
if ( Status( "stocknum" ) == 0 )    
	{  	
	
		  ProbLB=param("Prob Lookback",60,5,80,5);

		
		// fill input static arrays Every symbol in watchlist --------------------------------
	for( i = 0; ( symbol= StrExtract( symlist, i ) ) != ""; i++ ) // Here i=1 symbol - looping through every symbol in watchlist of symbols
		{ 
		SetForeign(symbol); 
		
		// ---------------------
		StaticVarAdd( "~SymbolCount", 1 );  // Should be same as WatchLSz  = "~SymbolCount" is new static variable, Counting # of active symbols on 1 bar 
		 
   		 Symctact = iif(V>0,1,0);  // Testing for activity V = volume C= CLOSE = closing price
		 StaticVarAdd( "~Symctact", Symctact );  // # active ticker on that bar = works
		 
		 ROClb = ROC(C,ProbLB);  // Individual CAR - roc = rate of change = 20 day % chg
		 
		 StDevval = (stdev( close, ProbLB )/ma(close,ProbLB))*100;  // Individual Relative SD %		 
		 
		 CARSD = ROClb/StDevval;// Individual CAR/SD
		
		 NDCARSD = NormDist(CARSD, 0, 1, True );  // IND Norm Dist of CAR/SD = indicatical to Excel  = time array		 
		 	 
		 Roc1fil = iif(V>0,ROClb,0); // filtered individual CAR
		 StaticVarAdd( "~Roc1fil", Roc1fil );  // store Total ROC of tickers in watchlist
		 
		 SDfil = iif(V>0,StDevval,0); // filtered ind SD
		 StaticVarAdd( "~SDfil", SDfil );  // store Total SD 
		 	 
		 ActiveTicka = StaticVarGet ( "~Symctact" );  // get # active tickers
		 ROC1TOTa = StaticVarGet ( "~Roc1fil" );  // get Total filtered ROC
			 _TRACE(" ROC1TOTa + sym " + ROC1TOTa + " " +  symbol);
		 PctAvgROCnoget = (Roc1fil/Symctact) ; 
			_TRACE(" PctAvgROCnoget + sym " + PctAvgROCnoget + " " +  symbol);
		 PctAvgROC = (ROC1TOTa/ActiveTicka) ;  // % AVg ROC for the watchlist that day  - This seems to work, as CARDIFF seems right - but can't get this to output
			_TRACE(" PctAvgROC + sym " + PctAvgROC + " " +  symbol);
		 
		staticvarset("~PctAvgROC3 "  ,PctAvgROC);
		
		 CARDiff = ROClb - PctAvgROC; // Ind Car diff vs the avg ROC
	 
		 SDAVGROC = stdev( (PctAvgROC) , ProbLB); // Std Dev of Avg ROC time array but not between tickers/symbols	 		 
		 
		 NDProbM= NormDist( (CARDiff/SDAVGROC) , 0, 1, True );  // IND Norm Dist			
		 
		 Ratingf =  round((NDProbM + NDCARSD)/2 )*10;
			
	
		/*  Objective:
			SDWLROC = stdev(ROClb OR Roc1fil, across/between all tickers in the watchlist loop);
			How to read in each ticker value in current bar as an array? 
			Is matrix processing necessary here?
			Matrix = mult dimensional			*/
							
		
		RestorePriceArrays(); 
	
		 staticvarset("~PctAvgROC " ,PctAvgROC);  // all symbols store % AVg ROC 
		staticvarset("~PctAvgROCg "  +  symbol ,PctAvgROC);  // all symbols store % AVg ROC

			
			staticvarset("~ROClb" +  symbol,ROClb);  // Individual CAR
			staticvarset("~StDevval"  +  symbol ,StDevval);  // Individual SD
			staticvarset("~CARSD"  +  symbol,CARSD);  // Individual CAR/SD
			staticvarset("~NDCARSD" +  symbol,NDCARSD);  // IND Norm Dist of CAR/SD 
	
			staticvarset("~CARDiff" +  symbol,CARDiff);  // store CAR Diff vs avg
			staticvarset("~SDAVGROC" +  symbol,SDAVGROC);  // Std Dev of Avg ROC
			staticvarset("~NDProbM" +  symbol,NDProbM);  // store Norm Dist of Car 
			
			staticvarset("~Ratingf"  +  symbol,Ratingf);  //
		
			StaticVarSet(  "Ratingf"  +  symbol, Ratingf);    
			
			
	} 
			StaticVarGenerateRanks( "rank","Ratingf", 0, 1224 );    
		 
	}  
_SECTION_END(); 
// ============================== end of Rank Loop ===================================== 
 
_SECTION_BEGIN("Extract & Manage Ranks"); 
	symbol = Name();  
	
	 SymbolCountg = StaticVarGet ( "~SymbolCount" );
	 Symctactg = StaticVarGet ( "~Symctact" );
	 ROCLBg = StaticVarGet ( "~ROClb" +  symbol );
	 StDevvalg = StaticVarGet ( "~StDevval" +  symbol );
	 CARSDg = StaticVarGet ( "~CARSD" +  symbol );
	 NDCARSDg = StaticVarGet ( "~NDCARSD" +  symbol );  
	 ROC1TOTa2 = StaticVarGet ( "~Roc1fil" );
	 PctAvgROC2 = StaticVarGet ( "~PctAvgROC" );  
		 PctAvgROCg = StaticVarGet ( "~PctAvgROCg" +  symbol  ); 	
		PctAvgROC3 = StaticVarGet ( "~PctAvgROC3"  );
	  NDProbMg = StaticVarGet ( "~NDProbM" +  symbol );
	  CARDiffg = StaticVarGet ( "~CARDiff" +  symbol );
	  SDAVGROCg = StaticVarGet ( "~SDAVGROC"  +  symbol);
	  Ratingpg = StaticVarGet ( "~Ratingp"  +  symbol);
	  Ratingfg = StaticVarGet ( "~Ratingf" +  symbol );
	  	 
	Var1 = StaticVarGet ( "Ratingf"+  symbol ); 

	// extract rank value 
	rank1o = StaticVarGet ( "rankRatingf"+  symbol ); 

	rank1 = (WatchLSz +1) - rank1o;  
	
_SECTION_END(); 

If you calculate Std Deviation yourself, you don't need to put all the individual values (one from each symbol) into an array or matrix that can be fed to AB's built-in StDev channel. Instead, you can accumulate the sum of the values, the sum of the squared values, and the count, and then use a formula like the one shown here: http://mathforum.org/library/drmath/view/61381.html

When you're done, you should have your own standard deviation array that has a different standard deviation value for each bar. Except for the loop to process each symbol, you should be able to do all of this with array logic and not use any other loops.

2 Likes

@mradtke Thanks for the suggestions. While I am comfortable with the math, not so much how to handle the AmiBroker loop when it gets outside of a time dimensional loop, but rather a cross sectional between tickers loop. If you/anyone have any example code I could modify in this case, that is appreciated.

I don't have a functioning example to provide you, but I think that something like the untested AFL below should work. Let's assume that for each bar you want to calculate the standard deviation of the 1-day rate of change across all symbols in your watch list. For simplicity, I'm not going to worry too much about holes in your data, although the solution below gives you a starting point to work from.

// Each element of these arrays will contain the accumulated sum
// across all symbols for that bar.
sumROC = 0;
sumROCSquared = 0;
cntObservations = 0;

for( i = 0; ( symbol= StrExtract( symlist, i ) ) != ""; i++ )
{
	SetForeign(symbol,0);						// Don't fill holes
		symROC = ROC(C,1);
		sumROC += Nz(symROC);
		sumROCSquared += Nz((symROC ^ 2));
		cntObservations += !IsNull(symROC );			// Not certain this will work, so might need different logic
	RestorePriceArrays();
}

// Sample Std Deviation
rocStdDev = sqrt((sumROCSquared - (sumROC ^ 2) / cntObservations) / (cntObservations-1));
4 Likes

@mradtke Thank you!
I need to play with it to understand how it is handling across the tickers later today, and will update back either way.
Kind Regards,
Scott

@portfoliobuilder @mradtke
Thank you again for your help. I am attaching a working solution to the objectives I was working against. I ended up using 3 passes of the watchlist; a more effecient coding approach is likely possible, but this runs quickly and manageably.

I would like to learn a method to allow the MaxOpenPositions to work with an array, so that it can be a portion of the # of active tickers, which changes over time. As this is a different question, I will open a new thread.
Scott

// ----------------------------------------------------------------------------------------------
	DBVOn = ParamToggle("DebugView","OFF|ON", 0);
	if( DBVOn ) _TRACE("First line after clear");
	
_SECTION_BEGIN("Rank Loop"); 
	a=b=d=buyr1=sellr1=ma20=rank=roc200i=rank2=rankcomb=Perf1=Sharp1=Sharp2=symlist=WatchLSz = NoS  = numberOfSymbols = Symctact=ROC1= 0; 

// ---------------------------------------------------------------------------------------------- 

	// Proper lOCATION uncertain
	wlist = GetOption("FilterIncludeWatchlist"); 

	
if ( Status( "stocknum" ) == 0 )    
	{  	
	if (2 == 2 )  // Applies only to filter - needs open paren?
		{ 
			symlist = CategoryGetSymbols( categoryWatchlist, wlist ) ; 
			numberOfSymbols = StrCount( symlist, "," ) + 1;
			WatchLSz = NoS  = numberOfSymbols; 		 				 
			StaticVarRemove("*");  // delete ALL static variables 
		} 
			{		

			}
_SECTION_BEGIN("Indicator NEW Options");		
		  ProbLB=param("Prob Lookback",60,5,80,5);
_SECTION_END();
		
// --------------------------------watchlist Loop Pass 1 -------------------------------------------------- 		
	for( i = 0; ( symbol= StrExtract( symlist, i ) ) != ""; i++ ) // Here i=1 symbol - looping through every symbol in watchlist of symbols
		{ 
		SetForeign(symbol); 
		
		// -------- Counting # of active symbols on 1 bar -------------
		StaticVarAdd( "~SymbolCount", 1 );  // Should be same as WatchLSz  = "~SymbolCount" is new static variable 
		 
   		 Symctact = iif(V>0,1,0);  // Testing for activity V = volume C= CLOSE = closing price
		 StaticVarAdd( "~Symctact", Symctact );  // # active ticker on that bar = works
		 
		 ROClb = ROC(C,ProbLB);  // Individual CAR - roc = rate of change = 20 day % chg
		 ROC1 = ROC(C,1);
		 //StDevval = (stdev( close, ProbLB )/ma(close,ProbLB))*100;  // Individual Relative SD % - earlier version.
		StDevval = stdev( (C/REF(C,-1)), ProbLB) *100;  // Individual Relative SD %		 
		 
		CARSD = (ROClb/StDevval)/100;// Individual CAR/SD
		
		 NDCARSD = NormDist(CARSD, 0, 1, True );  // IND Norm Dist of CAR/SD = identical to Excel  = time array		 
		 	 
		 Roc1fil = iif(V>0 AND roclb>-99 ,ROClb,0); // filtered individual CAR
		 StaticVarAdd( "~Roc1fil", Roc1fil );  // store Total ROC of tickers in watchlist
		 	
		 //PctAvgROCnoget = (Roc1fil/Symctact) ; 
		 //if( DBVOn ) _TRACE(" PctAvgROCnoget + sym " + PctAvgROCnoget + " " +  symbol);
		 
		RestorePriceArrays(); 
		 		 
		staticvarset("~ROClb" +  symbol,ROClb);  // Individual CAR
		staticvarset("~StDevval"  +  symbol ,StDevval);  // Individual SD
		staticvarset("~CARSD"  +  symbol,CARSD);  // Individual CAR/SD
		staticvarset("~NDCARSD" +  symbol,NDCARSD);  // IND Norm Dist of CAR/SD 
		
		}
		// In "Run Once" but outside WL Loop, so working with summary variables from earlier step
			ActiveTicka = StaticVarGet ( "~Symctact" );  // get # active tickers
			 SmpleadjCt = iif(ActiveTicka>1,ActiveTicka-1,ActiveTicka); // sample size adj (#ct-1)
				if( DBVOn ) _TRACE("1 SmpleadjCt " + SmpleadjCt);
				staticvarset("~SmpleadjCt" ,SmpleadjCt);  //  
			
			ROC1TOTa = StaticVarGet ( "~Roc1fil" );  // get Total filtered ROC
			if( DBVOn ) _TRACE(" ActiveTicka + sym " + ActiveTicka + " " +  symbol);
			if( DBVOn ) _TRACE(" ROC1TOTa + sym " + ROC1TOTa + " " +  symbol);
			
			PctAvgROCpre = ROC1TOTa/ActiveTicka;
				staticvarset("~PctAvgROCpre" ,PctAvgROCpre);  // selective max negative value?
				
			PctAvgROC = iif(ActiveTicka>0,(ROC1TOTa/ActiveTicka),0) ;  // % AVg ROC for the watchlist that day  - This seems to work, as CARDIFF seems right - but can't get this to output
				if( DBVOn ) _TRACE("1 PctAvgROC " + PctAvgROC );
			
			/* PctAvgROCgs  dont attach symbol! 
				// symbols not assigned out of WL loop but before normal loop*/
				
			staticvarset("~PctAvgROCgns" ,PctAvgROC);  // all symbols store % AVg ROC	
				if( DBVOn ) _TRACE("2b PctAvgROCgns " + StaticVarget("~PctAvgROCgns") );
				
// --------------------------------WL Loop Pass 2 -------------------------------------------------- 
	for( i = 0; ( symbol= StrExtract( symlist, i ) ) != ""; i++ ) // Here i=1 symbol - looping through every symbol in watchlist of symbols
		{ 
		SetForeign(symbol); 		
			
		 ROClb2 = StaticVarGet ("~ROClb" +  symbol);
			if( DBVOn ) _TRACE("r2 ROClb2 +sym " + ROClb2 + " " + symbol);
			
		 PctAvgROCp2 = StaticVarGet ("~PctAvgROCgns");
			if( DBVOn ) _TRACE("r2 PctAvgROCp2 " + PctAvgROCp2 );
			
		 CARDiff = ROClb2 - PctAvgROCp2; // Ind Car diff vs the avg ROC
			if( DBVOn ) _TRACE("r2 CARDiff +sym " + CARDiff  + " " + symbol);
		 CARDiffsq = (CARDiff*CARDiff); 	// sq the differences
			if( DBVOn ) _TRACE("r2 CARDiffsq +sym " + CARDiffsq + " " + symbol);
			
		// sum((Ind Car - MeanCAR)^2 )
		 StaticVarAdd( "~CARDiffsqad", CARDiffsq );  // add up squared differences across tickers 
			 if( DBVOn ) _TRACE("r2 CARDiffsqad " + StaticVarget("~CARDiffsqad")) ;  // sqrt( ARRAY ) 			  
		// cant do sqrt() - need to only grab final sym step ;	
				
		RestorePriceArrays();
			
		// Set variables from prior step
			staticvarset("~CARDiff" + symbol, CARDiff);  // Individual CAR vs avgRoc
				if( DBVOn ) _TRACE("r2  CARDiff +sym " + CARDiff  + " " + symbol);				
		}
						
		// In "Run Once" but outside WL Loop, so do calcs/work with summary variables from earlier step
			CARDiffsqad	= StaticVarget("~CARDiffsqad");
		    if( DBVOn ) _TRACE("r2 CARDiffsqad " + StaticVarget("~CARDiffsqad"));  // traces just once here
			
// --------------------------------WL Loop Pass 3 -------------------------------------------------- 
	for( i = 0; ( symbol= StrExtract( symlist, i ) ) != ""; i++ ) 				
		{ 
		SetForeign(symbol); 
		
		SmpleadjCt2 = staticvarget("~SmpleadjCt");  //  sample size adj (#ct-1)
			if( DBVOn ) _TRACE("r3 SmpleadjCt2 " + SmpleadjCt2);
		// staticvarset("~CARDiff" + symbol, CARDiff);  // Individual CAR vs avgRoc	
		
		CARDiff2 = StaticVarget("~CARDiff"+ symbol);  // basic car - avg car
			if( DBVOn ) _TRACE("r3 CARDiff2 sym " + CARDiff2 + symbol );  // nominator part = (CAR-AVERAGE WATCHL(CAR))
		
		 SDavgWL = sqrt(CARDiffsqad/SmpleadjCt2) ;  // sqrt (( sum((Ind Car - MeanCAR)^2 ) )/(#ct-1) ) 	= STDEVA(AVERAGE WATCHL car)
		   if( DBVOn ) _TRACE("r3 SDavgWL " + SDavgWL);
		   
		 NDstep4 = staticvarget("~NDCARSD" +  symbol);
			if( DBVOn ) _TRACE("r3 NDstep4 sym " + NDstep4 + symbol);
			
		 NDstep5 = NormDist( (CARDiff2 / SDavgWL), 0, 1, True ); 
		    if( DBVOn ) _TRACE("r3 NDstep5 sym " + NDstep5 + symbol);		 		
		 
		 Score =  round( ((NDstep4+NDstep5)/2)*10 );  
			if( DBVOn ) _TRACE("r3 Score sym " + Score + symbol);
			// 
		RestorePriceArrays();
			// Set variables from prior step
			staticvarset("Score2" + symbol, Score);  //
			  
		}	
			StaticVarGenerateRanks( "rank","Score2", 0, 1224 );
	}  
_SECTION_END(); 
// ============================== end of Rank Loop ===================================== 
 
_SECTION_BEGIN("Extract & Manage Ranks"); 
	symbol = Name();  
	
	 SymbolCountg = StaticVarGet ( "~SymbolCount" );
	 Symctactg = StaticVarGet ( "~Symctact" );
	 
	 ROCLBg = StaticVarGet ( "~ROClb" +  symbol );
	 StDevvalg = StaticVarGet ( "~StDevval" +  symbol );
	 CARSDg = StaticVarGet ( "~CARSD" +  symbol );
	 NDCARSDg = StaticVarGet ( "~NDCARSD" +  symbol );  
	
	ROC1TOTa2 = StaticVarGet ( "~Roc1fil" );	 	 
	PctAvgROCg = StaticVarGet( "~PctAvgROCgns" ); 
	
	if( DBVOn ) _TRACE("3 PctAvgROCgns " + StaticVarget("PctAvgROCgns") );				
	if( DBVOn ) _TRACE("4 PctAvgROCg " + PctAvgROCg);		
	
	  NDProbMg = StaticVarGet ( "~NDProbM" +  symbol );
	  CARDiffg = StaticVarGet ( "~CARDiff" +  symbol );
	  CARDiffsqad = StaticVarGet ( "~CARDiffsqad" );
	  
	  SDAVGROCg = StaticVarGet ( "~SDAVGROC"  +  symbol);
	  Ratingpg = StaticVarGet ( "Score2"  +  symbol);

@swalk10 Thanks for sharing Scott, it looks like a lot of thought went into it. I was curious if you were aware that a couple of variables may not have been fully calculated (or perhaps omitted which is OK as long as you are aware). I attempted to "Explore" some of the calculations and found perhaps a couple of missing group averages,
image

@portfoliobuilder

Mine does populate those columns, but it takes a 15 month lag - no idea why, as look back is more like 3 months. I have a long list of things to look at, and the lag was not in the short list right now. Check if yours is populating later - I can send you a screenshot on my output.

Here is some of the column output, as it is a bit tricky grabbing the "final" variable steps.

Filter =  1;	 	
		AddColumn ( C , "close " ); 
		AddColumn ( roc(c,1) , "ROC1" );   
	 
	  Addcolumn (Symctactg, "Symctactg Active Tickers" );
	   
	  Addcolumn(StaticVarGet ("~SmpleadjCt"), "sample adj ct"); 
	  
	 Addcolumn(StaticVarGet ("~PctAvgROCpre"), "PctAvgROCpre"); 												
	  Addcolumn (ROCLBg, "ROClb % Chg Lookback" );
	  Addcolumn (StDevvalg, "StDevval  % StDev ROC" );
	  Addcolumn (CARSDg, "CARSD  %Chg/R Std Dev" );
	  Addcolumn (NDCARSDg, "NDCARSD  Norm(%Chg/R Std Dev)" ); 
	 
	  Addcolumn (PctAvgROCg, "PctAvgROCg" );  // source ~PctAvgROCgns + prior PctAvgROC; some issues on null	  
	  	 	  
	  Addcolumn (CARDiffg, "CAR Dif v Avg" );  	 		  		  
	   Addcolumn (Ratingpg, "Ratingp" );  //aka score2 
1 Like