The Amibroker custom backtester interface provides three levels of user customization, simply called high-level, mid-level, and low-level. 1 Advanced users’ workshop: Custom Backtester Interface 4/19/ Advanced users’ workshop: Custom Backtester Interface by Tomasz Janeczko, Amibroker. 1 Topographic Surface Anatomy. STUDY AIMS. At the end of your study, you should be able to: Identify the key landmarks.
|Published (Last):||20 April 2009|
|PDF File Size:||18.58 Mb|
|ePub File Size:||17.46 Mb|
|Price:||Free* [*Free Regsitration Required]|
AmiBroker tends to refer to this as the Advanced Portfolio Backtester Interface, but as it seems to be more widely referred to as the Custom Backtester Interface, I interfaxe use this latter terminology. Due to the object model used by the backtester interface, a higher level of programming knowledge is required than for simple AFL or looping.
This document starts by discussing that model, so is aimed at AFL programmers who are already proficient and comfortable with basic AFL use, array cusom, and looping. The modern programming paradigm is called object-oriented programming, with the system being developed modelled as a set of objects that interact. The custom backtester interface follows that model. Interfaace object can be thought of as a self-contained black-box that has certain properties and can perform certain functions.
The private code and variables are totally hidden from the outside world and are of no interest to users of the object. Only developers working on the object itself care about them.
Document – AmiBroker’s Custom Backtester Interface | Aussie Stock Forums
Users of the object are only interested in the code and variables made accessible for their use. Properties can be read and written much the same as any other variable, just by using them in expressions and assigning values to them although some properties may be read-only.
These functions are called methods of the object. They are essentially identical to ordinary functions, but perform operations that are relevant to the purpose of the object.
For example, the Backtester object has methods functions that perform operations related to backtesting. Methods are called in much the same way as other functions, but again the syntax is a little different due to them being methods of an object rather than ordinary functions.
The aim of the object model is to view the application as a set of self-contained and reusable objects that can manage their own functionality and provide interfaces for other objects and code to use.
Each of those components manages its own functionality and provides you with a set of connectors and cables to join them all together to create the final application: Similarly, software objects have standard interfaces in the form of methods and properties that allow them to be used and reused in any software. To access the properties and methods of an object, you need to know not only the name of the property or method, but also the name of the object.
To use real AFL examples, the first object detailed in the help is the Backtester object. AmiBroker provides a single Backtester object to perform backtests.
AmiBroker Users’ Knowledge Base » AmiBroker Custom Backtester Interface
To use the Backtester object, you first have to get a copy of it and assign that to your own variable:. Now that you have the Backtester object in your own variable, you can access its properties and methods. From this you can see the advantage of keeping object variable baktester short. If a property is read-only, then you cannot perform any operation that would change its value. So, using the Equity interace which is read-only: The same syntax is used to access the methods of an object.
The method name is preceded by the object name with a decimal point: Any parameters are passed to the method in the same manner as to ordinary functions:. A good guess would be that it returns True if the custom metric was successfully added and False if for some reason it failed to be added. Another example with a return parameter: In other words, it holds a Signal object rather than backtesster Backtester object.
Unlike the single Backtester object, AmiBroker can have many different Signal objects created at the same time one for each trading signal. Note that the property sig. PosScore is a single number, not an array. PosScore is the position score value for that bar only, thus a single number.
Also note that AmiBroker help is not very clear on some topics. For example, the Signal object only has a few methods that indicate whether the current bar contains an entry, exit, long, or short signal, or has a scale in or out signal. For example, how do you tell the difference between a scale-in and a scale-out?
Fortunately for this specific example, the Signal object also has a property called Type that indicates exactly what type the signal is.
To use your own custom backtest procedure, you first need to tell AmiBroker that you will be doing so. There are a few ways of doing this: By setting a path to the file holding the procedure in the Automatic Analysis Settings Portfolio page. This option will be used throughout the rest of this document. And finally, before anything else can be done, a copy of the Backtester object is needed: Or, if the same values were specified in the Automatic Analysis settings, the two lines above would not be needed in your AFL code at all, and the procedure would be in the specified file.
The AmiBroker custom backtester interface provides three levels of user customisation, simply called high-level, mid-level, and low-level. The high-level approach requires the least programming knowledge, and the low-level approach the most. These levels are just a convenient way of grouping together methods that can and need to be called for a customisation to work, and conversely indicate which methods cannot be called in the same customisation because their functionality conflicts.
Some methods can be called at all levels, others only at higher levels, and others only at lower levels. AmiBroker help details which levels each method can be used with.
It simply allows custom metrics to be defined for the backtester results display, and trade statistics and metrics to be calculated and examined. AmiBroker help has an example of using the high level interface to add a custom metric.
In essence, the steps are:. As some positions may still be open at the end of the backtest, you may need to iterate through both the closed trade and open position lists:. As with the Signal object, AmiBroker can have many Trade objects created at the same time, one for each closed or open trade. The first for loop iterates through the closed trade list, and the second through the open position trade list.
However, any conditional involving a null value is always false, so this will still work.
Instead they call a Backtester object method to get the initial value the first Trade object and then another member to get the next value the next Trade object. So the for loop conditions here are just saying start from the first Trade object, at the end of each pass get the next Trade object, and keep doing that until there are no more Trade objects ie.
The loops are iterating through the list of intertace, not the bars on a chart. Each Trade object holds the details for a single trade. The average backtseter the total number of days winning trades were held divided by the total number of winning trades. For the trade details, the Trade object has the following properties: If trial and error proves that not to be the case, then we could alternatively try using the Trade object properties EntryPrice, ExitPrice, and IsLong to determine if it was a winning or losing trade.
As it turns out upon testing, GetProfit does in fact work as expected. Note that the Trade object also has a property called BarsInTrade, which looks like it could potentially be used instead of the dates, but that only gives the number of bars, not the number of calendar days.
Amibroker Custom Backtester: Step by Step Tutorial
So, to get the number of calendar days spent in a trade, we call our DayCount function passing the entry and exit dates: Note that we only need to consider closed trades in this example, as counting open positions would not accurately reflect the number of days trades were typically held for.
And if we run an optimisation using a different backtest to aboveit will have a column near the right-hand end of the results:. For this, the metric is added to each Trade object rather than the Backtester object and the trades are listed at the end of the procedure.
For example, to display the entry position score value against each trade in the backtester results, the following code could be used:. The first for loop iterates through the closed trade list and the second through the open position list amihroker get the entry score knterface for every trade listed in the results. Note that the bo. As another example, say we want to list for intsrface winning trade how far above or below the average winning profit it was as a percentage, and similarly for each losing backtfster, how far above or below the average loss it was as a percentage.
Relative loss percentages are displayed as negative numbers. To be backester to modify actual backtest behaviour, the mid-level or low-level interfaces must be used. Essentially this means using Signal objects as well as the Backtester object.
Amibrokrr the mid-level interface, each trading signal at intefface bar can be examined and the properties of the signals changed, based on the value of other Cjstom or Backtester object properties, before any trades are executed for that bar. The custom backtester interface template for a mid-level approach, where all the signals at each bar need to be examined, is:.
As with the Trade object in the earlier example, the inner for loop iterates through the list of signals at each bar, not through all bars on a chart. The for loop conditions are effectively saying start from the first Signal object for the current bar, at the end of each pass get the next Signal object for the same bar, and keep doing that until there are no more Signal objects for the bar ie.
Each Signal object holds the details of one signal at the current bar ie. The main differences between the mid-level and high-level approaches are: A loop is required to iterate through all bars of the chart. A nested loop is backyester inside that one to amibrkker through all the signals at each of those bars. However, since the backtester at this level is not run in the context of a particular symbol, the data must be saved to a composite symbol in the main code or perhaps a static variable and referenced in the custom backtest procedure with the Foreign function.
For example, in the main AFL code:. Here the volume EMA array is saved to a separate composite symbol for each stock ie. For this to work in backtests, the atcFlagEnableInBacktest flag must be used.
Custom Backtester Interface – AmiBroker
Then in the custom backtest procedure:. The statement if sig. IsLong calls the two Signal object methods IsEntry and IsLong to determine if the current signal interfzce an entry signal and a long signal ie. As this is not a read-only property, it can be both read and modified. In this example, as each new scale-in signal is detected, the list of open positions is checked for an open position in the same stock as the new signal.
The backtestdr combines use of the Backtester object, Signal objects and Trade objects to determine whether or not scale-in of a position should be permitted. Note that the Trade object is returned Null if no open position is found. As any comparison with a null value is always backktester, provided the test is for the True condition then the IsNull function is not needed: However, if the test is for the negative condition, IsNull is required: The low-level interface provides the most flexibility to control backtester operation.