Create a Composite Ticker Using Amibroker

One of the more common questions that I get asked by members of my trading course is “How do I create a composite ticker for S&P500 stocks?”.

In this article I’ll explain.

What is a Composite Ticker?

A Composite Ticker is created using the AddToComposite function provided by Amibroker. (Please read more here).

Simply put, the AddToComposite function allows you to create an artificial ticker that can store the value of multiple security statistics.

For example, you might like to know how many S&P500 stocks have become oversold on any given day.

Using AddToComposite, you could scan a watchlist of S&P500 stocks and count the number of tickers that have an RSI() value crossing below 20.

If 50 stocks have an RSI() value crossing above 20, our composite ticker would store a value of 50. If 20 stocks have an RSI() value crossing above 20, our composite ticker would have a value of 20. And so on.

This could obviously be useful information because if a high number of stocks have just become oversold, the index itself might perform well for the next few days.

How to Create a Composite Indicator

Using the above example as a template, we’ll create a composite indicator that stores the percentage value of stocks belonging to the S&P500 that have an RSI(2) value crossing below 20.

The first step is to create a watch-list which has each of the stocks belonging to the S&P500.

Because we’re going to want to backtest our composite indicator, it’s important at this stage to make sure that the watch-list also includes delisted stocks and the historical joiners and leavers of the index.

My data provider (Norgate Premium Data) has a ready-made watch-list which includes all the S&P500 members, both past and present, so to create my composite indicator I’ll be scanning the S&P500 historical constituents watchlist.

(To access a free trial of Norgate Premium data, please click here.)

The next step is to define the criteria that we want to scan for.

For this particular example we’ll count the number of stocks that have a 2 period RSI crossing below 20:

RSIOversold = Cross(20,RSI(2));

Remember that we’re only interested in the stocks that belong to the S&P500 at the time of our criteria being met. So we also need to include the following line in our formula:

InIndex = IsIndexConstituent(“$SPX”); 

To find the percentage value of stocks belonging to the S&P500 which meet our criteria we can scan the S&P500 watch-list using the formula:

RSIOversold = Cross(20,RSI(2));

InIndex = IsIndexConstituent(“$SPX”); 

Num = 500;

Criteria = InIndex AND RSIOversold;
Buy = 0;

Note in the above example that I have assigned the value of 500 to the Num variable.

In reality, the S&P500 often has a couple more than 500 stocks.

For complete accuracy you could also create a composite ticker that stores the number of current S&P500 constituents, and assign that value to the Num variable. But for simplicity I won’t do that here.

Once you’ve scanned the watch-list, your composite ticker gets stored in group 253.

However, as opposed to going into your groups and selecting the composite ticker, I find it easier to include an indicator plot function within the formula.

Using the Foreign() function we can then plot our composite ticker as an indicator beneath our price series.

So the complete formula is now as follows:

RSIOversold = Cross(20,RSI(2));

InIndex = IsIndexConstituent(“$SPX”);

Num = 500;
Criteria = InIndex AND RSIOversold;
Buy = 0;

X = Foreign(“~S&P500%StocksRSIOversold”,”C”);

Plot( X, “% of S&P500 Stocks Oversold”, colorblue , styleline ) ;

Once you’ve created the composite ticker you are now able to press “apply” to plot the values beneath your price series.


Testing the Composite Indicator

We now have an indicator which tells us the percentage number of stocks belonging to the S&P500 which have an RSI(2) value crossing below 20.

Perhaps if a there is a high percentage we might want to buy the S&P500 ETF “SPY” in anticipation of a short-term reversal.

One idea is to buy the SPY on the next day open if 25% or more S&P500 stocks have an RSI(2) value crossing below 20.

Exits are made on the open following a close above the previous day’s high.

The performance of this strategy since 2007 (with 100% of equity allocated to each position) is as follows:

  • No. of trades = 192
  • % of Winners  = 72.40%
  • Average P/L% per trade = 0.54%
  • Average hold time = 4 days
  • Annualised return = 10.42%
  • Maximum drawdown = -23.74%
  • Exposure = 29.27%

The equity curve and monthly breakdown of returns can also be seen below:


You could obviously be far more creative with how you might like to use the AddToComposite function.

For example, many charting websites now carry market breadth indicators which give data such as the number of stocks trading above their 200 day MA or the number of advancing or declining issues.

But the limiting factor is often that the indicators are often derived using data that belongs to all issues on the NYSE or NASDAQ, or to a particular index.

But what if you’re only interested in a particular sector?

The good news is that the AddToComposite function allows the creation of sector or industry specific breadth indicators too.

For example, one popular market breath indicator is called the “Breadth Thrust Indicator” (Read More Here)

To create a Breadth Thrust Indicator for the technology sector we need to first scan all the stocks belonging to the Russell 3000 historical constituents watchlist which have a GICS ID of 45:

To do this with Amibroker and Norgate Premium data,  please use this formula:

TechStocks = IsIndexConstituent(“$RUA”) AND InGics(“45”);

Buy = 0;

Next we need to find the number of advancing tech stocks and then divide by the total number of tech stocks.

And then finally, we need to smooth the ratio using a 10 period EMA.

Once again we scan the same watchlist using this formula:

Advancing = IsIndexConstituent(“$RUA”) AND InGics(“45”) AND C > Ref(C,-1);

NumTechStocks = Foreign(“~NumTechStocks”,”C”);

BreadthRatio = (Advancing / numtechstocks)*100;
BreadthThrust = EMA(BreadthRatio,10);

BreadthThrustTech = Foreign(“~BreadthThrustTech”,”C”);

Buy = 0;


As per the original breadth thrust parameters suggested by Marty Zweig, if the indicator crosses above 40% and then within 10 days also crosses above 61.5%, we expect the market to rally.

In this case the breadth thrust indicator was created using a composite of tech stock tickers, so we’ll apply the indicator to the tech sector etf “XLK”.

Note there have been 2 signals during 2016, both of which preceded a strong one month rally:


I hope that’s given you some pointers and an idea or two.

All the best,



  • Growbuck

    Reply Reply November 8, 2016

    Fun stuff Llewelyn. What did you use as an exit in the breadththrust example?

    • Llewelyn James

      Reply Reply November 9, 2016


      Thanks for reading. The example uses a 1 month timed exit.



Leave A Response

* Denotes Required Field