IMPORTANT NOTE: Since the introduction of native looping and flow control statements like if-else and while in version 4.40 the significance of scripting has been greatly reduced. Currently most of the tasks requiring scripting in previous versions could be handled in native AFL. What's more AFL loops are 3-6 times faster than JScript/VBScript.
AFL scripting host is an interface between AFL engine and JScript/VBScript engines (aka. Active Scripting technologies) available as a part of Internet Tools & Technologies platform provided by Microsoft.
It allows you to build the formulas that are have parts in AFL code and parts in JScript/VBScript.
Microsoft JScript/VBScript engines come installed with Windows.
JScript/VBScript documentation can be found on official scripting page at:
http://msdn.microsoft.com/scripting/
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 when prices reaches a new high buy = Close == HHV( close, 250 ); // ensure that sell is an array, // sell = 0 would set the type to number
sell = buy;
<% 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;
More scripting samples are available at the AFL on-line library at: http://www.amibroker.com/library/list.php
In case of any further questions, comments and suggestions please use customer support page at http://www.amibroker.com/support.html . 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.