Issue 4/2000
AmiBroker Tips weekly newsletter.
Issue 4/2000.
Copyright (C)2000 Tomasz Janeczko.
All back issues available from:
http://www.amibroker.com/newsletter/
IN THIS ISSUE
1 Welcome
2 Tutorial: Working with composites
3 AFL Formula Library: Implementing alerts on trend lines
4 Tip of the week: How to automate assigning stocks to sectors/industries ?
1 Welcome

Welcome to the 4th issue of AmiBroker Tips newsletter.

In tutorial column I describe how to set up composites correctly so that AD-Line, TRIN indicators are shown properly.

In AFL corner I discuss a method of detecting trend line breaks. This is somewhat tricky stuff to do in current version of AFL and future version will have better support for doing such things but for a while you are limited to this solution.

By the way: Do you find this newsletter useful? Have any comments/suggestions or article ideas. Please don't hesitate to drop a line to newsletter@amibroker.com

2 Tutorial: Working with composites

AmiBroker allows to plot composite indicators such as Advance-Decline line and Arms Index (TRIN). However for proper functioning they need some additional setup - mainly defining base stock (index) which is taken into account when performing calculations.

In order to make Advances/Declines and TRIN work you have to:

  1. Open Categories window using Stock->Categories menu item.
    Select base index for given market in Markets tab and Base indexes for - Composites combo.
    For example if you are following NYSE this can by ^DIJ (Dow Jones Average)


  2. Choose Stock->Calculate composites... menu item to open the window shown below and mark Number of advancing/declining issues and Apply to: all quotes, All markets

  3. Click Calculate . From now on ADLine and TRIN indicators should be visible.

Q: Why does AB need "base index"?
A: Just because it may happen that not all stocks are quoted every businness day and AB needs must calculate number of
advancing/declining issues per market. So it checks the "base index" quotations dates and tries to find corresponding quotes of all stocks belonging to that market to find out how many issues advanced, declined and not changed at all.

Q: What are "Volume for base index" and "Copy volume to all indexes" checkboxes for?
A: "Volume for base index" and "Copy volume to all indexes" are provided in case you DON'T have real volume data for index quotes. In that case AmiBroker can calculate volume for index as a sum of volumes of all stocks belonging to given market.
First option assigns calculated volume only to "base index", the second copies the volume figure to all indexes belonging to given market.

3 AFL Formula Library: Implementing alerts on trend lines

A trend line is a sloping line drawn between two prominent points on a chart. Rising trend lines are usually drawn between two troughs (low points) to illustrate price support while falling trend lines are usually drawn between two peaks (high points) to illustrate upside price resistance. The consensus is that once a trend has been formed (two or more peaks/troughs have touched the trend line and reversed direction) it will remain intact until broken.

The trend line is described by well-know linear equation:

y = ax + b

where x represents time (bar number), y represents price, a defines the slope of the line and b defines initial offset. The main problem in defining appropriate AFL formula is finding the values of these two latter coefficients. If a trend line is drawn between two important lows the slope of the line could be calculated by subtracting the second low price from the first low price and dividing the result by a number of bars between the lows:

a = ( low2 - low1 ) / ( bars2 - bars1 )

Calculating offset (b) value is trivial when we shift the time scale so x=0 is located at the first low. In this case b=low1.

So our mathematical formula for the trendline between two important lows will look like this:

y = ( x - bars1 ) * ( low2 - low1 ) / ( bars2 - bars1 ) + low1

While determining low prices is simple (just point your mouse over the dominant low and read the low price from a data tooltip that appears on the screen), determining the bar number is not that simple. You can of course count bars by hand but this is simply too much work (especially when you don't have Florida volunteers for a recount :-) ). Luckily we have AFL that allows us to do it in automatic way. All we have to do is to make a running total of bars (our x coordinate) using cum() function:

x = cum( 1 );

and then find out where low occured using valuewhen() function:

bar1 = valuewhen( low == low1, x, 1 );
bar2 = valuewhen( low == low2, x, 1 );

Since trend lines are different for each stock, now I will show you the whole thing using AXP (American Express) quotes.
We can observe quite nice trend on this stock, with two important lows on March 9th, 2000 (low price 39.7648) and June, 22th 2000 (low price 51.9375) as show in the picture below:

Note that StartY and EndY parameters of the trendline are exactly equal the low prices of the days - this is extremely important since we will be searching for this values using valuewhen() function (actual lows could be determined using data tooltip).

So we have startvalue = 39.7648 and endvalue = 51.9375 and we can write an AFL formula for the trendline:

x = cum(1);

startvalue = 39.7648;
endvalue = 51.9375;

startbar = lastvalue( valuewhen( low == startvalue, x, 1 ) );
endbar = lastvalue( valuewhen( low == endvalue, x, 1 ) );

a = (endvalue-startvalue)/(endbar-startbar);
b = startvalue;

trendline = a * ( x - startbar ) + b;

A trend line could be now drawn with a price chart using the following assignments:

graph1 = trendline;
graph0 = close;

/* some color + style settings */
graph0style=64;
graph0color=2;
graph1style = 5;
graph1color = 8;

Now we can test trend line break using the following formulas:

buy = cross( close, trendline ); /* buy signal when close crosses above the trendline */
sell = cross( trendline, close ); /* sell signal when close crosses below the trend line */

Note that these tests are correct only for single stock, so in fact we should check the ticker name before:

buy = name()=="AXP" AND cross( close, trendline );
sell = name()=="AXP" AND cross( trendline, close );

As you can see the whole procedure is a little bit confusing and need to be repeated for every stock individually. But what about making it automatic? Yes - it is possible in AFL! AmiBroker Formula Language has the functions for detecting important lows and highs (through(), peak() functions) and we can use them to generate automatic trend lines. Just let AmiBroker two last important lows for us using the following formula:

perchg = 10;

startvalue = lastvalue( trough( low, perchg, 1 ) );
endvalue = lastvalue( trough( low, perchg, 2 ) );

where perchg is a variable that controls minimum change threshold for finding lows. The rest of the formula remains the same, so complete automatic trend line formula using lows and 10% minimum change looks as follows:

x = cum(1);

perchg = 10;

startvalue = lastvalue( trough( low, perchg, 1 ) );
endvalue = lastvalue( trough( low, perchg, 2 ) );

startbar = lastvalue( valuewhen( low == startvalue, x, 1 ) );
endbar = lastvalue( valuewhen( low == endvalue, x, 1 ) );

a = (endvalue-startvalue)/(endbar-startbar);
b = startvalue;

trendline = a * ( x - startbar ) + b;

graph0 = close;
graph1 = trendline;
graph0style=64;
graph0color=2;
graph1style = 5;
graph1color = 8;

I am not saying that this formula is perfect. It sometimes generates strange trend lines and it strongly depends on perchg parameter. You can of course use peak() function instead of trough() to base your trend line on highs instead of lows.

As for the future - in some next version of AmiBroker the support for alerts on studies will be enhanced so watch out!

( Note: the formulas presented here are also available from http://www.amibroker.com/library.html )

4 Tip of the week: : How to automate assigning stocks to sectors/industries ?

Note: This functionality is available only in Windows version of AmiBroker

In the first issue of AmiBroker Tips newsletter AmiBroker I discussed using of AmiBroker's OLE automation interface for accessing stock data. In this article I will give you another example of automation: assigning stocks to industries using simple JScript. For starters I recommend reading the first article before proceeding with this one.

First we should set up our sectors and industries using Stock->Categories window. The difference between a sector and an industry is that industries "belong" to sectors, for example: "Air Courier", "Airline", "Railroads", "Trucking" industries belong to "Transportation" sector. So an assignment to an industry implicts assignment to a sector. If you don't want to have detailed industries you can just assign first 32 industries to 32 sectors on one-by-one basis.

Now let's suppose that we have a text file that contains tickers, full company names and a industry number. Industry number should correspond our settings in Categories window. A sample file would look like this:

ELM,ELINK MEDIA LIMITED,0
GCN,GOCONNECT LIMITED,0
SGN,SINGLETON GROUP LIMITED,1
AHH,AGRO HOLDINGS LIMITED,1
ATP,ATLAS PACIFIC LIMITED,1
AFF,AUSTRALIAN FOOD & FIBRE LIMITED,1
ASR,AUSTRALIAN RURAL GROUP LIMITED,1
ARP,ARB CORPORATION LIMITED,2
ATL,AUTO ENTERPRISES LIMITED,2
ALO,AUTO GROUP LIMITED,2
BER,BERKLEE LIMITED,2
ADB,ADELAIDE BANK LIMITED,3
ANZ,AUSTRALIA & NEW ZEALAND BANKING GROUP LIMITED,3
BOQ,BANK OF QUEENSLAND LIMITED.,3
BWA,BANK OF WESTERN AUSTRALIA LIMITED,3

and our Categories are set up so sectors and industires have one-to-one relationship with the following (zero-based) numbering 0 - "Advertising & Marketing", 1- "Agriculture & Related Services", 2- "Automotive & Related Services" and 3- "Banking".

The script for importing the data file will look like this:

/* change this line according to your data file name */
var filename = "industry_data.txt";

var fso, f, r;
var ForReading = 1;
var AmiBroker;
var fields;
var stock;

/* Create AmiBroker app object */
AmiBroker = new ActiveXObject( "Broker.Application" );

/* ... and file system object */
fso = new ActiveXObject( "Scripting.FileSystemObject" );

/* open ASCII file */
f = fso.OpenTextFile( filename, ForReading);

/* read the file line by line */
while ( !f.AtEndOfStream )
{

r = f.ReadLine();

/* split the lines using comma as a separator */
fields = r.split(",");

/* add a ticker - this is safe operation, in case that */
/* ticker already exists, AmiBroker returns existing one */

stock = AmiBroker.Stocks.Add( fields[ 0 ] );

stock.FullName = fields[ 1 ];
stock.IndustryID = parseInt( fields[ 2 ] );

}

/* refresh ticker list and windows */
AmiBroker.RefreshAll();

The whole thing is just reading the file line by line and assigning the fields to properties of stock automation object. It's so simple :-). The only thing that you might want to change is the name of the file with a data - my example uses "Industry_data.txt" file name but this can be changed according to your naming convention. A complete script could be found here and a sample data file is here.

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


AmiBroker Tips weekly newsletter. Issue 4/2000. Copyright (C)2000 Tomasz Janeczko. All back issues available from: http://www.amibroker.com/newsletter/