AmiBroker Documentation Item No. ab400.html

This is the part of AmiBroker documentation. Copyright 2001 Tomasz Janeczko. All rights reserved.


AFL Scripting Host - preliminary documentation

Basics

AFL scripting host is an interface between AFL engine and JScript/VBScript engines available as a part of Internet Tools & Technologies platform provided my Microsoft.
It allows you to build the formulas that are have parts in AFL code and parts in JScript/VBScript.

Requirements

Microsoft JScript/VBScript engines come with Internet Explorer 4 or higher(Windows 98, Millenium, 2000 have it included in the operating system). It is however advised to install the latest version of Internet Explorer (5.5) or download and install the latest version of Windows Scripting Host (5.5) from Microsoft:

Windows 95, 98, Me, NT:
http://www.microsoft.com/scripting/downloads/v55/other/scr55en.exe

Windows 2000:
http://www.microsoft.com/scripting/downloads/v55/windows2000/scripten.exe

JScript/VBScript documentation can be found on official scripting page at:
http://msdn.microsoft.com/scripting/

Enabling AFL Scripting Host

If you want to use scripts within your formulas you have to call EnableScript() function
in the beginning of your formula. The function takes one input parameter - engine name:

EnableScript("jscript");

or

EnableScript("vbscript");

From then on, you will be able to embody parts written in scripting language in your formulas. The begin and the end of the script must be marked with <% and %> sequences, as shown in the example below:

EnableScript("vbscript");

// "normal" AFL statements
buy = cross( macd(), 0 );
sell = cross( 0, macd() );

<%
..... your script code here.....
%>

// "normal" AFL statements
buy = ExRem( buy, sell );

Using variables

Currently the only way to exchange the information between "normal" AFL part and script part is to use variables. AFL scripting host exposes one object (predefined, no creation/initialization needed)
called AFL.

The AFL object has one (default) parametrized property called Var( varname ) that can be used to access AFL variables from the script side:

// example in VBScript
<%

buyarrayfromscript = AFL.Var("buy") ' get the buy array from AFL to the script-defined variable

AFL.Var("buy") = buyarrayfromscript ' set the buy array in AFL from the script-defined variable

%>


Since Var is default property you can omit its name and write simply AFL( varname ) as shown in the example below:


<%

buyarrayfromscript = AFL("buy")
' gets the buy array from AFL to the script-defined variable

AFL("buy") = buyarrayfromscript
' sets the buy array in AFL from the script-defined variable

%>

In AFL there are three data types possible: array (of floating point numbers), a number (floating point) and a string. The VBScript and JScript engines use variant data type that can hold any type of the variable including three used by AFL. As in AFL, you don't declare variables in scripting languages, the type is determined by the first assignment. In case of VBScript you can get/set AFL variables of any supported type using syntax shown above. But in JScript, due to the fundamental difference in handling arrays in JScript (array elements in JScript are implemented as dynamic properites of an array object) you need to use the following code to get the value of AFL array into JScript array:

// example in JScript
<%
function GetArray( name )
{
return VBArray( AFL( name ).toArray();
}

myJScriptArray = GetArray( "close" );
%>

The GetArray() function shown above makes it easy to convert automation-type safe array into JScript array. This example shows also how to define and use functions in JScript;

Assigning AFL variables from script-side arrays is much more simple, AFL scripting host detects JScript arrays and can get their contents directly:

// example in JScript
<%
AFL("buy") = myJScriptBuyArray;
%>

All other data types are handled the same in JScript and VBScript

// example in VBScript
ticker = name();
<%
tickerstring = AFL("ticker")
AFL("ticker") = "new name"
%>

or in JScript:

// example in JScript
ticker = name();
<%
tickerstring = AFL("ticker");
AFL("ticker") = "new name";
%>

Iterating through arrays

One of the most basic task that everyone would probably do is to iterate through array. In VBScript this can be done using For..To..Next statement, in JScript using for(;;) statement. Both these constructs need to know array size or number of elements in the array. In VBScript you should use UBound( arrary) function to get the upper bound of the array, in JScript you just use length property of the array. The following examples show this. (Please remember that in both VBScript and JScript arrays are zero-based.)

// example in VBScript
<%
myArray = AFL("close")

sum = 0

for i = 0 to UBound( myArray )

sum = sum + myArray( i )

next

%>

or in JScript:

// example in JScript
<%
function GetArray( name )
{
return VBArray( AFL( name ).toArray();
}

myArray = GetArray( "close" );

sum = 0;

for( i = 0; i < myArray.length; i++ )
{
sum += myArray[ i ];
}

%>

Examples

a) Indicator example - Exponential moving average:

EnableScript("jscript");
<%
close = VBArray( AFL( "close" ) ).toArray();

output = new Array();

// initialize first element
output[ 0 ] = close[ 0 ];

// perform the loop that calculates exponential moving average
factor = 0.05;
for( i = 1; i < close.length; i++ )
{
output[ i ] = factor * close[ i ] + (1 - factor) * output[ i - 1 ];
}


AFL.Var("graph0") = close;
AFL.Var("graph1") = output;


%>
WriteVal( graph1 );

 

b) Profit-target stop example

Here comes the example of the formula that realizes profit-target stop at the fixed 10% percentage from the buy price. Note that buy condition is met when the price reaches a new high, so it happens multiple times after initial buy. Therefore ValueWhen( buy, close ) can not give you initial buy price and that kind of trading rule could not be implemented in AFL itself. But, with scripting there is no problem...

EnableScript("VBScript");

hh = HHV( close, 250 );

buy = Close == HHV( close, 250 ); // buy when prices reaches a new high
sell = buy; // ensure that sell is an array, sell = 0 would set the type to number

<%
close = AFL("close")
buy = AFL( "buy" )
sell = AFL("sell")

' this variable holds last buying price
' if it is zero it means that no trade is open
lastbuyprice = 0

' iterate along the array
for i = 0 to UBound( close )
sell( i ) = 0

' Remove Buy signals if trade was already initiated
if( lastbuyprice > 0 ) then
buy( i ) = 0
end if

' if there is no open trade and buy signal occurs get the buying price
if ( lastbuyprice = 0 ) AND (buy( i ) = 1) then
lastbuyprice = close( i )
end if

' if trade is open and sell condition is valid - generate sell signal
' and close the trade
if (lastbuyprice >0 ) AND ( close( i ) > ( 1.1 * lastbuyprice ) ) then
sell( i ) = 1
lastbuyprice = 0
end if
next

AFL("buy") = buy
AFL("sell") = sell

%>

buy = buy;

Further information

In case of any further questions, comments and suggestions please contact me at: tj@amibroker.com . Please note that AFL scripting is fairly advanced topic and you should play a little bit with AFL first before going too deep into scripting.


Microsoft, ActiveX, JScript, VBScript, Internet Explorer, MSDN, Windows, Windows NT, Win32, and Win32s are either registered trademarks or trademarks of Microsoft Corporation in the U.S.A. and/or other countries.