Reading the Backtest Report
A backtest report is a long document, and almost nobody reads it as one. People scroll to the number they were hoping for, feel something about it, and then read the rest of the report in the light of that feeling. If the number was good, the trade list becomes confirmation; if it was bad, the settings become suspect. The report has not changed. The reader has.
The defence is procedural rather than intellectual. Decide the order in which you will look at things before you look at any of them, put the numbers that can invalidate the test in front of the numbers that can excite you, and keep the same written record every time so that two runs a month apart are actually comparable. By the end of this lesson you will have that order, that record, and a clear picture of what the report contains.
Where the report is
Section titled “Where the report is”Run a backtest from the Analysis window and click the Report button. That opens the report for the run you have just done.
The drop-down arrow on the same Report button opens the Report Explorer, which lists every report AmiBroker has stored, not only the most recent one. This is more useful than it sounds. Six weeks into developing a strategy you will want to know what the fourth variation did, and the Report Explorer is the only place that still knows.
What is actually in the report
Section titled “What is actually in the report”AmiBroker’s own documentation names two pages of the report explicitly — the statistics page, where the metrics live, and the Monte Carlo page, which appears when Monte Carlo simulation is enabled in the settings. It separately documents the other contents: the charts, the trade list, the formula and the settings.
The statistics page
Section titled “The statistics page”This is the table of metrics, and it is what the next three lessons are about. Two structural facts matter before any individual number does.
First, the modern portfolio backtester reports statistics in three columns: All trades,
Long trades and Short trades. Where a system takes no short trades, the short column
reads N/A. The old, pre-portfolio backtester only ever produced an all-trades column,
which is one quick way to tell whether a forum post you are reading describes the engine
you are using.
Second, hovering the mouse over a field name shows a tooltip with that metric’s short
description — the same text the User’s Guide carries. When you cannot remember whether
Recovery Factor divides by the currency drawdown or the percentage one, the answer is
already on your screen.
The charts
Section titled “The charts”The report’s charts are ordinary AFL formulas that live in the Charts tree’s Report Charts folder. Each is rendered to a bitmap of fixed dimensions and embedded in the HTML, which explains the classic complaint that the profit table is unreadable: the numbers are too big for the picture. The fix is Settings → Report → Chart dimensions (in pixels), and it only affects reports generated after the change. Reports already stored keep the picture they were built with.
Two further facts about this page. You can add your own report charts by putting an AFL
file in that folder. And EnableTextOutput( 3 ) lets a report chart emit HTML instead of
a bitmap, which is how AmiBroker’s own profit table stopped being a scaling problem.
The trade list
Section titled “The trade list”Settings → Report has a check box, Include trade list in the report, on by default, and a radio group, Result list shows:, with three choices that change what the Analysis window’s result list contains:
| Setting | What you get | When you want it |
|---|---|---|
Trade list |
One row per trade, ordered by exit date by default | Normal reading, sampling trades |
Detailed log |
One row per data bar, showing scores, positions, and the reason a trade could or could not be opened | Debugging position sizing, ranking, and “why did nothing happen?” |
Summary |
One row per backtest, containing the summary statistics | One-line-per-run output, optimizations |
The columns visible in AmiBroker’s own documentation screenshot of a trade list include
the position value, cumulative profit, # bars, Profit/bar, MAE and MFE, plus any
per-trade custom metrics appended on the right. MAE and MFE are percentages —
the maximum adverse and maximum favourable excursion of each trade.
The guide’s own warning is worth repeating: trade lists “may be huge and consume quite a bit of disk space”. Turn the option off before a large optimization, and back on when you are reading a single run.
The formula and the settings
Section titled “The formula and the settings”Settings has two check boxes, Formula and Settings, which embed the exact AFL source and the exact backtester settings into the stored report. Both live under the settings dialog’s Old tab, which is a genuinely confusing place for them, because they control the content of the report you actually read.
Turn both on and leave them on. A stored report that contains its own formula and its own settings is reproducible six months later by someone who has forgotten everything, including you. A stored report that contains only numbers is an anecdote.
The test we will read
Section titled “The test we will read”Every lesson in this part refers to the report produced by one formula. It is an unremarkable long-only breakout, and its rules are not the point — the assumption block at the top is.
Complete runnable AFL
// report-reference-system.afl// Part 29 - Understanding Backtest Results//// The single backtest whose report every lesson in this part reads.//// The rules are deliberately ordinary - a long-only breakout taken only in an// established uptrend, on a liquid universe, with one maximum-loss stop. The// point of this file is not the rules. The point is that every assumption the// report depends on is written down in one place, so that when you read a// number you can say what produced it.//// No result is claimed for this system. Nothing here is a recommendation.//// ------------------------------------------------------------------------// ASSUMPTIONS - a backtest report without these attached is not evidence// ------------------------------------------------------------------------// Universe Whatever watch list you apply it to, further filtered below// by average traded value. If your list was built from today's// index membership, it is survivorship-biased and the report// describes a past that never existed. Part 30 covers that.// Periodicity Daily bars. Set Analysis -> Settings -> General -> Periodicity// to Daily. Every metric in the report changes if you do not.// Timing Signals are computed on the close of the signal bar and acted// on at the NEXT bar's open: SetTradeDelays( 1, 1, 1, 1 ) with// the trade prices taken from Open. Nothing in this formula is// allowed to read a price it could not have known.// Slippage A fixed percentage moved against you on every fill. Crude,// but stated. PriceBoundChecking is left on, so AmiBroker keeps// the adjusted price inside the bar's High-Low range.// Commission 0.10 per cent of trade value per side (CommissionMode 1).// Interest Uninvested cash earns nothing. This is set deliberately: a// non-zero Settings interest rate quietly credits a low-exposure// system with income it did not trade for, and that income lands// in Net Profit and in Annual Return %.// Leverage None. AccountMargin 100 is a cash account.// Stops One maximum-loss stop, checked against the High-Low range but// exited at the NEXT bar's open (ExitAtStop = 2). Exiting at the// exact stop price assumes a fill that a gap does not offer.// Capacity NOT modelled. The liquidity filter is a proxy; the backtester// still fills the whole position at a single price. Every figure// in the report inherits that assumption.// ------------------------------------------------------------------------
// ---- Account and portfolio ---------------------------------------------MaxPositions = 10;
SetOption( "InitialEquity", 100000 );SetOption( "MaxOpenPositions", MaxPositions );SetOption( "AccountMargin", 100 ); // 100 = cash accountSetOption( "InterestRate", 0 ); // idle cash earns nothingSetOption( "AllowPositionShrinking", False ); // no half-sized entriesSetOption( "MinPosValue", 2000 ); // skip trades too small to be realSetOption( "PriceBoundChecking", True ); // keep fills inside the bar
// Equal weight across the maximum number of simultaneous positions.SetPositionSize( 100 / MaxPositions, spsPercentOfEquity );
// ---- Costs --------------------------------------------------------------SetOption( "CommissionMode", 1 ); // 1 = percent of trade valueSetOption( "CommissionAmount", 0.10 ); // 0.10% per side
SlippagePercent = Param( "Slippage per side (%)", 0.05, 0, 0.50, 0.01 );
// ---- Execution timing ---------------------------------------------------SetTradeDelays( 1, 1, 1, 1 );
BuyPrice = Open * ( 1 + SlippagePercent / 100 );SellPrice = Open * ( 1 - SlippagePercent / 100 );
// Stops are executed before regular signals, so cash freed by a stop is// available on the same bar. Turn this on if you want the opposite.SetOption( "ActivateStopsImmediately", False );
// ---- Universe filter ----------------------------------------------------// Traded value, not share volume: a 3.00 share and a 300.00 share trading the// same money are equally tradeable, and their share counts are not comparable.MinTurnover = Param( "Min. avg daily turnover", 2000000, 0, 50000000, 100000 );TurnoverPeriod = Param( "Turnover average (bars)", 50, 5, 250, 5 );
AvgTurnover = MA( Close * Volume, TurnoverPeriod );LiquidEnough = AvgTurnover > MinTurnover;
// ---- Rules --------------------------------------------------------------TrendPeriod = Param( "Trend average", 200, 50, 400, 10 );EntryPeriod = Param( "Breakout lookback", 50, 10, 200, 5 );ExitPeriod = Param( "Exit lookback", 25, 5, 100, 5 );MaxLossPct = Param( "Max. loss stop (%)", 12, 2, 40, 1 );
Uptrend = Close > MA( Close, TrendPeriod );
// Ref( ..., -1 ) so that today's own high is not part of the level it must// exceed. Comparing HHV with the bar that produced it is a silent no-op.BreakoutLevel = Ref( HHV( Close, EntryPeriod ), -1 );ExitLevel = Ref( LLV( Close, ExitPeriod ), -1 );
Buy = Uptrend AND LiquidEnough AND Close > BreakoutLevel;Sell = Close < ExitLevel;
Short = False;Cover = False;
// When more symbols signal than there are free position slots, the ranking// decides which ones are taken. Ranking on longer-term momentum is a choice;// record it, because it is part of the system, not a detail.//// AmiBroker ranks on the ABSOLUTE value of PositionScore unless you turn on// SeparateLongShortRank, so a score that can go negative silently promotes the// worst candidates. ROC() cannot fall below -100 for a positive price, so// shifting it by 100 keeps the score non-negative and the ordering intact.PositionScore = 100 + ROC( Close, 100 );
// ExitAtStop = 2: the High-Low range is checked, but the exit is taken at the// next bar's open rather than at the exact stop price.ApplyStop( stopTypeLoss, stopModePercent, MaxLossPct, 2 );Run it once on a watch list of your own, over a range of your own, with Periodicity set to Daily, and keep the report open as you read the rest of this part.
A reading order that resists wishful thinking
Section titled “A reading order that resists wishful thinking”The order below is deliberately hostile to enthusiasm. Everything that could tell you the test is not worth reading comes before anything that could tell you the test went well.
Read the report in this order
- 1. Settings and formulaWhat was actually run, before any number
- 2. Number of tradesIs there enough evidence to read at all?
- 3. Exposure %How much of the time was money at work?
- 4. Drawdown and the equity curveWhat would holding this have felt like?
- 5. Annual Return % and CAR/MaxDDOnly now, the headline
- 6. Trade distributionPayoff Ratio, Profit Factor, largest win
- 7. The trade listSample it. Do the trades look possible?
- 8. Write it downThe record, not the report, is the artefact
Each step earns its place:
- Settings and formula. Wrong periodicity, wrong date range, a commission of zero or trade delays of zero make every subsequent number meaningless. Checking this first costs thirty seconds and saves whole afternoons.
- Number of trades. Thirty trades cannot support a conclusion about a win rate, a Profit Factor or anything else. Establish the sample size before you form an opinion that the sample size cannot carry.
- Exposure %. This changes what every return figure means, and it is the denominator of two of them. A system that is in the market 8 per cent of the time and one that is in it 95 per cent of the time are not doing comparable things, whatever their returns.
- Drawdown and the equity curve. Look at the worst decline and the shape of the curve before the return, because the drawdown is the part you would actually have to survive in order to collect the return.
- The headline.
Annual Return %andCAR/MaxDD, now that you know what they are a return on and a ratio of. - Trade distribution.
Payoff Ratio,Profit Factor, the largest win. If one trade supplied most of the profit, the summary statistics are describing an accident. - The trade list. Sample ten trades at random and ask whether each one could have been taken: was the symbol liquid on that date, was the fill price inside the bar, did the exit happen at a price that was knowable at the time?
- The record. Which is the next section.
What to write down every time
Section titled “What to write down every time”The report is disposable. The record is not. Keep it in the same shape for every run, in a plain text file or a spreadsheet, so that two runs six weeks apart can be compared without archaeology.
| Field | Example of what to record |
|---|---|
| Date run, AmiBroker version | 2026-09-01, 7.00.1 |
| Database and data source | Local EOD database, vendor and download date |
| Universe, and how it was built | Watch list name, the rule that built it, and whether delisted symbols are in it |
| Date range and periodicity | From-To dates as set in the Analysis window; Daily |
| Initial equity | 100,000 |
| Position size rule | Equal weight, 10 per cent of equity, max 10 open positions |
| Trade delays and trade prices | 1 bar all four; entries and exits at the open |
| Commission mode and amount | Percent of trade value, 0.10 per side |
| Slippage assumption | 0.05 per cent per side, applied to the fill price |
| Stops in force | Maximum loss 12 per cent, ExitAtStop mode 2 |
| Rate settings on the Report tab | Whatever Settings → Report shows; the Risk-free rates pair is not a constant and two metrics move with it |
| The question you were asking | “Does the trend filter earn its place?” |
| The metrics you will compare on | Chosen before the run, not after |
That last pair of rows does most of the work. Choosing the comparison metric before the run is the difference between testing an idea and shopping for a number, and writing down the question stops a run drifting into “let me see what happens if…” without anyone noticing.
You know where the report and the Report Explorer are, and that the Explorer keeps every past run. You know the documented contents: a statistics page with All, Long and Short columns, a charts page built from AFL formulas in the Report Charts folder, a trade list whose format is controlled by a radio group in Settings, and — if you turn them on — the formula and settings that produced it all. You know that the guide does not enumerate the tab strip, so you check that on your own installation rather than taking anyone’s word for it.
More importantly, you have an order to read in and a record to keep. The next lesson starts on the statistics page itself, with the numbers most people read first and this course reads fifth.
Check your understanding
Sources for this lesson
5 verified · checked 2026-08-31
- 01AmiBroker User's Guide — System test report windowamibroker.com/guide/w_report.html2026-08-31
- 02AmiBroker User's Guide — Using New Analysis window§ Viewing Reports / Running the Report Exploreramibroker.com/guide/h_newanalysis.html2026-08-31
- 03AmiBroker User's Guide — System test settings window§ Report tabamibroker.com/guide/w_settings.html2026-08-31
- 04AmiBroker User's Guide — How to add user-defined metricsamibroker.com/guide/a_custommetrics.html2026-08-31
- 05AmiBroker User's Guide — Portfolio Backtester Interface Reference§ Trade objectamibroker.com/guide/a_custombacktest.html2026-08-31
Every technical claim on this page was checked against the official AmiBroker documentation on the date shown. Where the course disagrees with folklore, the source is how you can tell which one to trust.