Skip to content
Level 4 · Trading System ResearcherLessonPart 32 · page 3 of 530 min
30Minutes
4AFL functions
6Sources
StandardRequires
AFL functions taught here4

The AmiBroker Walk-Forward Workflow

Walk-forward testing has been a built-in mode since AmiBroker 5.10, and setting it up is a tab, six fields per phase and one combo box. The difficulty is not operating the dialog. It is that two of those fields quietly override others, one mode lets you construct a procedure that is not a valid walk-forward at all, and the results land in three different places depending on what you want to look at.

This lesson walks the dialog as it is documented, then finds every piece of output the run produces.

Open an Analysis window, press Settings, and switch to the Walk-Forward tab. The dialog is captioned Backtester settings, and its tabs are General, Trades, Stops, Report, Portfolio, Walk-Forward and Monte Carlo. Nothing on the earlier tabs stops applying: the initial equity, commissions, trade delays, position sizing and stops you set for an ordinary portfolio backtest are the settings each walk-forward step runs under.

The tab has two groups — In-sample data and Out-of-sample data — with the same field set in each, a mode selector across the top, an Optimization target field at the bottom, and a Preview list that shows the segments your settings generate.

The mode selector offers Easy mode (EOD), Easy mode (intraday) and Advanced mode. The choice is more consequential than the word “easy” suggests.

Easy mode is the default and the safe one. It assumes two things: that the out-of-sample segment immediately follows the in-sample segment, and that the length of the out-of-sample segment equals the walk-forward step. From those it derives the out-of-sample start date from the in-sample end date, adds the step to get the out-of-sample end date, and forces the in-sample and out-of-sample steps to be equal. The User’s Guide’s claim for this mode is that it makes the correctness of the walk-forward settings automatic. In Easy mode the out-of-sample fields are derived for you and are not yours to edit.

EOD versus intraday is not cosmetic. In EOD mode the end date of one period and the start date of the next are the same date, so there is no gap between periods. In intraday mode the next period starts on the day after the previous period’s end, which stops the boundary day being counted twice when you are testing on intraday bars. Choosing the wrong one either double-counts a session or drops one, on every step.

Advanced mode hands you every field. The guide’s own description of what that means is worth quoting in substance: the user has complete control over all values, “to the extent that they may not constitute a valid WF procedure”. Overlapping in-sample and out-of-sample windows are a look-ahead leak of the most direct kind, and AmiBroker will not stop you building them.

Both the In-sample data and Out-of-sample data groups carry the same set. Each group also has an enable checkbox on its header, which the guide notes exists for special cases such as running sequential backtests with no optimisation phase.

Field What it does
Start: Beginning of the initial in-sample period. Not the beginning of the test.
End: End of the initial in-sample period. This is the date that walks forward.
Anchored Ticked, Start stays put while End advances, so the window expands. Unticked, Start advances by Step too, so the window slides.
Last: The walk stops once End reaches this date.
Use today When ticked, the Last date you typed is ignored and today’s date is used instead.
Step: A number plus a unit — years, and the shorter units — by which the window advances each iteration.

Two of these deserve underlining.

Anchored is the anchored-versus-rolling decision from the previous lesson, reduced to a checkbox. It is a methodological commitment, not a display option, and it belongs in your written record of the run.

Use today overrides Last silently. This is the source of the classic complaint that a walk-forward run keeps producing different segments from one week to the next: with Use today ticked, the segment set genuinely changes every day. It is the right setting for a process you run repeatedly on live data and the wrong setting for a reproducible experiment.

Under the fields sits a Preview grid with a Mode column reading IS or OOS, plus Start and End. It regenerates immediately as you change any setting, and it is the only place the actual segment dates are shown.

Read it before every run, and check four things: that the first in-sample segment starts where you meant; that each OOS row begins where the preceding IS row ends, according to the EOD or intraday convention you chose; that no IS row overlaps its own OOS row; and that the number of rows matches the step count you calculated. If the preview disagrees with your arithmetic, your arithmetic or your settings are wrong, and finding out now costs seconds rather than an evening.

The tab also has Load and Save buttons for the settings themselves, which is the cheapest way to make a course exercise or a team procedure repeatable.

At the bottom of the tab is Optimization target, and it is the objective function: the name of the optimisation-report column used to sort results and pick the best one on each in-sample segment. The default is CAR/MDD. You can select any built-in column from the combo box, exactly as it appears in the optimisation output, or type the name of a custom metric you added through the custom backtester — the combo does not enumerate those, so the spelling has to be yours and it has to be exact.

Three things about this field surprise people.

It lives on the Walk-Forward tab even when you are not doing walk-forward. The non-exhaustive optimisation engines read the same field, so a reader who sets OptimizerSetEngine( "cmae" ) and never opens this tab is optimising CAR/MDD whether they intended to or not.

It does not re-sort an ordinary exhaustive optimisation result list. That list arrives sorted by Net % profit; click a column header to change it. The Optimization target drives selection inside walk-forward and smart engines, not the display.

And the choice of target changes the winner. CAR/MDD prefers a smoother ride; Net Profit % prefers the largest number regardless of the path; Profit Factor on a system with three trades prefers an accident. Whatever you choose, choose it before the run, and write it into the record — it is as much a part of the procedure as the window lengths.

One walk-forward run, end to end

  1. SettingsWalk-Forward tab: mode, dates, step, target
  2. PreviewCheck every IS/OOS row before running
  3. RunOptimize button drop-down, Walk-Forward
  4. Walk Forward tabPer-step results appear as they finish
  5. RecordExport, save the project, write the log
The two accented steps are the ones people skip, and they are the ones that make a run defensible.

Click the drop-down arrow on the Optimize button in the Analysis window and choose Walk-Forward. Older documentation calls the same command “Walk Forward Optimization”; it is the same thing. AmiBroker then runs the whole sequence of optimizations and backtests.

While it runs, the progress dialog has a MINIMIZE button. Pressing it lets you watch the Walk Forward output accumulate step by step, which on a long run is the difference between finding a broken configuration after two minutes and finding it after two hours.

Remember what you have started. The run is a sequence of complete optimizations, so the time cost is the number of steps multiplied by the cost of one optimisation over your whole watch list.

Three separate places, and they answer different questions.

The Walk Forward tab. On the current Analysis window, walk-forward results are displayed in the Walk Forward tab at the bottom of the Analysis window, a row per step. Older documentation describes a separate “Walk Forward document” in the main application frame, which is the same output from an earlier generation of the interface; if you are following a tutorial that mentions it, look in the tab instead.

The composite equity tickers. Combined in-sample and out-of-sample equity are written to two composite tickers, ~~~ISEQUITY and ~~~OSEQUITY. Consecutive periods are concatenated and scaled to keep the equity line continuous, which — as the User’s Guide says outright — assumes you are generally compounding profits. These are symbols in your database, not report rows, so you look at them by charting them.

The out-of-sample summary report. Since version 5.60 a walk-forward run also produces a summary report covering all out-of-sample steps. It appears in the Report Explorer — reached from the drop-down arrow on the Report button — as the last entry, with type PS.

The summary’s built-in metrics are computed properly across all steps — the guide is careful to say they are “not averages but properly calculated metrics”. Custom metrics are a different matter: they are combined by whichever method you asked for when you added them, from first step value, last step value, sum, average, minimum or maximum. The default is last step value, so an unspecified custom metric in a walk-forward summary is the final segment’s number and not a summary at all. The report prints a note saying which method was used; read it.

~~~OSEQUITY holds the answer to the question the whole exercise asked, and it is a ticker rather than a number, so nothing displays it until you write a formula. This one plots the out-of-sample equity prominently and the in-sample equity behind it, with a toggle, so that the line your eye lands on is the one that counts.

Complete runnable AFL

wf-equity-plot.afl
// wf-equity-plot.afl
// Part 32 - The AmiBroker Walk-Forward Workflow
//
// Charts the two composite tickers a completed walk-forward run leaves behind:
// ~~~ISEQUITY holds every in-sample segment concatenated, ~~~OSEQUITY holds
// every out-of-sample segment concatenated. The out-of-sample line is the one
// the whole exercise was for.
//
// Apply this as a CHART formula, not in the Analysis window. PlotForeign reads
// the composites by name, so the symbol selected in the chart contributes only
// the date axis - pick an index or any symbol whose history spans the run.
//
// Assumptions and caveats:
// - The composites exist only after a walk-forward run has completed, and the
// NEXT walk-forward run overwrites them. Chart or export before re-running.
// - The User's Guide states that consecutive in-sample and out-of-sample
// periods are concatenated and SCALED to keep the equity line continuous,
// and that this assumes you are compounding profits. On a fixed-size system
// the scaling is a modelling assumption, not a measurement.
// - The spelling is ~~~OSEQUITY: three tildes, and OS rather than OOS. A
// wrong ticker name plots nothing and reports no error at all.
_SECTION_BEGIN( "Walk-forward equity" );
ShowInSample = ParamToggle( "Show in-sample equity", "No|Yes", 1 );
// In-sample first and thinner, so the out-of-sample line is the one your eye
// lands on. In-sample equity is context, not evidence.
if ( ShowInSample )
{
PlotForeign( "~~~ISEQUITY", "In-sample equity", colorOrange, styleLine );
}
PlotForeign( "~~~OSEQUITY", "Out-of-sample equity", colorGreen,
styleLine | styleThick );
Title = "{{NAME}} - walk-forward equity - {{DATE}} - {{VALUES}}";
_SECTION_END();

Download wf-equity-plot.afl39 lines

There are only three moving parts. PlotForeign draws a named symbol’s data on the current chart, so the composite is charted without changing the selected symbol; the symbol you have open contributes the date axis and nothing else. ParamToggle puts the in-sample line behind a Parameters-dialog switch, because in-sample equity is context rather than evidence and should be easy to remove. The Title line uses AmiBroker’s chart title tokens so the values under your cursor are readable.

Apply it as a chart formula, not in the Analysis window. It is not a strategy and it has no Buy array; it only reads two symbols that a completed run left behind.

PlotForeign( tickersymbol, name, color, style, ... ) plots another symbol’s price data in the current pane. The first argument is the ticker string, and a ticker that does not exist produces an empty plot rather than an error — which is why the spelling matters so much here.

ParamToggle( "name", "list", default ) creates a two-state control in the Parameters dialog and returns the selected index, so the chart can be reconfigured without editing code.

Two lines over the span your walk-forward run covered: an orange in-sample line and a thicker green out-of-sample line. Both start at the initial equity you configured. The out-of-sample line is continuous across step boundaries because AmiBroker scaled the segments to make it so.

Look at the out-of-sample line’s shape, not its endpoint: where it went flat, how long it stayed underwater, and whether any single stretch produced most of the movement. An endpoint tells you almost nothing that the summary report does not tell you better.

Chart it on a symbol whose history you know spans the whole run, and check that the lines begin at your configured initial equity and end on or near the last date in the preview list’s final OOS row. Then deliberately break it: change ~~~OSEQUITY to ~~~OOSEQUITY and confirm you get an empty pane with no error message. That is the failure mode you are guarding against, and seeing it once is worth a paragraph of warning.

An empty pane. Either the ticker name is misspelled, or no walk-forward run has completed in this database. The composites do not exist until a run finishes.

Yesterday’s curve. The composites are overwritten by the next walk-forward run. If you are comparing two configurations, chart or export the first before starting the second.

A curve that does not match the report. Check whether you are looking at ~~~ISEQUITY. The in-sample line usually looks considerably better, which is the entire lesson of this part in one visual.

Add a second toggle that plots the equity of a fixed-parameter baseline run — the same rules with the parameters frozen — so the value added by re-optimisation is visible as the gap between two lines rather than inferred from two tables. The lab at the end of this part builds that baseline.

A walk-forward result you cannot reproduce is an anecdote. Four mechanisms, all documented, make it an experiment.

Save the Analysis project. An Analysis Project (.APX) file is described in the official Batch documentation as self-contained: it holds everything needed to run your scan, exploration, backtest or optimization, including the formula, all options and settings, and the apply-to and range selections. Saving one before a run captures the entire configuration in a single file.

Export the result list. With a New Analysis window active, File → Export HTML/CSV writes the result list out; File → Import HTML reads a previously exported HTML file back in. The guide notes that these menu items appear only when a New Analysis window is active, which is why people conclude they do not exist.

Let the Report Explorer keep the reports. Backtest reports are generated automatically and stored, so past runs remain available without exporting anything. The walk-forward out-of-sample summary is one of those stored reports.

Write the log yourself. No file records why you chose a four-year window, or that you had already run the test twice with different targets. Keep a plain text log with the date, the formula version, the geometry, the target, the universe, the cost assumptions, the result, and — most valuable of all — what you expected before you pressed the button.

You can now build a walk-forward configuration out of documented fields rather than guessed ones, you know that Easy mode exists to stop you constructing an invalid procedure and that Advanced mode will happily let you, and you know the three places output lands: the Walk Forward tab for per-step numbers, the PS summary report in the Report Explorer for the aggregate, and ~~~OSEQUITY for the curve.

What you do not yet have is a way to judge the gap between the in-sample and out-of-sample numbers. That is the next lesson, and it is the one that decides what you do with the run.

Check your understanding

Question 1. In Easy mode (EOD), how is the out-of-sample segment defined?
Show the answer and why

Answer: It starts where the in-sample segment ends and its length equals the walk-forward step

Easy mode derives the out-of-sample dates from the in-sample end date and forces the two step values to be equal. That is precisely what makes it hard to build an invalid procedure in Easy mode.

Question 2. You typed 2023-12-31 into Last, ticked Use today, and ran the test in March. Which segments did AmiBroker generate?
Show the answer and why

Answer: Segments ending at the current date; the typed Last date was ignored

Use today overrides Last outright. The typed date is not used at all, which is why a run configured this way produces different segments every time it is repeated.

Question 3. Where does the combined out-of-sample equity curve live after a walk-forward run?
PlotForeign( "~~~OSEQUITY", "Out-of-sample equity", colorGreen, styleLine );
Show the answer and why

Answer: In a composite ticker named ~~~OSEQUITY, which you chart

It is written to a composite symbol in the database, so it is charted rather than read. Note the spelling: three tildes and OS, not OOS — a wrong name plots nothing and reports no error.

Question 4. A custom metric you added appears in the walk-forward out-of-sample summary report. What does its value represent by default?
Show the answer and why

Answer: The value from the last out-of-sample step

The default combining method is "last step value". Built-in metrics are recalculated correctly across all steps; custom metrics are only combined by the method you chose, and the report prints a note saying which one was used.

Sources for this lesson

6 verified · checked 2026-08-31

  1. 01AmiBroker User's Guide — Walk-forward testing and optimizationamibroker.com/guide/h_walkforward.html2026-08-31
  2. 02AmiBroker User's Guide — New Analysis window§ Running a Walk-Forward Test; Exporting and Importing the Result Listamibroker.com/guide/h_newanalysis.html2026-08-31
  3. 03AmiBroker User's Guide — Optimizationamibroker.com/guide/h_optimization.html2026-08-31
  4. 04AFL Function Reference — PlotForeignamibroker.com/guide/afl/plotforeign.html2026-08-31
  5. 05AmiBroker User's Guide — System test report windowamibroker.com/guide/w_report.html2026-08-31
  6. 06AmiBroker User's Guide — Using Batch window§ Analysis Project (.APX) filesamibroker.com/guide/h_batch.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.