Static var to calc an Watchlist AVG

Thinking about to get an average RSI for example from a certain watchlist (Techs)
and use this value for a filter and run this filter over another watchlist or certain stock which is not in the first watchlist which I run the average RSI.
Here it is running, but how can I fix the watchlist here. Thanks for any advise.

periods = Param("periods", 14, 5, 30, 1);
RSIval = RSI(periods);

if (Status("actionEx") == actionScan)
{
	if (Status("stocknum") == 0)
		StaticVarRemove("~RSI*");
	StaticVarAdd("~RSItotal", RSIval);	
	StaticVarAdd("~RSIcount", 1);
	
}
RSItotal = StaticVarGet("~RSItotal");
RSIcount = StaticVarGet("~RSIcount");
AverageRSI = (RSItotal / RSIcount);

If you want to fix the watchlist in the code, rather than run it as a Scan, you’ll need to use a loop to loop through the symbols in the watchlist. You can find an example of it here. You should also use the following to conditionally trigger it so it only runs prior to processing the first stock on the watchlist you are ultimately processing.

if (Status("stocknum") == 0)  // only run when processing the first symbol 
    CreateAverageForWatchList( listnum ); // from linked example above

Nonsense. He doesn’t need to use loop. He can keep his code and just has to add some checks and that’s it.

/// code from this thread
/// @link http://forum.amibroker.com/t/static-var-to-calc-an-watchlist-avg/2515
periods = Param("periods", 14, 5, 30, 1);
RSIval = RSI(periods);

wlname = "Techs";// set watchlist

scan = Status("actionEx") == actionScan;

if(scan) {
	inWL = InWatchListName( wlname );	
	if( inWL ) {
		if(Status("stocknum") == 0)
			StaticVarRemove("~RSI*");
		StaticVarAdd("~RSItotal", RSIval);	
		StaticVarAdd("~RSIcount", 1);
		//_TRACE( "Calling StaticVarAdd in Scan" );
	}	
}

RSItotal = StaticVarGet("~RSItotal");
RSIcount = StaticVarGet("~RSIcount");
AverageRSI = (RSItotal / RSIcount);
Plot( AverageRSI, "AverageRSI", colorRed );

if(! scan) {
	wl = CategoryFind( wlname, categoryWatchlist );
	list = CategoryGetSymbols( categoryWatchlist, wl);	
	symcount = StrCount( list, "," ) + 1;
	if( RSIcount < symcount )	Error( "Too less symbols applied in Scan.\nCheck 'Apply to' filter setting of analysis and re-run scan!" );
}
1 Like

Yep, spot on. That’s certainly another way to achieve it.

The OP @Munichtrader does say he wants to “use this value for a filter and run this filter over another watchlist”. In which case using the loop approach would allow him to run the whole process in a single step over the second watchlist, without having to do a Scan first.

Alternatively he could use Batch to do the Scan followed by whatever process he wants to run on the second watchlist.

Some options to consider for you @Munichtrader. See what works best for your use case.

It’s not another way it is the superior option because using SetForeign is slower and if he runs it in chart he would still have to add a trigger too since without it it unnecessarily slows everything down continuously (i.e. applying looping code on WL of 500 symbols). So whether pressing scan button or chart paramtrigger doesn’t matter. BTW, analysis has option auto-repeat. So he would only need to press scan button once himself (all subsequent updates are done automatically). Everything else (calling static vars etc.) can be done in additional separate analysis window or chart pane (and even in separate code). Much quicker than dragging SetForeign code along all the time.

Fact remains static vars are much faster, global (accessible everywhere) and he doesn’t need loop as only choice as been claimed and he can keep his core code of post #1. Even without any edits. Because @Munichtrader, quite frankly you would not even need additional code as you can save your (staticvar creation) code as analysis project being set to your fix WL via ‘Apply to’ -> Filter analysis toolbar setting. Analysis projects save all analysis settings plus AFL. That’s actually the simplest option.

The saved project can be re-applied from File-Recent files menu. Via “Customize” UI functionality you can move Recent files drop down menu to analysis toolbar or AB main menu bar for quicker access of .apx analysis project file.

Hi, I’m new to AFL programming, and I’m trying to calculate a composite of the percentage of stocks in the S&P 500 that are trading above their 50-day moving average over time. I’d like to be able to examine it on a chart and then do backtesting with it and similar variables. Initially, I set it up with AddtoComposite with mixed success, but then in reading these posts, I figured I should learn how to use the StaticVarAdd function. Here is my attempt below, but I can’t seem to get it to work on the chart or elsewhere. Any insight would be much appreciated.

//Calculates a composite of the % of S&P 500 stocks that are trading greater than
//their 50 day EMA.

#include_once "Formulas\Norgate Data\Norgate Data Functions.afl";
SetBarsRequired( 100, 0 );

Filter = NorgateIndexConstituentTimeSeries("$spx") ;

gt50ema= IIf((C>=EMA(C,50) AND Filter),1,0);
lt50ema=IIf((C<EMA(C,50) AND Filter),1,0);

gt50emacomp=StaticVarAdd("~gt50pema",gt50ema);
lt50emacomp=StaticVarAdd("~lt50pema",lt50ema);

pctgt50pema=(gt50emacomp/(gt50emacomp+lt50emacomp+000001))*100;
Plot(pctgt50pema,"% > 50p EMA",colorGreen,styleLine);

StaticVarAdd is a procedure that does not return anything
https://www.amibroker.com/guide/afl/staticvaradd.html
StaticVarAdd creates static vars.
You try to create and call via Staticvardd. Wrong.
You call a static var via StaticVarGet.
https://www.amibroker.com/guide/afl/staticvarget.html

//Calculates a composite of the % of S&P 500 stocks that are trading greater than
//their 50 day EMA.

#include_once "Formulas\Norgate Data\Norgate Data Functions.afl";
SetBarsRequired( 100, 0 );

Filter = NorgateIndexConstituentTimeSeries("$spx") ;

gt50ema = C >= EMA( C, 50 ) AND Filter;
lt50ema = C < EMA( C, 50 ) AND Filter;

gt50emacomp = StaticVarGet( "~gt50pema" );
lt50emacomp = StaticVarGet( "~lt50pema" );

pctgt50pema=(gt50emacomp/(gt50emacomp+lt50emacomp+1e-9))*100;
Plot(pctgt50pema,"% > 50p EMA",colorGreen,styleLine);


if(Status("action") == actionScan) {
	if(Status("stocknum") == 0) {
		StaticVarRemove("~gt50pema*");
		StaticVarRemove("~lt50pema*");
	}
	StaticVarAdd("~gt50pema",gt50ema);
	StaticVarAdd("~lt50pema",lt50ema);
	Buy = 0;
}

Thanks so much; this is really helpful! How do I get it to appear on my price chart? I tried running Scan, then Apply and it comes up empty. I tried clicking on it in the indicator box and again nothing happened.

Would you pretty please use debugging methods.
I’m not support service.

I’ve given you a fixed formula that basically works. Now read a bit and please check yourself what’s causing empty output.

I don’t have Norgate data and I don’t have “Norgate Data Functions.afl” and so I don’t have NorgateIndexConstituentTimeSeries function. All three ones are not part of AmiBroker setup.

So I tested without Filter variable in the two array conditions gt50ema/lt50ema and it worked. So do the same first too. And as mentioned use debugging methods to know what’s going on.

Trust me, you are intelligent enough. So just use your Superman powers.

Thanks for your help. I’ll figure it out.

@paulgraham I am interested in building up a library of examples of using StaticVarAdd but if you are a Norgate data feed subscriber, you already have access to a variety of data for percentage of stocks above common moving averages in many of the major indexes.
image

But here is my attempt at calculating that using StaticVarAdd, run an Explore on the Watch List you are interested in.

// 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 (if any)
    StaticVarRemove( "~SymbolCount*" );
    StaticVarRemove( "~above*" );

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

        above = C >= MA( C, 50 );
        StaticVarAdd( "~SymbolCount", 1 );
        StaticVarAdd( "~above", above );

        RestorePriceArrays();
    }
}

ABOVEcomp = StaticVarGet( "~above" );
svSymbolCount = StaticVarGet( "~SymbolCount" );
PercentAbove = ( ABOVEcomp / svSymbolCount ) * 100;

///////////////
// Explore
///////////////
// various Filter settings are possible depending on what you want your
// Exploration output to look like
Filter = Status( "stocknum" ) == 0 ;
SetOption( "NoDefaultColumns", True );
AddColumn( DateTime(), "Date", formatDateTime );
AddColumn( svSymbolCount, "Total Number of Stocks", 1.0 );
AddColumn( ABOVEcomp, "Number>50 day ma", 1.0 );
AddColumn( PercentAbove, "Percentage > 50 day ma", 1.2 );

///////////////
// Chart
///////////////
Plot( PercentAbove, "Percentage > 50 day ma", colorRed, styleThick );

Produces an Exploration that looks like this,
image

A Plot like this,
image

2 Likes

@paulgraham @NorgateData Interestingly, my calculations do not match the data series provided by our friends at Norgate Data? Close, but not exact.

image

1 Like

Thank you so much! Your code is very clear, and I appreciate the help. I wasn’t aware that Norgate already had these preprogrammed. I’ll probably try this on a number of other indexes, so it’s helpful to know how to program it. I wonder if Norgate is using a different type of moving average in its calculations…

Thanks for this interesting discussion and different solutions. It helps erveryone and myself to get better in the amibroker world.:blush:

Again a beginner question my results on my database. Why do I get not all
results back to 2000 - here if I run the last script from portfoilobuilder /
explore the calculation is going back till 2014 and not back to 2005.
My database is bigger than 2005 back to 2000.
Any reason why? or which button do I have to change here?
In the Chart picture I get not all.Example2
Example

I think I know. My first symbol in my watchlist has only a short history back to 2014.
How can calc this because if a symbol comes into the index whith a short period of history the calculation is wrong. Is it possible to calc this average with all symbols and doesn´t consider the one symbol which has not enough database.

@Munichtrader Try turning on “Pad & Align” to a symbol you have long history of data for. That may solve your problem.

It is worth mentioning that if you do not have the historically accurate constituents of an Index that your results (it looks like you are testing against the DJIA) will not reflect what stocks were actually in the Index back in 2000.

Is there any other possibility to test a portfolio which different timeframes. Symbols in my list shortest timeframe 273 bars and longest 5000bars.
Again I get the performance only back tp 2013 and not back with 5000bars.
Can someone check which code I have to change here, that I get back the performance
till 5000 bars. Or is it only possible to have a list with all the same bars history?

The _TRACE( symbol ); here which window do I have to click to see the symbols. In the description the link doesn’t work
DebugView freeware program from http://www.sysinternals.com/Utilities/DebugView.html To view messages. Any hint how I view this.

Thanks for any help.

// we run the code on WatchList 0
List = CategoryGetSymbols( categoryWatchlist, 12 );
SetOption("MaxOpenPositions", 3);
 
if ( Status("stocknum") == 0 ) // Generate ranking when we are on the very first symbol
{
     StaticVarRemove( "values*" );

     for ( n = 0; ( Symbol = StrExtract( List, n ) )  != "";  n++    )
     {
         SetForeign ( symbol );
        
         // value used for scoring
         values = 100 - RSI(); 
         RestorePriceArrays();
         StaticVarSet (  "values"  +  symbol, values );
         _TRACE( symbol );
     }

     StaticVarGenerateRanks( "rank", "values", 0, 1224 );
}

symbol = Name();
values = StaticVarGet ( "values" +  symbol );
rank = StaticVarGet ( "rankvalues" +  symbol );

PositionScore = values;

BuySignal = Cross( Close, MA(Close, 100 ) );

// buy on the next bar
Buy = Ref( BuySignal, -1);
BuyLimitPrice = Ref( Close, -1) * 0.999;

// now we check if limit was hit for the symbols ranked as top 3
Buy = Buy AND L < BuyLimitPrice AND rank <= 3;
BuyPrice = Min( Open, BuyLimitPrice );

// sample exit rules - 5 - bar stop
Sell = 0;
ApplyStop( stopTypeNBar, stopModeBars, 5, 1);

trace
This is message which I get to my second problem

First calculation not going back to 2000!

Equitycurve