How to write your own chart commentary

One of the interesting aspects of using AmiBroker Formula Language is writing automatic chart commentaries. The idea behind this technique is as follows:

  1. You write the commentary formula that consists of two basic elements: static texts and AFL expressions
  2. AmiBroker evaluates expressions using currently selected symbol data and generates dynamic content
  3. The mixture of static text and evaluated formulas are displayed in commentary output window
  4. Additionally buy/sell arrows are plotted on the chart

Commentaries are available from Analysis->Commentary menu. When you open commentary window you will see two tabs: Commentary and Formula. In the Formula tab you can type the AFL statements which will be evaluated by AmiBroker resulting in dynamic commentary that appears in Commentary tab. The following sections will guide you through the steps needed to write your very own commentary formulas.

Writing static texts

Static text elements written in the formula should be enclosed in the quotation marks and terminated by semicolon sign as shown below:

"This is sample static text statement";

You can write several statements and each statement will be placed in a new line in the commentary output window:

"This is first line of text";
"This is second line of text";

Please type these examples into edit field in the Formula tab and switch to Commentary tab. You will see the texts displayed in the output area but without any quotation marks or semicolons. This is because AmiBroker has evaluated this simple text statements into strings and it displayed the strings in the output window.

Instead of just typing the text, it is advised that any new code should use printf function instead.

printf( "This is sample static text statement" );

To write several lines of text you can use a couple of statements as shown above or you can do this using single statement and line break sequence ('\n'):

printf( "This is first line of text\nThis is second line of text\nThis is third line of text" );

You can also concatenate the string constants which will result in single line text:

printf( "This" +
" is" +
" single"+
" line" + " of text" );

Colors and styles

Since version 5.90 commentary and interpretation windows support colors and bold/italic styles. To specify beginning and end of bold section use <b> and </b> tags. To specify beginning and end of italic section use <i> and </i> tags. To change text color use EncodeColor as shown in the example below:

printf("<b>Bold text</b>\n");
printf("<i>Italic text</i>\n");
printf("Now " + EncodeColor( colorRed ) + "red text\n");
printf("and finally " + EncodeColor( colorGreen ) + "green <b>AND bold <i>AND italic</i></b>\n");
printf(EncodeColor( colorBlack ) + "going back to black");

Dynamic content

I guess that you are quite bored with these simple examples, let's start with some dynamic content.

To enable dynamic commentaries AFL has a couple of special functions available, but two of them are the most important: NumToStr() and WriteIF(). WriteIF() function is used for conditional text display and will be described later in this article, now let us see what we can do using NumToStr() function.

The AFL reference manual says:

NumToStr( ARRAY );
FUNCTION This function can only be used within an Guru commentary. It is used to display the numeric value of NUMBER or ARRAY.

So, if you want to display a value of a number or currently selected bar of the array you should use NumToStr() function. But... wait a minute - what does it mean "currently selected bar of the array"? Let me explain this using simple formula (please type it in the Formula tab):

printf( NumToStr( close ) );

When you switch to Commentary tab you will see the value of closing price (the same one which is displayed at the top of main price chart). But when you click on the chart in another place, selecting different date and then you click "Refresh" button you will see different value - the closing price at day you have selected. So NumToStr( close ) function displays the value of currently selected bar of close array. And it works exactly the same way with other arrays. If you write

printf( NumToStr( macd() ) );

you will see the exact value of MACD indicator at the day you have selected in the main chart. Having our current know-how we are able to write some statistics:

printf( "Closing price = " + NumToStr( close ) + "\n" );
printf( "Change since yesterday = " + NumToStr( close - ref( close, -1 ) ) + "\n" );
printf( "Percent chg. since yesterday = " + NumToStr( roc( close, 1 ) ) + " %%\n" );
printf( "MACD =" + NumToStr( macd() ) + " , Signal line =" + NumToStr( signal() ) + "\n" );

When you switch to Commentary tab you will see output similiar to this one:

Closing price = 17.940
Change since yesterday = -0.180
Percent chg. since yesterday = -0.993 %
MACD = -0.001 , Signal line = 0.063

Quite nice, isn't it? You can also write current symbol ticker and selected date using name() and date() functions as shown below:

printf( "Statistics of " + name() + " as of " + date() );


Instead of using NumToStr to convert number to string, we can format numbers directly using printf flexible % format specifiers. For example using %.2f means write a number with 2 decimal places, %.3f will mean write a number with 3 decimal places, %g will mean write a number with minimum required number of digits (auto-format). So we could write our previous example as follows:

printf( "Closing price = %.3f\n", close );
printf( "Change since yesterday = %.3f\n", close - ref( close, -1 ) );
printf( "Percent chg. since yesterday = %.2f%%\n", roc( close, 1 ) );
printf( "MACD = %.4f, Signal line = %.4f\n", macd(), signal() );

As we can see this code is shorter and clearer. The first argument of printf function is a string (strictly speaking so called formatting string that contains text and number placeholders/format specifiers marked with %. Subsequent arguments of printf function are actual values (numbers) we want to write (without need to convert to string anymore). As you may have noted, if we want to specify just percent sign, not a formatting sequence, we need to write %% (two percent signs).

But what we miss here is an ability to write something if some condition is met and write something different otherwise...

Conditional text output

AFL is equipped with very nice function called WriteIF() that can output different texts depending on the condition. Let us look what documentation says:

FUNCTION This function can only be used within an Guru commentary. If EXPRESSION evaluates to "true", then the TRUE TEXT string is displayed within the commentary. If EXPRESSION evaluates to "false", then the FALSE TEXT string is displayed.

So we can easily output different text depending on expession, for example:

writeif( macd() > signal(), "The MACD is bullish because is is above it's signal line", "The MACD is bearish because it is below its signal line" );

You can also combine several WriteIf() function calls in order to handle more possibilities:

"The current market condition for "+ name() + " is: ";

avgcond1 = ( c > ema( close, 200) ) + 0.1 * ( close > ema( close, 90) ) + 0.1 * ( close > ema( close , 30 ) );
avgcond2 = -( c < ema( close, 200) ) - 0.1 * ( close < ema( close, 90) ) - 0.1 * ( close < ema( close , 30 ) );

WriteIf( avgcond1 == 1.2,
"Very Bullish",
WriteIf( avgcond1 == 1.1,
WriteIf( avgcond1 == 1.0,
"Mildly Bullish", "") ) ) +

WriteIf( avgcond2 == -1.2,
"Very Bearish",
WriteIf( avgcond2 == -1.1,
WriteIf( avgcond2 == -1.0,
"Mildly Bearish", "") ) );

The formula above will return the text "The current market condition for {your ticker here} is: Very Bullish" if close price is above 30 day average and close is above 90 day average and close is above 200 day average. In other cases the formula will give you Bullish, Mildly Bullish, Mildly Bearish, Bearish or Very Bearish ratings.

For more examples on AFL commentaries please check AFL formula library especially MACD commentary formula which demonstrates all techniques presented here.

Now you are ready to start with your own commentaries... Good luck!