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 (a.k.a. Active Scripting technologies) available as part of the Internet Tools & Technologies platform provided by Microsoft.
It allows you to build formulas that 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 the official scripting page at:
http://msdn.microsoft.com/scripting/
If you want to use scripts within your formulas, you have to call EnableScript() function
at 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 beginning 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 information between the "normal" AFL part and the 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) parameterized 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 variableAFL.Var("buy") = buyarrayfromscript ' set the buy array in AFL from the script-defined variable%>
Since Var is a 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 variableAFL("buy") = buyarrayfromscript ' sets the buy array in AFL from the script-defined variable%>In AFL there are three possible data types: array (of floating point numbers), a number (floating point) and a string. The VBScript and JScript engines use a variant data type that can hold any type of variable, including the three used by AFL. As in AFL, you don't declare variables in scripting languages; the type is determined by the first assignment. In the 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 properties of an array object) you need to use the following code to get the value of an AFL array into a 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 an automation-type safe array into a JScript array. This example also shows how to define and use functions in JScript.
Assigning AFL variables from script-side arrays is much simpler; 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 way 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 tasks that everyone would probably do is to iterate through an array. In VBScript, this can be done using For..To..Next statement; in JScript, using for(;;) statement. Both these constructs need to know the array size or number of elements in the array. In VBScript, you should use UBound( array) function to get the upper bound of the array; in JScript, you just use the 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 = 0for 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 a profit-target stop at a fixed 10% from the buy price. Note that a buy condition is met when the price reaches a new high, so it happens multiple times after an initial buy. Therefore ValueWhen( buy, close ) cannot give you the 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 numbersell = 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 nextAFL("buy") = buy AFL("sell") = sell%>buy = buy;
More scripting samples are available at the AFL online library at: http://www.amibroker.com/library/list.php
In case of any further questions, comments, and suggestions, please use the customer support page at http://www.amibroker.com/support.html. Please note that AFL scripting is a fairly advanced topic and you should play a little with AFL first before going too deep into scripting.