Advanced users’workshop:Custom BacktesterInterfaceby Tomasz Janeczko,

Custom backtesterinterface (CBI) - what for?For everything that is not possible to dowith standard backtester except.making coffee(feature not implemented, sorry)

Custom backtesterinterface (CBI) - what for? adding your custom metrics position sizingbased on portfolio-level equity advanced scaling-in/-out based on portfolioequity (for example rebalancing) and other runtime stats customized rotational trading systems implementing custom formulas for slippagecontrol advanced systems using PF-level stats on barby-bar basis to decide which trades to take

Purpose of this session to explain some basic conceptsto show a couple of usage examplesto answer questions that you may haveit is NOT 1-hour programming course

Portolio backtest: 2 passes first pass collecting trade signals, ranking/sorting by position score(your AFL formula is executed once for everysymbol under test) second pass actual backtest (simulation of trading onhistorical data using signals collected in 1st pass)(executed only once per backtest)

First backtester pass(regular)

Second backtester passThis is where custom backtester interface canbe used For each bar the following things happen: Top ranked entry signals are checked andtrades are entered (if funds are available) Exit/scale signals are matched against openpositions and executed Stops are applied and executed All portfolio-level statistics/metrics are updatedWith CBI you can actually change every aspect of this pass

How to enable it ?To enable custombacktest, you can useAA- Settings,Portfolio tab(if you do so, customcode will be applied toALL backtests)

How to enable it ?.or you can enable it from the code:SetOption("UseCustomBacktestProc", True" );(if you want to use use external file for it)In this case custom backtest will be applied tocurrent formula only.

Where to enter CBT code ifit is enabled inside formulaTo distinguish between normal run (phase 1)and final backtest run (phase 2) you need touse Status function:SetCustomBacktestProc("");if( Status("action") actionPortfolio ){. YOUR CBT CODE (PHASE 2)HERE.}. YOUR REGULAR TRADING SYSTEM (PHASE 1)

CBI - 3 programming levels high-level - the easiest (allows simpleimplementation of custom metrics) medium-level (allows to modify signals,query open positions - good for advancedposition sizing) low-level approach (the most complex)- provides full control over entire backtestprocess for advanced programmers only

CBI programming model Custom backtester interface uses so called“object oriented programming”methodology (a.k.a. OOP) Don’t be afraid - at basic level (only thislevel is required to understand CBI) OOPis fairly simple

OOP - object definition In computer science an object is selfcontained entity that encapsulates bothdata (so called properties) andprocedures (so called methods) tomanipulate the data. Sounds difficult.? . Maybe but it isactually simple.

OOP - simple exampleBefore we dig into objects used by CBI one “real-world”example what object is and how to use: a PEN - in programming could berepresented as object having properties color, thickness methods that perform some actions DrawLine( x, y ) for examplepen CreatePen(); // object creationpen.thickness 2; // property modificationpen.DrawLine( 30, 20 ); // method call

OOP vs functionalprogrammingMany old-time programmers are afraid aboutOOP, while they used more or less the sameidea without actually realising that.Example:FILE HANDLE - OBJECT - in everyprogramming language there is a concept offile handle that all file functions (METHODS)require to identify the file (OBJECT) on whichto operate.

CBI object hierarchy

CBI access to objects Backtester object is available directlyusing GetBacktesterObject() AFL function. All other objects (Signal/Trade/Stats) areaccessible by calling appropriate methodsof backtester object

High level mode The simplest. Uses only two objects (Backtester andStats) and only two methods(Backtest()/GetPerformanceStats()) how does it work? We call default Backtest() procedure and after that we are collecting statistics tocalculate our own figures. what for? user-defined portfolio-level metrics

Ex 1: High Level - custommetrics In the first example we will add simplenew metric to backtest/optimizationoutput:Expectancy ( ) %Winners * AvgProfit %Losers * AvgLoss

Ex 1: High level - custommetrics - cont. SetCustomBacktestProc("");/* Now custom-backtest procedure follows */if( Status("action") actionPortfolio ){bo GetBacktesterObject();bo.Backtest(); // run default backtest procedurest bo.GetPerformanceStats(0); // get stats for all tradesexpectancy rsPercent")/100 rcent")/100;// Here we add custom metric to backtest reportbo.AddCustomMetric( "Expectancy ( )", expectancy );}

Ex 1: High level - custommetrics - results

Medium level Semi-advanced - uses all object classes how does it work? for each bar: we can modify signals, check/modify open positions,retrieve per-trade statistics then we call default signal processing method what for? Advanced position sizing PF-level signal control (custom rotational trading) Trade-based metrics

Ex 2: Mid-level - pos. sizingbased on portfolio eq.if( Status("action") actionPortfolio ){bo GetBacktesterObject();bo.PreProcess();for( bar 0; bar BarCount; bar ){CurrentPortfolioEquity bo.Equity;for( sig bo.GetFirstSignal( bar );{if( CurrentPortfolioEquity 50000if( CurrentPortfolioEquity 60000if( CurrentPortfolioEquity 80000}bo.ProcessTradeSignals( bar );}bo.PostProcess();}sig; sig bo.GetNextSignal( bar ) )) sig.PosSize -20;) sig.PosSize -16;) sig.PosSize -12;

Ex 3: Mid-level - excl. top-Nsignals in rotational modeSetOption("UseCustomBacktestProc", True );ExcludeTopN 1; // how many top positions to excludeif( Status("action") actionPortfolio ){bo GetBacktesterObject();bo.PreProcess();for( bar 0; bar BarCount; bar ){Cnt 0;for( sig bo.GetFirstSignal( bar ); sig; sig bo.GetNextSignal( bar ) ){if( Cnt ExcludeTopN ) sig.Price -1; // excludeCnt ;}bo.ProcessTradeSignals( bar );}bo.PostProcess();}EnableRotationalTrading( True );SetOption("MaxOpenPositions", 5 ); SetOption("WorstRankHeld", 10 );

Low level mode The most complex but most powerful how does it work? for each bar we can check signals/open pos/PF-stats to decide whattrades to enter/exit/scale we can call EnterTrade/ExitTrade/ScaleTrade for usingany parameters we want, we are not limited by signals we need to handle stops and update portfolio statistics what for? rarely used, only for very advanced pf systems

Ex 4: Mid/Low-level rebalancingif( Status("action") actionPortfolio ){bo GetBacktesterObject();bo.PreProcess(); // Initialize backtesterfor(bar 0; bar BarCount; bar ){bo.ProcessTradeSignals( bar );CurEquity bo.Equity;for( pos bo.GetFirstOpenPos(); pos; pos bo.GetNextOpenPos() ){posval pos.GetPositionValue();diff posval - 0.05 * CurEquity; // rebalance to 5% of pf equityprice pos.GetPrice( bar, "O" );if( diff ! 0 AND abs( diff ) 0.005 * CurEquityAND abs( diff ) price ){bo.ScaleTrade( bar, pos.Symbol, diff 0, price, abs( diff ) );}}}bo.PostProcess(); // Finalize backtester

Some questions I collectedbefore (1)Q: Rebalancing sample: can the weight alsobe an array, so the weights becomedynamic?A: Yes it can. Instead of this line:diff posval - 0.05 * CurEquity;Use this:diff posval - Foreign(" TickerWithWeights", "C") *CurEquity;

Some questions I collectedbefore (2)Q:How can I access percentage position size to makeleverage adjustment for expectancy per 100 investedA: You need to store original percent position size fromappropriate Signal object (if you are using regular mode). Todo so, you can use SetVar function inside loop using midlevelfor( sig bo.GetFirstSignal( bar );sig;sig bo.GetNextSignal( bar ) )VarSet("OrigSize" sig.Symbol, sig.PosSize );Later on you would need to read it back when you iterate throughtrades.Because of complexity I will post code sample a bit later to the KB.

Some questions I collectedbefore (3)Q: I have problem with using ATC in CBprocedure together withatcFlagEnableInPortfolioA: Yes there is a problem in current beta,but it will be fixed next week

Some questions I collectedbefore (4) Q: Is there already a way to automatically savethe " EQUITY" to a different choosen nameafter a backtest? If not, would you considerintroducing this possibility? A: Currently there are two ways: harder: writing equity to file and using OLE to reimport it at the end of CB procedure. easier: using ATC and atcFlagEnableInPortfolio (butas mentioned earlier it requires fix to the beta)

Some questions I collectedbefore (5) Q: Will there be a link between theaccount manager and the portfolioBT/CBT A: At some point in the future yes. Firstversion of new account manager that willappear within months probably will nothave it.

Any more questions? Please feel free to ask any questions.

Thank YouFor more information visit:

Title: Using High-frequency market data for better trading Author: Tomasz Janeczko Created Date: 3/8/2006 12:07:04 AM