AmiBroker Code for the Breadth Indicator

30qtrindicator 3

As per request, I’m including the AmiBroker code for the “30% up/down last quarter in the Russell 3000 index” indicator. I REALLY need to come up with a better name for it than that. How about the Haines Breadth Indicator? No, that’s  stupid. Magic Matt’s Mystical Meter? Uh…sure.

It’s a two step process. You must do a scan every day, or as frequently as you want accurate data. It doesn’t hurt if you’re away on vacation and miss a few days, as AmiBroker will fill in the gaps when you return. The scan counts up all the stocks meeting your criteria, and writes these to separate ‘composite’ files that are then read back in by the indicator. You use this with the ‘explore’ process.


AddToComposite(C/LLV(C,60)>=1.3 AND xx,"~POS30QTR","X",19);
AddToComposite(C/HHV(C,60)<=.7 AND xx,"~NEG30QTR","X",19);

// above is the breadth measurement that showed the most promise.
//You could comment out all the other indicators and
//possibly speed things up.

AddToComposite(C/Ref(C,-1)>=1.04 AND xx,"~POS4DAILY","X",19);
AddToComposite(C/Ref(C,-1)<=.96 AND xx,"~NEG4DAILY","X",19);
AddToComposite(C/LLV(C,20)>=1.2 AND xx,"~POS20MO","X",19);
AddToComposite(C/HHV(C,20)<=.8 AND xx,"~NEG20MO","X",19);
AddToComposite(L==LLV(L,60) AND xx,"~NEWLOW60","X",19);
AddToComposite(H==HHV(H,60) AND xx,"~NEWHI60","X",19);

AddToComposite(myrsi<10 AND xx,"~LO_RSI_COMP","X",19);
AddToComposite(myrsi>90 AND xx,"~HI_RSI_COMP","X",19);

AddToComposite(rsi14<30 AND xx,"~LO_RSI14_COMP","X",19);
AddToComposite(rsi14>70 AND xx,"~HI_RSI14_COMP","X",19);

AddToComposite(C>BBandTop(C) AND xx,"~HI_BB_COMP","X",19);
AddToComposite(C<BBandBot(C) AND xx,"~LO_BB_COMP","X",19);



Filter= IsIndexConstituent("$RUA");
AddColumn(pos4d,"+4% today",1);
AddColumn(neg4d,"-4% today",1);
AddColumn(pos30q,"+30% qtr",1);
AddColumn(neg30q,"-30% qtr",1);
AddColumn(pos20m,"+20% month",1);
AddColumn(neg20m,"-20% month",1);
AddColumn(spyop,"SPY Open",1.2);
AddColumn(spycl,"SPY Close",1.2);
AddColumn(newlow,"New 60d Low",1.0);
AddColumn(newhi,"New 60d Hi",1.0);
AddColumn(pos30q/(pos30q+neg30q)*100,"30q dif",1.2);
AddColumn(newhi/(newhi+newlow)*100,"hi-lo dif",1.2);

It occurs to me that I don’t know if the first line….


…works for all types of data sources. If you don’t get any results, change xx to equal “1” and use AmiBroker’s filter to select current Russell 3000 members.

I run this on a historical set of the Russell 3000 constituents, so it takes a while on my aging laptop. You could also just set AmiBroker’s filter (not the one in the code, but the one used when running an ‘explore’ job) to the current list of Russell 3000 members. Just be aware that your historical data will be subject to survivorship bias. This won’t have any effect on your current readings however…it just means your data will get less reliable as you look back in time.

If you don’t run the composite code regularly, you won’t have any recent data for your indicator to display. It won’t break though, but it won’t be valid either.

Here’s the code for the diffusion indicator. It’s actually generic in the sense that you can compare any two composites (or tickers) you want. It defaults however to the file name used for the “30% quarterly” composite index. It also defaults to a 10 day requirement for a signal to be given.

thresh1=Param("buy thresh",75,1,99,1); 
thresh2=Param("sell thresh",75,1,99,1); 
Ticker1 = ParamStr("Symbol1", "~POS30QTR" ); 
Ticker2 = ParamStr("Symbol2", "~NEG30QTR" ); 
flgrng=Param("threshold count",10,1,50,1); 


10 thoughts on “AmiBroker Code for the Breadth Indicator”

  1. Thanks for all your work on this indicator. I have setup my AmiBroker with this code and will be watching closely at how it does.

    I have typically used the classic 200-day MA as a timing tool, but like this as it seems to warn earlier than that does.

    Question, as I believe you have said that your investments are mostly of the long-term variety, do you use this indicator as somewhat binary – i.e. sell all your long-term holdings when breadth goes red and back in when green?

    Personally, I find that I need these type of systems to control my emotions and was wondering what your approach it?

    1. Hi Jeremy and thanks for your comment! This indicator is a little conservative, which can be a useful thing. As a practical matter, I use it as a semi-discretionary filter as to whether I will enter long-term trades or not. I still use additional criteria for picking actual stocks, but I will keep from buying new ones when the indicator is red. I use individual trailing stop-losses on stocks, rather than exiting everything when the indicator turns red. And for short-term swing trades, I ignore the indicator completely (because set ups tend not to be dependent on overall market health).

      1. Thanks Matt – appreciate the response.

        I am a relative newbie with AmiBroker so getting used to things. One thing I want to try to see how I can build this indicator into a backtest that trades in and out of SPY (like you did as you were building this)? Are you able to elaborate on the code you ended up with to backtest this indicator? Personally I would love to see that if you were willing to give it up, as I suspect it is very complicated and beyond my abilities right now!

      2. Hello again Matt – out of interest, on the trailing stop after a red signal what do you use? A moving average breach as a signal (i.e. 13 day MA) or something else?

        1. Hi, Jeremy. If I understand your question correctly, I don’t use anything additional to tell me to exit. The red indicator already has ten days of data built into it, so when it turns red (from previously green), I would exit. Likewise turning from red/neutral/green…as soon as it’s green, I’d get back into the market.

    1. I don’t use metastock so I don’t have the ability to do that, sorry! I use this indicator as a ‘market health’ indicator when investing in long-term individual stocks. While I tested it on SPY, I don’t actually use it to trade that particular ETF. Thanks for your comment!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.