This action might not be possible to undo. Are you sure you want to continue?
Personal ramblings, muses, tips and notes on becoming familiar with the Amibroker Backtester
This document is a personal aide de memoire and not designed to replace the User Manual or Help files which can be consulted at all times. No attempt has been made to be exhaustive or complete
Abbreviations: AA = Automatic Analysis; AB = Amibroker; AFL = Amibroker Formula Language; CCY1 = First Currency of Pair; CCY2 = Second Currency of a Pair; FX = Foreign Exchange; GUI = Graphic User Interface; PnL = Profit and Loss; TJ = Tomasz Janeczko, creator of Amibroker; USD = United States Dollar
Introduction In attempt to get to grips with what the backtester does, and how it does it, I have recorded some notes here together in one document for future reference, which may be of use to others. Having done this I am at last somewhat more comfortable with the prospect of making some sense of results of backtests, rather than just running some buy and sell conditions and wondering if I could believe the results, not because of any fault of Amibroker, but through ignorance on my own part as to how I could control what was happening under the bonnet as it were. This document is aimed at being one stop shop for me to come back to any time in the future, and may be of some use to other people new to the Amibroker backtester. I make no attempt to get involved with more advanced concepts such as the Custom Backtester interface, which has been covered elsewhere, rotational trading (fund switching) and no attempt at system creation or money management. GETTING STARTED When we just enter some simple code into the AA window:
Buy = Cross( Close, EMA(Close,45)); Sell = Cross( EMA(Close, 45), Close);
and then click Back Test we should expect to get some results. Therefore FIRST basic issue is we NEED buy and sell conditions, and the backtester should run. If it does not run, there are other issues in the settings or AFL that are incorrect, such as insufficient funds, too big a position size, or not enough information for AFL to use in its calculations. A discussion of these follows. For FX there are specific settings, which we will discuss later in the Forex section. SETTINGS CONUNDRUMS We can backtest in one of three ways: one ticker at a time: Just select Apply to Current Symbol or do an individual Backtest which can be run on a watch list or the whole database. This runs the buy sell code per ticker, i.e. it runs through Ticker#1 and applies all the buy sell signals, then moves to Ticker#2 and so on. This can be useful to see which Ticker a given set of Buy Sell signals works best for.
Page 2 of 27
Or we can do a Portfolio backtest which emulates real trading conditions more accurately. Here AB looks at all the tickers in the Watch list and bases entries and exits not only according to coded buy/sell signals but also according to other rules (such as Money Management rules, and Preferred Ticker filter). So for example we can tell AB to only use a given percent of capital per trade, we can limit the number of open positions, and so on. More importantly, to make the best use of the Portfolio backtester we can tell AB which ticker to select if there are more than one buy candidates, based on user preferences. So if there are 10 Buy candidates, but only enough funds for two, which should AB choose? This is set with PositionScore. (If this is not set, then AB just chooses the available tickers alphabetically). This function can be used for example to tell AB to select in order of lower priced tickers, or volume or volatility etc. Portfolio level backtesting therefore refers to position sizing based on the current equity value of your account. We can trade more than one ticker at a time. To effect this in Amibroker we need to define TWO things: a. the maximum number of open positions. MaxOpenPositions in the AFL overrides the SETTINGS GUI b. the PositionSize variable in the AFL If we set Current Symbol in Automatic Analysis then Individual backtest gives the same results as Portfolio level backtester. If we select All Symbols or Use Filter selection, then Backtest by default is portfolio level one. Else if we click Individual backtest it goes through each ticker one by one. So for most purposes we should just use the Back Test button, which defaults to Portfolio level backtesting, and we need to set the rules up correctly. If we are trading Current symbol it will default to the current symbol. AFL SETTINGS Let us go through the available backtest settings and see what we can do with them. The settings can be placed in one of a number of places. 1. The Backtest Settings GUI window. (Go to Analysis, Automatic Analysis, Settings) 2. The AFL code used for the Backtest (Enter code into the AFL editor) 3. Specific data related to the Ticker involved, as defined in Symbol, Information menu. Some Some Some Some Some settings can only settings can only can be set in AFL can be set in AFL can be set in AFL be set in AFL. be set in the Settings window. and the Settings window. and Information window. and Information window and the Settings window.
In addition, once we have run a backtest we can view the trades in the Results part of the AA, but we can also view the settings we used, by clicking the Report, Settings link. These are saved with the report in the directory Program Files\Amibroker\ Reports and can be viewed from Report, View Last Report or Report, Report
// exactly equal to.0). // Set this to zero to show only the results of the actual trades and not interest accrued. for easy reference when you review them later. // According to TJ this is only needed if you use dll files or other script. //can be any length but no punctuation is to be included. SetOption(“CommissionMode”. T’WOULD BE GOOD TO HAVE THE ABILITY TO SET THIS IN THE AFL. // or whatever settings we need: These OVERRIDE the Settings tab PositionSize = 1000. // does not appear in Settings GUI.0). SetFormulaName("TemplateBTShares"). // replaces the above with more advanced features. If not defined in AFL // then full equity is used for each trade. // exactly equal to.1. Let’s go through some (most) of the settings one by one and then create a summary table. // Note also that the first figure references past bars. 15). AB looks for this First in the Backtester SETTINGS Graphics User Interface (GUI) // then looks for it in the AFL code. the Settings Value SetOption(“CommissionAmount”. Timeframeset(InDaily). SetOption(“InitialEquity”. // SO THE TIMEFRAMESET HAS TO BE SET IN THE SETTINGS WINDOW and is not something we can // code for in the AFL. Note. See the help files. It gives precedence to the setting in the AFL code. // use this for most backtests. // therefore the second parameter needs to be set to zero. BUT: This cannot be done from AFL: see TJ’s response in post #114929 of the Yahoo Groups Amibroker user group. but OVERRIDES. SetBarsRequired(10000. in my testing the AFL setting // is given predominance. that not all of the settings are stored in this Report Settings location. but OVERRIDES.0.Page 3 of 27 Explorer. We have to have this defined in one of these // places. this is the default: redundant signals are removed. method). SetBackTestMode(Regular). Although the // advice given by TJ in the past is to set this to the same value in both places.10000).0). // does not override the Settings Inweekly. however. // the second parameter references future bars so if this is greater than zero.0). SetPositionSize(value . SetOption(“InterestRate”. // this OVERRIDES the Settings value. This helps to identify systems or versions of systems. Therefore must be set in AFL. we will get a Check: // references future bars error. // If you only use pure AFL this is not needed. . the Settings value SetTradeDelays(1. // to accurately assess your system.
// if we want to buy shares in multiples of 100. not if we // only select one symbol. // As per help files use 1 for shares and futures. Don’t see any reason at the moment // to set this to false. Settings can be made Globally (in SETTINGS) or per symbol. we set this 100 and so on.. If we do not use // Applystops.3). Mainly of use therefore in conjunction with Applystops to make sure // entries and exits take place at allowed true prices and not fictitious calculated levels. // Only works with portfolio level Backtester if we choose Apply to All symbols. Leave True. SetOption(“PriceBoundChecking”.).True). // AFL overrides SETTINGS. . // This setting is not entirely consistent with the rules of AFL overriding most of the settings. SetOption("MinShares". or use fractions for mutual funds. AFL overrides SETTINGS. The only // correct place to set this is in the SETTINGS GUI. but I am sure others may see a need for this. // defaults to the Trade list. TickSize = 0. I see no reason at present to change this.Page 4 of 27 setOptions(“MaxOpenPositions”. // See also TickSize under the Forex section for further details. // TickSize is a special case.True). // if we set this 0 (zero) backtester will buy fractions of shares.0). // changing this on its own makes no difference to the trade results. This controls the column title (Contracts or Shares) and // the way the profit is calculated. SetOption(“FuturesMode”. SetOption(“PortfolioReportMode”.0). i. // AFL setting OVERRRIDES the Settings in GUI.01. // Advice: Do not try and set this in the AFL. // Per symbol setting overrides global values in SETTINGS GUI // AFL overrides SETTINGS. in AFL we .True). SetOption(“AllowSameBarExit”. // 1 is needed for shares to ensure we do not buy fractional shares. we should not need to specify TickSize. The AFL OVERRIDES the Settings window value. // overrides SETTINGS: defines minimal dollar value of desired position SetOption("UsePrevBarEquityForPosSizing". // Can only be set in AFL. // needs to be False for shares.e. 500). If we use the AFL to set this to ON. // if we want to buy shares in parcels of multiples of 10. RoundLotSize =1. then for Shares database and shares // code. but do not override // the BuyPrice or SellPrice arrays. and set to True for Futures and Forex backtesting // We need to set this in SETTINGS GUI. // overrides SETTINGS: defines minimal number of shares that can be bought SetOption("MinPosValue". This must be used in conjunction with // PositionSize. it will change the way the calculation is done but will not change the Column header from Shares // to Contracts. If we are to use the SetOption(“FuturesMode”.1). // Set to False to use current equity for Position Sizing. set this 10. or Use Filter.
// the highest absolute value gets selected first. // This does three things: // a. This is controlled from the Settings but overridden by AFL. the calculations at least will be correct but the column header // will not be: the lesser of two evils. and then run a shares backtest with // SetOption(“FuturesMode”. Settings that be set in more than one place in Amibroker SETTINGS THAT CAN BE SET IN MORE THAN ONE PLACE “InitialEquity” SETTINGS GUI AB looks at Settings first SYMBOL INFORMATION N/a AFL Code Then AB looks for AFL value: Precedence Given to AFL value Appears in Report ? Formula and . under Analysis. General and (de)selecting the tick box. // Therefore to get correct calculations. SUMMARY OF SETTINGS So to summarize the available settings: Settings that can only be set in AFL SETTINGS THAT CAN ONLY BE SET IN AFL SetBarsRequired(10000. SetOption(“AccountMargin”.1) PositionScore Can be set in AFL ? Yes Yes Yes Yes Yes Yes Can be set Elsewhere ? No No No No No No Appears in Report ? Yes Yes Yes Yes Yes Yes under Formula Under Formula Under Formula Under Formula only in Formula only in Formula Table 1. the backtest column header is CONTRACTS. // This is best set in the SETTINGS GUI. Settings.0) SetFormulaName(“Name”) SetBackTestMode(Regular) PositionSize SetOption(“PriceBoundChecking”. we want to leave this at 100 // can be set in SETTINGS or AFL. Changes the output to Report. so this code means those tickers with the lowest RSI() // PositionScore = 1 / C. when OFF the header is SHARES // This is controlled from Settings. If we wish to add this to the AFL we can use this as a reminder to // ourselves to ALSO make the correct switch in SETTINGS GUI. // This all seems convoluted but is probably by design.Page 5 of 27 // use this as a reminder to ourselves to switch the SETTINGS GUI tick box to the correct value.100). so that if we leave an FX database and open a shares // database and leave the Futures Mode tick box checked. Settings window. The reverse also applies. // to see what this does. False) in the AFL. When ON. PositionScore = 100 – RSI(). // for shares traded with no leverage. would select the tickers with the lowest price first. // the AFL value is read into the backtester report settings window. column header and Report Settings output we should restrict // ourselves to the SETTINGS GUI. c. see the Forex section. // AFL settings OVERRIDE the GUI settings. This is primarily // // // controlled from Settings but can be overridden with AFL setting. // b. Changes the way AB backtester does its calculations for profit and loss.
In Formula. Formula Settings (can be wrong value if overridde n by) AFL value in Formulas Only in Formula In Formula + also in Settings. If set this overrides Then AB looks here . Settings “AccountMargin” AB looks at Settings first N/a Then AB looks for AFL value Given to the AFL value MarginDeposit = RoundLotsize = N/a AB looks at Settings first Symbol Info Then it looks at Per symbol info Then AB looks for AFL value Then AB looks for AFL value Given to the AFL value Given to the AFL value “PortfolioReportMode” “FuturesMode” Special case: Set in SETTINGS alone OR in both SETTINGS and AFL must match. This is a Then AB looks here. The AFL value is shown in Report Settings.Page 6 of 27 “CommissionMode” “CommissionAmount” SetTradeDelays “MaxOpenPositions” “MinShares” “MinPosValue” "UsePrevBarEquityForPosSizi ng" “AllowSameBarExit” “AllowPositionShrinking” “InterestRate” AB looks at Settings first AB looks at Settings first AB looks at Settings first AB looks at Settings first AB looks at Settings first AB looks at Settings first AB looks at Settings first AB looks at Settings first AB looks at Settings first AB looks at Settings first N/a N/a N/a N/a N/a N/a N/a N/a N/a N/a this takes precedence over the other two Then AB looks for AFL value Then AB looks for AFL value. Formula and settings but displays the value from the AFL Formula. Ticksize AB looks at Settings First AB looks in settings first N/a N/a Then looks for AFL value Then looks to AFL Given to the AFL value Calculation s given preference to the AFL value Given to the AFL value for AB looks here first. Formula only. Then AB looks for AFL value Then AB looks for AFL value Then AB looks for AFL value Then AB looks for AFL value Then AB looks for AFL value Then AB looks for AFL value Then AB looks for AFL value Then AB looks for AFL value Settings Given to AFL value Given to the AFL value Given to the AFL value Given to the AFL value Given to the AFL value Given to the AFL value Given to the AFL value Given to the AFL value Given to the AFL value Given to the AFL value Formula and Settings Formula and Settings Formula and Settings Formula only Formula only Formula only Formula only Formula only.
Long. Controls over the EXITS We can control our exits in one of two ways. Short or Long and Short. AB provides us more flexibility in setting the exits by use of stops. There are in-built stops which we can set via the Settings GUI and there are Applystops which we code up in AFL. 1.Page 7 of 27 global “default” value the Global value calculations only read from the Global value. they do NOT show up correctly in the Records. Addcolumn(GetOption(“MinPosValue”). Settings page. In addition. FIRST.”MinPos”. Controls over ENTRIES Entries depend on the Buy conditions and are coded up in AFL in the AA window. [Note that although these values work in the Backtester.g. which gives us the ability to use Param and Optimize functions on these. This document does not cover AFL or system design and so no more will be said here. In addition the setting for StopTypeNBar does not appear in the Report. we can use the Applystops in the actual AFL. you need to go to Settings and Select Positions. These values will show up in the Backtester report page for Settings. SECOND. They perform the same task. The last thing to be said about these is that if need be we can create an exploration to display all of these settings using the GetOption function e. Table 2.0). We can use the Sell Condition as coded in AFL 2. Settings that can NOT be set in AFL These can NOT be set in AFL Periodicity Positions: Long or Short Can be set in AFL ? No No Set Where SETTINGS GUI SETTINGS GUI Table 3. and they override the values set in the SETTINGS window. or at least I have not found a way to get them to do that. we can use the built-in stops from the GUI in the Backtester Settings. Positions Long or Short does not have an AFL switch but is obviously controlled by the Buy and Sell rules. So for all Backtests there will be some settings that need to be set via the SETTINGS GUI and some that can be set with the AFL.6. That way you can separate out the two to assess the results of the Long trades and Short trades independently. . These are self explanatory and can be looked up in the help files. However if you have Long and Short conditions in your code.
simulating real trading. ExitAtStop. the exit for the StopTypeLoss is controlled by the AFL. StopTypePoint: control passes to the AFL StopTypeLoss: Amount. From tests we can show that: StopTypeLoss: StopModeDisable. then whichever one gets hit first will be enacted by AB. if we have different types of stops in the SETTINGS GUI and the AFL.Page 8 of 27 Settings link. and no other stops. where we coded StopTypeLoss in both the AFL and SETTINGS GUI. together with N-bar stop in the SETTINGS GUI. However. unless the N-bar stop gets hit first. Fig 1. So for the situation in Fig 2. in which case this exit gets taken. StopTypePercent. StopTypePoint: control passes to the AFL StopTypeProfit: Amount. .] Applystops The functions and commands of the Applystops can be obtained from the help files. and ReEntryDelay: control passes to the AFL StopTypeNBar: Amount (N-Bar exit ) and ReEntryDelay: control passes to the AFL. Moreover the pattern is the same: the AFL code for any one type of stop overrides the Settings GUI. So if we have StopTypeLoss set in the AFL and StopTypeLoss set in the SETTINGS GUI. StopTypePercent. and ReEntryDelay: control passes to the AFL StopTypeProfit: StopModeDisable. So we see that ALL the individual ApplyStop parameters in the AFL will override those in the SETTINGS GUI. then control over the exits passes to the AFL code. ExitAtStop.
or the SETTINGS GUI. Using the AFL allows more control and flexibility. although these are the ones used by the backtester. To avoid any confusion we may choose to set the stops in either the AFL. This may look something like the following. Remember to set ExitAtStop correctly to suit your trading plan. we can use all of the necessary AFL commands before our actual systems code.] Sample Code Now that we have defined all or most of the settings that we need to get accurate backtest results. Ya Haf Ta Go To SETTINGS.// removes redundant signals .afl ChrisB Jan 2008 You can NOT select the Time Period here. EVEN IF they are disabled. the Backtester Report Settings link seems to read the values from the SETTINGS table. OR if they are enabled.//Set this in each new backtest code: can be any length but no punctuation SetBacktestMode(backtestRegular). SetFormulaName("SharesUnNamed"). // // // // // Template BT Shares.Page 9 of 27 Fig 2. It will not show the AFL coded Applystops. [As an aside. So if we need to read the ApplyStop Amounts in the Report Settings window then we would need to have these entered in the SETTINGS window. especially if we are looking at Optimizing the amount parameter.
True).// False to use current equity for Pos Sizing SetOption("PriceBoundChecking".// Always set to True.No output To save time and coding we can save this as a Template file. SetOption("HoldMinBars".False).0. 500).//overrides SETTINGS SetOption("CommissionMode". SellPrice.//Overrides SETTINGS SetOption("FuturesMode". 2.//overrides SETTINGS.//overrides SETTINGS PositionSize = 1000. we need to tell AB backtester at what prices to open and close these trades. 50 = for 50% margin //NOT the same as MarginDeposit for futures.Page 10 of 27 SetBarsRequired(10000.// disables exits for this number of Calendar days //exits SetOption("ReverseSignalForcesExit".10000). Template_BT_Shares.// only needed if you use dlls or external script SetOption("InitialEquity". SETTING THE PRICES AT THE BUY AND SELL Once we have defined our rules for entries and exits. and then just use the following code at the beginning of all our backtest files #pragma nocache #include <Template_BT_Shares. // 3.0). SetOption("AccountMargin". Not needed if // you enter on Close SetOption("InterestRate". .Detailed Log.//overrides SETTINGS. (and ShortPrice and CoverPrice for short positions).0).//overrides SETTINGS //0 = Commision Table .afl in the chosen directory (by default C:\Program Files\Amibroker\Formulas\Include). SetOption("MaxOpenPositions".// POSITIVE = dollars.1. 2 = $ per trade.//False for Shares.0). defines minimal shares to be bought SetOption("MinPosValue".//True for stop and reverse systems SetOption("AllowSameBarExit".95). 1 = percent . If this is left out it defaults to the SETTINGS values.True).0).// disables exits for this number of bars SetOption("HoldMinDays". used dollar value for Shares.afl> This will run the above settings from the named file and then we can concentrate only on coding up the system. //overrides the SETTINGS //only works for Portfolio level testing with > 1 symbol SetOption("MinShares". Once again the AFL values OVERRIDE the SETTINGS values. To do this we define BuyPrice.// Needed if you enter on Open.19.//Must be used with PositionSize. e.0).True). 3 = $ per share/contract SetOption("CommissionAmount".//Use True as default.//overrides SETTINGS SetOption("AllowPositionShrinking".g.2). use default of 1 for shares. BuyPrice = SellPrice = ShortPrice = CoverPrice = 0pen.// 0-Trade list: 1. //in case there is not enough cash SetOption("UsePrevBarEquityForPosSizing". True). DELAYS Based on our trading system we should next aim to define WHEN Amibroker simulates the Buy and Sell orders: we can do so in the SETTINGS Trades GUI. True for FX: // Set also in SETTINGS GUI.1).//100 = no margin for shares. SetTradeDelays(1. We can do this in the SETTINGS Trades Tab but also from the AFL.2).// overrides SETTINGS.3.False). //reports SetOption("PortfolioReportMode". 3). to allow this SetOption("ActivateStopsImmediately".100). NEGATIVE = Percent // CANNOT be set in SETTINGS RoundLotSize = 1.True).Summary.
30) . or can they display on our own charts that we have code up in Formula Editor? The arrows will display on Any or All charts if a. In the Backtest results list.-1) . Sell. No. Or … b. Show trading arrows. select Axes and Grids. Method 2. we have run the backtester and our settings are correct or realistic b. (For Shorts the entry is a hollow red down arrow. Separating out the buysignal and the buy. There are two ways we can do this: Method 1. Axes and Grids. Show trading arrows (or SetChartOptions(0. Show trading arrows. on the Price chart (or any other indicator chart) right click. Show arrows for all raw Signals. We can for example use delays of Buy. Show current trade arrows. S e c o n d l y . Sell. We can do this in one of two ways: a.0). Buy = Ref(Buysignal. now called formula editor) use SetChartOptions(0. This can be toggled off by going to the chart. when and at what level the buy signals. to show the inbuilt buy and sell signals on the charts we need to enable the chart settings to show arrows. or b. and sell arrow as Red Down Arrow. Cover or Short arrows on the Price Chart. choose Yes. This tells AB we want to see the trading arrows on the Charts.0. for example: Buysignal = Cross( EMA(C. right click. Or we can leave these set to 0 as in SetTradeDelays(0. So Firstly.Page 11 of 27 or in AFL. Close). w e c a n c o d e u p s o m e a r r o w s ( o r D i g i t s ) o n t h e C h a r t s using the PlotShapes function. meaning we effect these trades on the bar (day) after the signal. This sets the chart default to show Trade Arrows. entries and exits occurred. The desired arrows will then appear in their correct place on the charts. when you create code for a chart (as in indicator builder. w e need to be able to check on the charts where. Param.ChartShowArrows). . the AFL values used with SetTradeDelays OVERRIDE the SETTINGS values. we can then right click the Results list and select a.0. allows us to be better able to plot these signals and entries on the chart for visual confirmation (see next section) Once again. Show arrows for actual trades. AB displays Buy signal as lime green up arrow.ChartShowArrows) is enabled. and the Cover is hollow lime green up arrow) Do the arrows show only on native AB charts. T h e f i r s t w a y i s t o u s e t h e i n b u i l t f e a t u r e o f A B t o d i s p l a y t h e B u y . CHECKING THE SIGNALS ON THE CHARTS In o r d e r t o c h e c k t h a t o u r c o d e i s t e l l i n g A B t o d o w h a t w e e x p e c t i t t o . trades were actually taken c. or c. Short and Cover equal to 1. and then use Ref function to tell AB to take the trade on the next bar(day).
2. go to the Reports list and select which arrows we wish to see. The Equity(1) has the purpose of looking back at the type of exit that was taken . the in-built exit arrow in AB does not tell us why an exit was taken. Which Exit? How then do we know why any one exit was taken? When you look at the Backtest report you can easily see why any one position was closed: Fig 3. and is read by AB from stops set in AFL or via the SETTINGS GUI. we repeat the same: just making sure that Chart has Show trading arrows enabled. Buy Sell signals Applystops as needed. . This is the required sequence as per TJ: 1.e. equity(1).so that we can plot this on the charts using the PlotShapes function. the regular Sell command or which one of the ApplyStop functions. but just points to the bar where the exit occurred. Note these above details are for Buy and Sell orders AND for exits based on the Applystops. The type of stop that closed the position appears in brackets in the Trade column. i. 4. Then run backtest. PlotShapes. However if we wish to see on the charts which exit rule caused the position to close. If we were to add a new chart after running a Backtest. No extra coding is needed for AB to show an exit based on Applystops: however. So when we have coded exits based on one of a number of Applystops (perhaps together with a regular Sell signal) these will all be displayed as the regular exit arrows in the Chart when we select Show Arrows for actual trades. This is done by using the Equity(1) call and the PlotShapes function. then we need to use Method 2 by adding some extra code in the AFL.Page 12 of 27 On Price charts we just need to make sure the Show trading arrows is enabled for each chart. right click the reports list and select Show Arrows. 3.
56). // = 3 stopTypeTrailing. The Equity(1) function looks at the exits based on the inbuilt stops or ApplyStop to see which type of stop was used for the exit. 1 ). colorRed. // set color of the shape .10). 1 .1).0. If two or more different stops are triggered on the VERY SAME bar then they are evaluated in this fixed order: Fixed Ruin stop (loosing 99. 0. . Plot (C . stopModePoint. Plot (EMA(C. 0 . 0. Sell = Ref( Sellsignal. Remember that to view the inbuilt Buy and Sell arrows we need to Run the Backtester. we should make sure we do not have that layer * shapeDownArrow. // position referenced to the High * shapeDownArrow.96% of the starting capital) Max. loss stop Profit target stop Trailing stop N-bar stop Therefore to make things a little easier to decipher on the charts we can plot those as actual numbers using the ShapeDigitx function. 0 . according these rules: 2 3 4 5 6 = = = = = StopTypeLoss StopTypeProfit StopTypeTrailing StopTypeNBar “Ruin stop” Also from the help files.1).0). 1 ).L. ApplyStop ApplyStop ApplyStop ApplyStop ( ( ( ( stopTypeLoss.1). BuyPrice.5 . stopModePoint. To get the backtest arrows to match those we have plotted however. colorBlue. // to the selected layer ( if we than default. . 1 .-10). and allows these to be displayed on the chart (or in an Exploration). . Buysignal = Cross ( EMA (C. colorLime.// = 2 stopTypeProfit. Plot (EMA(C.Page 13 of 27 These are the rules for PlotShapes: PlotShapes( "reason" PlotShapes( "reason" PlotShapes( "reason" use // a layer other disabled) PlotShapes( "reason" PlotShapes( "reason" * shapeDownArrow. * shapeDownArrow. if more than one type of stop signal is received on the same bar. H. have Show arrows enabled on the Chart and then Right click the results list and choose Display Arrows. 0. we should not forget to run the backtest as well. stopModeBars. with the code looking like this: SetTradeDelays(0. PlotShapes ( Buysignal * shapeHollowUpArrow. Plot (EMA(C.9 . and can be displayed without having run the Backtest.200).-1).5). this is the order of precedence. 1 .colorBlue. -1) .30) ."" . PlotShapes ( Buy * shapeSmallCircle. colorRed. H. colorGreen. 0. colorRed.0.30). 1 ). // =4 stopTypeNBar. 64). // = 5 Equity(1). 0. * shapeDownArrow. colorRed. especially once we have adjusted the PlotShapes code or ApplyStop code. // say why to plot the shape . Close).0. colorBlack ."ema 30". Because the PlotShapes are plotted as an indicator they do so independently of the backtester. 0 . -10) // 10 pixels above the High.0). Sellsignal = Cross ( RSI(21). stopModePoint. Buy = Ref (Buysignal. "ema 5". . "ema 50". colorRed. . 1 . 0 .
PlotShapes( IIf(Sell==5. PlotShapes( IIf(Sell==4.SellPrice. shapeSmallCircle.0). shapeNone) .0).0.0. shapeDigit1.0.0). shapeNone). H.Page 14 of 27 PlotShapes( Sellsignal * shapeHollowDownArrow. [See also Help files for ShapePositionAbove. PlotShapes( IIf(Sell==2. shapeNone) . PlotShapes( IIf(Sell==1. shapeNone) . PlotShapes( IIf(Sell==4.0). 35).50). shapeSmallCircle. shapeSmallCircle.20). shapeNone) .H. PlotShapes( IIf(Sell==2. shapeDigit5.38). shapeSmallCircle. but when we use ShapeDigit we need offset of 30 to place the digit above the High. shapeNone) . colorRed. For all plotted shapes a positive value shifts the shape up and a negative value shifts the shape down. colorGreen. -25).H.H. colorRed. except for shapes with Down already in the name (such as shapeDownArrow. SellPrice. colorLime. shapeDigit2. PlotShapes( IIf(Sell==1. 0). colorBlack. colorRed. shapeDownTriangle etc) in which this is the other way around. shapeNone) .SellPrice. colorRed. 0 . colorRed. colorRed.H.SellPrice. 0 . The last value in the PlotShapes function refers to the offset.0. 0 . PlotShapes( IIf(Sell==3. when we use shapeDownArrow we need offset of –30 to place the arrow above the High. As explained in the help files.45). shapeDigit4. shapeDigit3. shapeNone) . colorLime. PlotShapes( IIf(Sell==5. H. SellPrice. shapeNone). shapeSmallCircle.0. PlotShapes( IIf(Sell==3. 0.0. shapeNone) .0. colorGreen.] .
AddColumn( Sell . with the small red circle at the Sell Price and above that the plotted shape to tell us the reason for the exit. If we prefer to view these with an Exploration we can use this code: Filter =Buy OR Sell. which gives us the type of exit thus: Fig 5 . Fig 4.Page 15 of 27 On the chart below we have separated out the buysignal and the Buy and we can see … … … … … … … the buysignal plotted as a hollow up blue arrow. AddColumn( Buy . the actual Buy day has the usual Lime Green up arrow from the Backtester a shape (here a small lime circle) at the BuyPrice the Sell signal plotted as a hollow down red arrow the red down arrow as the actual sell day."sell"). "buy"). So now we can look at the Chart to see if our trades taken match what we intended in the code.
"Pos Size"). TickSize. 4. When we trade shares. * AFL always dominates the settings placed elsewhere ** This is a global setting. the GUI SETTINGS and the information sheet. 3. Note that some settings can be controlled in all three places. some in only two and some in only one. To be sure of correct USD backtest results we need to make sure all values are correctly set in the AFL. Like the other settings there is an order of precedence. This can be done in the Settings GUI or in the AFL. 2. Filter = 1. 6. 5.2). PositionSize."FM". MarginDeposit. this column header changes to Contracts. the Backtester will show a column header called Shares. AddColumn AddColumn AddColumn AddColumn AddColumn AddColumn ( ( ( ( ( ( GetOption("FuturesMode").0). When we trade futures/forex and enable Futures mode.1. and we can use Addcolumn in an exploration to reveal the order of precedence by playing with the settings. Symbol Information for symbol specific information or AFL. and we need to tell AB this."ticksize".Page 16 of 27 FOREX backtesting These are the settings we need to address for Forex backtesting 1."RLS"."Pnt Val"). . 1. ** TICKER INFORMATION N/a Then Info sheet Info sheet first Then info sheet N/a Then AB looks at ticker specific Information which overrides global value AFL Code Set this to the same at SETTINGS GUI Then AFL dominates* Then AFL dominates* Then AFL dominates* AFL only Then AB looks for AFL value*: this overrides the other two Table 4. 1. TickSize is better to set in AFL or in Ticker info because it varies from currency to currency Why we need Futures specific settings FIRST it is NB to understand we are not trading shares here. by switching Futures mode to ON. PointValue. AB looks for these values in this order and gives precedence in ascending order like so: Forex settings Futures Mode RoundLotSize MarginDeposit Pointvalue PositionSize TickSize SETTINGS GUI AB looks here first Settings first Not available N/a N/a AB looks at Settings first.4). Futures mode RoundLotSize MarginDeposit PointValue Position size TickSize Like the other backtest settings. RoundLotSize. "Marg Dep"). we can set these in one of three places: Settings GUI for global settings.
which is the same as Lots in Forex. if at all. then we need to tell the Backtester what our . Therefore with Futures Mode ON we have to tell the AB Backtester what the dollar value of a Point move is. we do not generally use leverage to the same extent. there is 1:1 relationship between a 1 point move and 1 dollar value b. So buy paying attention the title/header in this column we can easily see if we have Futures mode ON of OFF.Page 17 of 27 Fig 6. Fig 7. So switching Future Mode ON displays the Contracts column in the Backtester results. The other thing it does is that it recognizes that we are no longer dealing with shares where a.
TickSize FuturesMode ON Best set in the SETTINGS GUI: if we want to have this in AFL then we need to ensure this matches the GUI settings. So just like the USD value per pip changes. which is a 1 point move. when USDJPY moves from 119.7 regular lots or even odd lots like buying 6 650 USDJPY this introduces more variables to the calculation of the PnL (Profit and Loss) in Dollars.83 USD respectively. and the dollar value of this move will depend on the USD value of each pip. This is because the dollar value per point move will vary per instrument traded. So we specify this information by the PointValue.Page 18 of 27 margin per contract is. minilots (10k) or fractions thereof. MarginDeposit 4. In shares. PointValue: L e t u s q u o t e t h e h e l p f i l e h e r e w i t h a d d e d e m p h a s i s t o d r i v e t h i s home: Point-value is per-symbol setting (definable in Symbol-Information window …) that determines the . to complicate things note that the USD value per pip changes as the currency prices moves up and down. If we take 2 lots each pip is worth 18. AB uses MarginDeposit and PointValue in the calculations that it uses to create the Report or Results. (See Fig 12) It needs us to tell it what these values are. Now if we trade minilots (10 000 of the Base currency pair) these values would be different: 0. Moreover if our platform allows us to trade fractional lots e. Specify the Pointvalue 3. and then we need to tell the AB Backtester what our Position size is going to be. So if we took one regular Lot of USDJPY (100 000 USD). so does the USD value per Point.g. mini or fractional). which can be set in AFL or in the Symbol.0001 comprises a move of 10.90 each pip would be worth about 9. REPORTS in Dollars Remember when we look at the Reports page the value in the Profit column can only have the correct Dollar value if we have the following settings correctly specified: 1. Position size 5. whether we trade standard (100k) lots. Similarly a 1 point move in the other non-JPY pairs with tick values of 0.000 pips. The value of each pip will then depend on the exchange rate of the currency at the present moment.00 USD per share or a move from 117. this is not a move of 1 dollar.58 and so on. (tells AB to only take full Lots: if you have mini account or can use fractional units you may have a reason to change this) 6. There is a linear relationship here because each dollar has 100 cents. However. Information field. Futures mode ON 2.00 to 120. Moreover. a 1 point move is a move from 12.915 USD and 1.15 USD.30 USD. and in Forex can depend on the size of our Lots (regular. which currency we trade in.00 USD per share to 13. This is in fact a move of 100 pips. So when we enable Futures Mode. RoundLotSize = 1.58 to 118. with the USDJPY currently at around 109.00. 0.
MarginDeposit can be set in the Symbol Information field. Information to set this. If we only backtest one currency pair we can set the PointValue in the AFL. As currency exchange rates change. MarginDeposit = 1000. So for a standard 100 000 EURUSD lot this is calculated as follows: A One Point move is from 1. 1. So for a standard 100 000 EURUSD lot at Margin of 1% this means we would have to place a deposit of 1 000 to open a 100 000 position and so we would enter 1000 for MarginDeposit. TickSize = IIf( StrRight( Name(). Next. Therefore PointValue = 100 * 0.0000 EURUSD This equals 10 000 pips From our trading platform we read that one Pip = 10 USD.// for pairs with JPY as counter currency PositionSize = MarginDeposit. Therefore a one point move is calculated as PointValue = 10 000 pips * 10 dollars per pip = 100 000 (USD) per lot.0001). . MarginDeposit MarginDeposit is the amount of money you need to deposit to open a trade. and your Lot size and number of Lots.3) == "JPY". To start off with we can choose to only trade in single Lots. or in the AFL. The AFL setting takes precedence. 100000). Currently for a 10 000 minilot in USDJPY the PointValue will be 0. the value of PointValue will also slowly change over time for non US pairs.1). SetOption("InitialEquity". but it would seem just as easy to set this in the Information field.915 per lot. the backtest dollar values may not be correct in the earlier part of the test. RoundLotSize = 1. This means that for Forex we need to specify the Dollar value of a One Point move for One Lot. we need to specify PositionSize.0000 to 2. But if we wish to test a number of currencies then we should use the Symbol. 0. // for example for 100:1 leverage on standard lot PointValue = 915 . and will be based on your account size. otherwise we would have to write some AFL code to determine PointValue per ticker. Hence we may choose to test with results displayed in Pips. Sample code would be: SetOption("FuturesMode". 0.Page 19 of 27 amount of profit generated by one contract for a one point increase in price. So for example if we backtest the EURJPY over the last 4 years where the price moved from 127 to 168 using the PointValue for today. This could be easily done with the IIF or If functions or even fed in to Parameter. your leverage or trading platform margin. we have to tell AB the full position size so it can do the calculations. Position size To allow AB to complete the calculations.01.915 = 91. Then we just set the Position size to the same value as the MarginDeposit: PositionSize = MarginDeposit.5 USD.
We tell AB the PositionSize we want in fixed Dollar amount and let it work out the Lots needed. RoundLotSize = 1. 100000). 0. I f w e w a n t t o b a c k t e s t w i t h m o r e t h a n o n e l o t w e h a v e t w o c h o i c e s .// for pairs with JPY as counter currency PositionSize = -10. We tell AB how many Lots we want to trade b. 0. // this means 10% of equity .10. TickSize = IIf( StrRight( Name().Page 20 of 27 The backtester will then show 1 contract/Lot having been traded: Fig 8. 2. RoundLotSize = 1. SetOption("InitialEquity".1.01.3) == "JPY". SetOption("InitialEquity". We tell AB the PositionSize we want as percentage of Equity and let it work out the Lots needed. 0. a. 100000). c.01. 1.// for pairs with JPY as counter currency NumLots = 3. Fig 9. // for example for 100:1 leverage on standard lot PointValue = 915 .3) == "JPY". Assuming a standard 100 000 account trading standard 100k lots and 1% margin requiring a 1 000 deposit: a. [Or if we wish to Optimize the position sizing we could use: NumLots = Optimize("NumLots". TickSize = IIf( StrRight( Name(). MarginDeposit = 1000.0001). Let AB work out the required number of Lots by defining the PositionSize as percent of Equity.0001). PositionSize = NumLots * MarginDeposit. MarginDeposit = 1000. PositionSize = NumLots * MarginDeposit. Sample code would be: SetOption("FuturesMode".1). 0. ] b. // for example for 100:1 leverage on standard lot PointValue = 915 .10.1). Tell AB how many Lots to trade SetOption("FuturesMode".
the MarginDeposit and the PositionSize.0001).3) == "JPY".01. Number of contracts will be 12 000 / MarginDeposit.Page 21 of 27 Fig 10.// for pairs with JPY as counter currency PositionSize = 12000. Again it works out the Number of contracts as PositionSize/MarginDeposit: SetOption("FuturesMode". // for example for 100:1 leverage on standard lot PointValue = 915 . // this means 12.000 / 1000 = 20 Lots. 0.] Calculations Having told AB to use Futures Mode and having given it the PointValue. 100000).1). TickSize = IIf( StrRight( Name(). AB takes 10% of account. MarginDeposit = 1000.1 * 100 000 = 10 000 as the Position Size in Dollars. As the Equity changes so will the number of contracts traded. So if MarginDeposit is 1 000 then we will expect to see AB open 12 Lots for us: Number of contracts = PositionSize/MarginDeposit = 12 000/ 1 000 = 12 Lots The number of contracts traded stays fixed as Equity changes. Here we have specified PositionSize = 12 000. AB then divides this by the MarginDeposit: 10 000 / 1000 = 10 Lots Or we can use PositionSize = -20. Let AB work out the Lots by defining a fixed dollar amount to trade. RoundLotSize = 1. // tells AB to use 20% of equity Position size will be 100 000 * 0.000 dollar position Fig 11.2 = 20 000 Number of contracts will be 20. [As an aside I have avoided using SetPositionSize in FX. 0. C. calculated as 0. I have not tested this but somehow suspect it internally looks at some of the other FX values and we could land up with double entries in the calculations. the calculations are done as follows . SetOption("InitialEquity". AB then works out the Number of contracts as PositionSize / MarginDeposit.
TickSize can be set in one of three places. The actual value that gets used can be displayed with an exploration output. and then this value gets used for calculations. (Fig 13) The Symbol Information value supersedes the Global value and is used in any needed calculations. SETTINGS in GUI b. in which case it appears that AB will internally round or adjust the calculated Exit Price to match a valid ticker specific price level. and we are still getting correct dollar values in the Backtester. If we code up some AFL for the TickSize then this gets given precedence for calculations in the backtester.Page 22 of 27 Fig 12. which is discussed later. Symbol information c.] . EXCEPT in two cases: FIRST where the Exit price is defined by ApplyStop or in-built stops. TickSize Note that we have not specified TickSize specifically yet. The SECOND reason has to do with the way we can calculate the Forex commissions or spreads. However the Report Settings value is still read from the Global Settings value. AFL The SETTINGS GUI value is the global default value which is used if no other values are set. and it is this value which is displayed in the Backtest Report Settings link. TickSize is not needed for the basic PnL calculations. a. but continues to display the global value. [Again the Report Settings link is of no use in checking the settings of the backtest parameters. Therefore it remains important that we always specify TickSize.
0001). 0. To use AFL in Backtester to set the TickSize for Forex. so… PointValue = Dollar value per pip / TickSize = $10 / 0. (this is because in AB the PointValue is the dollar value of a single pip divided by the TickSize: for standard lot EURUSD in USD denominated account each pip = $10. SetOption(“CommissionMode”.Page 23 of 27 Fig 13. we next need to set the correct costs/commission.0001 = 100 000) Multiplying the PointValue by the TickSize calculates the dollar value per pip. So we need to arrive at . So if we have one lot of 100 000 with PointValue of say 100 000. 0.3).//tells AB to use a specific dollar value per contract SetOption(“CommissionAmount”. youramount).3) == "JPY". Different currency pairs have varying spreads per Pair. GETTING THE COMMISSION AMOUNT RIGHT IN FOREX BACKTESTING Having got the correct Dollar value for the backtest results. TickSize of 0. we can use the IIf function: TickSize = IIf( StrRight( Name(). ranging form 1 to say 15 pips.01. TickSize * Pointvalue).01 then the Commision Amount is set as SetOption(“CommissionAmount”. // tells AB what value to use in the calculations.
but can be easily done with the IIF statement. with the actual spread depending on your Broker. and is already part of our code to get the correct Dollar value in the backtester. Now. SetOption("FuturesMode".5 * Spread * TickSize * PointValue). 0.3) == "JPY". Spread = 4.// SET THIS ALSO IN GUI SETTINGS.10. its value is zero and the CommissionAmount will always be zero. 0. OnePip = Name() == "EURUSD" OR Name() == "EURGBP". Sell = BarsSince(Buy) == 4.3) == “JPY”. If we do not specify any TickSize . Set the correct spread with the IIF function e. We also know that the spread varies per ticker.1). for Currencies we only pay the Spread once per round trip.3. leading to incorrect final dollar values. generally on entering the trade. TwoPip = Name() == "EURCHF" OR Name() == "EURJPY" OR Name() == "USDJPY" OR Name() == "AUDUSD". 98900. So the sample code for a Forex backtest commission calculation for a pair where CCY2 is JPY would look something like this: SetFormulaName("FxCommissionCorrect"). 1. PositionSize = NumLots * MarginDeposit.0. so our final dollar calculation for the CommissionAmount will look like this: SetOption(“CommissionAmount”. SevenPip = Name() == "GBPCHF" OR Name() == "GBPJPY". IIf(ThreePip.1).5 * Spread * TickSize * PointValue). IIf(FourPip. ThreePip = Name() == "CHFJPY" OR Name() == "USDCHF" OR Name() == "GBPUSD". // $ amount per contract SetOption("CommissionAmount".4.2. // for example for 100:1 leverage on standard lot PointValue = 915.01. 0. Spread = IIf( OnePip. we would have to both a.30)). also with IIF function. 0.Page 24 of 27 SetOption(“CommissionAmount”.01.3) == "JPY".3) == "CAD". Spread * TickSize * Pointvalue).1. EMA(C. This therefore shows again why we need the TickSize to be specified. 100000).0001). . IIf ( StrRight( Name(). And lastly. 0. RoundLotSize = 1. // silly simple Buy & Sell rules Buy = Cross( Close.g. SetOption("InitialEquity". TickSize = IIf( StrRight( Name().7. 1.0001). Set the correct PointValue for each pair: as discussed above we can best do this with the Symbol. Information field. We know that the TickSize will vary per currency: this is easily set in each ticker’s Information sheet or better still with AFL like this: TickSize = IIf(StrRight(Name(). or if we like we could code this into the AFL. b. MarginDeposit = 1000. 5))))). // current GBPJPY Spread SetOption("CommissionMode". such as PointValue = IIf ( StrRight( Name(). if we wanted to run this across all currency pairs at the same time. IIf(TwoPip.3). FourPip = Name() == "CADJPY" OR Name() == "USDCAD" OR Name() == "AUDJPY" OR Name() == "EURCAD" OR Name() == "NZDUSD". 915. IIf(SevenPip. // for pairs with JPY as the counter currency NumLots = Param("NumLots".
These values will only need occasional changes once currency exchange rates change significantly.0. . and then we do not need to set this in the Information sheet.3) == "CHF". IIf ( Name() == "AUDNZD". SetOption("FuturesMode". pipEQUITY = dollarEQUITY / DollarPerPip. // Set trading capital in dollars DollarPerPip = PointValue * TickSize. PointValue = IIf( StrRight( Name(). PointValue = 100. TickSize = IIf(StrRight(Name(). perhaps trading different Lot sizes or in different currencies. // typical JPY and USD values dollarEQUITY = 100000. 100. trade different lot sizes or had accounts in different base currency.3)=="JPY". PositionSize = MarginDeposit = 1. 90000. For Yen pairs we need 100 for the PointValue because there are 100 pips moved for one point. Because of this we may choose to get the Backtester to give us the results in Pips rather than Dollars.1). MarginDeposit = 1000.01.915. and can easily be obtained from your broker’s platform or a simple spreadsheet. PositionSize = MarginDeposit =1. PointValue = IIf( StrRight(Name(). // Use these to reset Equity from Dollars to Pips PositionSize = MarginDeposit = 1. IIf ( Name() == "EURGBP". So we can add this code to convert the initial Equity we start with into Pips. 195000. 10000) . we can just set the PointValue equal to the amount of pips in a one point move: For Non Yen pairs this works well: PositionSize = MarginDeposit = 1.3)=="JPY".// reminds us the results we are looking at is in pips. then the Statistics in the backtest Report will be meaningless.3) == "JPY". REPORTS in Pips We note also that if have more than one account. we would have to change the PointValue for each account if we want the Backtester settings to return the Profit in Dollars. If we want to display the profit in pips.// SET this also in the SETTINGS GUI RoundLotSize = 1. Now we have a potentially new problem: the PnL is expressed in Pips but unless we convert the equity to Pips. PointValue = 10000. 78000. 100000))))). SetFormulaName("FxPnLinPIPS").0001).0. So now we are in a position to set the Commission Amount to allow the Backtester to display correct dollars amounts in the backtester. 100000). PositionSize = MarginDeposit = 1.Page 25 of 27 IIf ( StrRight( Name(). Now we can use the IIf Statement to define this in AFL. They would also need to be adjusted if one were to have different account sizes.
100. where we set them and how to use them is the first step to developing confidence in the results the backtester displays. We have seen how the Applystops work and how they can be plotted for visual reference. //Reset PointValue to allow for results in Pips as above PointValue = IIf( StrRight(Name(). largest win. where the commission amount is simply equal to the Spread. Losers: Avg Loss %. Net Profit%. Max System Drawdown. CAR/MaxDD. although not all the values will be valid we can still plot the Equity curve and extract the most important statistics needed to compare one strategy against another. Then when we run a backtest over the same ticker. We have . Net Profit. Setting the Commission in Pips Finally. 10000). once with normal dollar results. SetOption("CommissionAmount". then we find that MOST. Avg Bars Held. Net Risk Adjusted Return%. Avg bars held. These statistics will remain valid: Initial Capital. Summary Knowledge of how the backtester does its calculations. Losers Number and Percent. Largest Loss.Page 26 of 27 SetOption("InitialEquity". and which settings were needed to obtain accurate forex calculations.3). but not all of the Backtester statistics are displayed correctly. # bars in largest win. Profit Factor. Other statistics: Max trade % drawdown. Recovery Factor. Avg Profit/Loss%: Winners: Avg Profit% . Max System % Drawdown. So. This is easy. Avg Loss. and then with PipValue results. pipEQUITY). Total Profit. Ending Capital. Standard Error. and we remember that we only pay the spread in Forex once per round trip: Spread = 4. U l c e r P e r f o r m a n c e Index. Annual return%. We have looked at the differences between backtesting shares and forex. Winners number and percent. Other statistics: Max trade drawdown. Avg Profit/Loss. Sharpe Ratio of trades.Spread / 2). Avg Profit. RARMaxDD. These statistics will not make sense: Exposure%. SetOption("CommissionMode". we need to include the Commission in Pips. U l c e r I n d e x . Avg Bars held. We have learnt the basics of the backtester. Risk Adjusted Return%. Risk-Reward Ratio. Total Loss. Max Consecutive. K-ratio. Max Consecutive. Payoff Ratio. same data and same system. where we can use the AFL to override the SETTINGS GUI entries.3)=="JPY". # bars in Largest Loss. which settings cannot be set in the AFL and which ones can only be set in the AFL.
The next run of the backtest does not always register the new change. Amibroker help file Yahoo Amibroker group Amibroker support http://www. 2. See message #97492 in Amibroker usergroups.au . Reference future bars Prior to running the backtester we need to ensure the code and settings do not allow referencing future bars.Page 27 of 27 seen how we can express forex results in dollars or pips and shown how to obtain correct commissions to be factored into the calculations.amibroker. Check. We can just hit the Back Test button a few times.net. or else the strategy will not be able to be traded live. If there is a reference to future bars we will need to rem out each line until we find out which is the offending code and rectify this first. 3. Go to AA. we make frequent changes to the code or settings.com/kb/2006/08/09/amibroker-for-forex/ ChrisB c/b Jan 2008 Feedback/errors/ corrections welcome via yahoo amibroker usergroup or kris45mar [at] iinet. Even using the next bars data to work out the position sizing can result in this error. References 1. Other Simple Tips When testing and running these backtest AFLs. or we can save changes to the AFL and reload the file. Check or Tools. 4.
This action might not be possible to undo. Are you sure you want to continue?
We've moved you to where you read on your other device.
Get the full title to continue listening from where you left off, or restart the preview.