Issue 12/2001 (No. 20)
AmiBroker Tips newsletter.
Issue 12/2001. No 20.
30 June 2001.
Copyright (C)2001 Tomasz Janeczko.
All back issues available from:
1 Welcome
2 AFL Library: Calculating multiple security statistics using AFL scripting
1 Welcome

Welcome to the 12th issue of AmiBroker Tips newsletter in the 2001. Well some time has passed since the last issue of the newsletter, but hope you will excuse me because this time I have prepared something special for you - the article on calculating multiple-security (or cross-market) statistics using AFL scripting. I will show you what new exiting possibilities AFL scripting opens and I will present two applications of this technique.

But first let me ask you one thing: have you upgraded already to the version 3.60? If not - it is strongly recommended - not only the version 3.60 brings you a lot of bug fixes but (most importantly) it contains literally hundreds of new features including AFL scripting host (that we will use in this issue's article).

For the details on what is new in the version 3.60 please check the news page on AmiBroker web site at: . The downloads are available from

Second thing: do you know that a brand new, "interactive" AFL on-line library has launched recently? This database driven on-line application not only allows you to downloads the AFL formulas for the indicators, explorations, trading systems and commentaries but also allows you to add your own creations to share with the others! Check it out at: Some of you already contributed to this library - Thank You Very Much!

Just a reminder: if you have any comments/suggestions or article ideas, please don't hesitate to drop a line to

2 AFL Library: Calculating multiple security statistics using AFL scripting

Note: Examples provided in this article require AmiBroker 3.60

2.1 Introduction

AFL Scripting host introduced recently to AmiBroker is an interface between AFL engine and JScript/VBScript engines provided by Microsoft. The scripting host in AFL allows you to mix parts in the "native" AFL code with parts written in JScript or VBScript. This solution gives you unprecedented flexibility while maintaining the original speed and easy syntax of AFL. You can use AFL for the fastest execution of your formulas and JScript/VBScript for things that are hard or impossible to do in AFL.

This article will show you one interesting application of AFL scripting: calculating multiple security (or cross market) statistics and indicators. The article assumes that you have basic knowledge of AFL scripting - so it is advised to read the AFL scripting host documentation first.

2.2 The idea

Basically AFL allows you to calculate things based on single security prices. The are two exceptions from this rule provided by RelStrength() and Foreign() functions. These two functions allow you to use other security prices in the AFL formula. Although these functions are very useful for things like relative performance charts, they are not so useful for tasks requiring prices of all stocks (or a large number of stocks) because one would need to type several hundreds of Foreign() function calls to do so. Moreover this approach would require listing all the ticker names within the formula which makes the formula tight to particular market. We obviously need completely different approach...

Just imagine if we were able to store the results of calculations performed on single security somewhere and then use those partial data to generate some multiple security indicator. You may say that one can create the exploration, then export the results to the CSV file, then load it into Excel and then perform the calculations there. It would work (in some cases) but you have to agree that the solution is not nice.

This is the area where AFL scripting may help a lot. With AFL scripting you have an access not only to AFL variables but also to all registered OLE automation and COM objects. What does this mean for you? It means that AFL scripting host allows you to create external files and ... access AmiBroker application objects!

Is this cool? I guess so - we are able to create some artificial "composite" tickers to store multiple-security (or cross market) statistics and then use them in other formulas!

So, to summarize the concept: we will run our formula (using Scan feature) through a group of stocks performing some calculations. We will compute some multiple security statistics and store the results in the artificial ticker created using AFL scripting host and AmiBroker automation objects.

2.3 The solution

The key to the solution is the following algorithm:

  1. Perform you ordinary AFL formula first (that will calculate single stock indicator)
  2. Create an artificial ticker (named for example "_composite")
  3. Loop through the array generated in AFL and add quotes to the artificial ticker that will hold our multiple-security statistics data

Example 1:

In the first example I will show how to calculate the indicator that shows the number of stocks meeting certain criterion. In this example this would be RSI less than 30 (oversold condition), but it can be anything you like.

So the first line of our formula will be:

values = rsi() < 30;

This will store "true" in the values array for all date points when RSI is less than 30.

Then we will enable AFL scripting host and prepare the date arrays that we will use later in the scripting part to add the artificial quote on appropriate date:


days = day();
months = month();
years = year();

Now it is the time for the scripting part (note <% sign marking the beginning of JScript code in AFL). The following four lines simply convert AFL-side variables to the array variables visible from the JScript side:

days = AFL("days").toArray();
months = AFL("months").toArray();
years = AFL("years").toArray();
values = AFL("values").toArray();

Then we are ready for the "real-thing", first we create an AmiBroker automation object, then we add an artificial ticker called "_composite" (note that Add method is safe - in case the ticker already exists it simply returns existing object without adding the duplicate):

oAB = new ActiveXObject("Broker.Application");

comp = oAB.Stocks.Add("_composite");

Now we will loop through the array adding the quotations to artificial ticker and store our statistics in the Volume field of the quotation object:

for( i = 0; i < days.length; i++ )

 qt = comp.Quotations.Add( years[ i ] + "-" + months[ i ] + "-" + days[ i ] );

 if( values[ i ] == 1 ) qt.Volume += 1;

We simply add 1 to the Volume when values array is true ( RSI < 30 ).

Finally we close our scripting block with %> and add a buy = 0 assignment so the Scan function of Automatic Analysis window does not complain about missing buy/sell variable assignments:

buy = 0; // do not generate signals

(A ready to use JScript formula could be found here and the VBScript version could be found here)

If we run the formula using "Scan" function of Automatic Analysis window the result would be an artificial stock "_composite" filled with quotations. The Volume field of those quotes will contain the number of stocks meeting our criterion (RSI<30) in the population of scanned stocks.

You can easily see the chart of this new "indicator" using the following custom formula in Indicator Builder:

graph0 = foreign("_composite", "V");

High values of this "indicator" show that most of the stocks in the analysed group are oversold. This usually happens before a great rise of the whole market. We just created market-wide oversold detector!

There are two caveats: (1) if you want to re-run the formula you must delete "_composite" ticker, otherwise the results of two scans would be cumulated. (2) the multiple-security calculation formula should only be used in Automatic Analysis window (Scan/Backtest)


Example 2:

In the second example I will show you how to use the same technique to count the number of open positions of your trading system. This is useful if you want to know how big account would you need to trade your system following all the trades. Our formula will be very similar to the one before so I will point only the differences.

First we should have our original trading system formula:

/* Your original formula here */
/* In this example this is simple macd/signal crossover system)

buy = cross( macd(), signal() );
sell = cross( signal(), macd() );

Then the rest of code is the same upto the for loop which looks a little bit different (for simplicity only long trades are considered):

// we add artificial "_openposcount" stock that we will use to store // the cross-market statistics information comp = oAB.Stocks.Add("_openposcount");

// the trade is closed initially
intrade = 0;

for( i = 0; i < days.length; i++ )

// we add the quotation to the artificial stock that we will use
// to store the information about the cross-market statistics
qt = comp.Quotations.Add( years[ i ] + "-" + months[ i ] + "-" + days[ i ] );

// check if no trade is open and there is a buy signal then open long trade
if( intrade == 0 && buy[ i ] ) intrade = 1;

qt.Volume += intrade; // we use Volume field to count number of open trades each day

// check if there is an open trade and there is a sell signal then close long trade
if( intrade == 1 && sell[ i ] ) intrade = 0;


We use "_openposcount" artificial ticker to store the results. Again we should run just back test of the formula and the "_openposcount" ticker would become available. Use graph0 = foreign( "_openposcount", "V"); in Indicator Builder after running the back-test to see the chart of the number of open positions of your system.

Of course the same (mentioned above) ceveats apply to using this formula.

(A ready to use formula for counting open positions could be found here.)

2.4 Known issues

As mentioned before this code has one major drawback - to recalculate properly the values of multiple-security indicator you have to delete artificial ticker before running scan. This is so, because currently the script does not know when one scan ends and the next scan begins. This drawback will be eliminated in the next release of AmiBroker that will provide additional information to the script.

Another issue is a problem of daily updates of the indicator. The most safe method is of course deleting the artificial ticker and re-running scan. Alternatively one can tweak the "for" loop to include only the most recent bar. This is, however, not recommended. I hope to invent some better method soon and include it in the next release of AmiBroker.

2.5 Conclusion

As you can see AmiBroker's AFL scripting host adds a new dimension to the toolbox of a trader. Coupling AFL code with scripting parts and AmiBroker's automation interface enables things you could only dream of when using other software.

The technique presented in this article could be used to create very interesting multiple-security indicators. Mr. Dimitris Tsokakis is currently working on application of this technique to the creation of new kinds of market breadth indicators. The preliminary results are promising. I think that AmiBroker will help us develop a new brand of technical analysis tools making market entry and exit signals much more reliable than before.

.... and that's all for this week - hope you enjoyed reading

AmiBroker Tips newsletter. Issue 12/2001. Copyright (C)2001 Tomasz Janeczko. All back issues available from: