vike
TraderReferenceCli

Walk-forward

Validate a run over out-of-sample windows — `vike-cli backtest run` over a profile carrying a [walkforward] table, which replaced the retired top-level `walkforward` verb.

This verb moved — it is `vike-cli backtest run` now

Walking forward is how a run is validated, not a different kind of run, so it stopped being a verb of its own. Put a [walkforward] table in the profile and run vike-cli backtest run with the same file: n_splits is the window count and mode/rank_by shape it.

was:  vike-cli walkforward     --profile wf.toml
now:  vike-cli backtest run    --profile wf.toml

The old spelling is refused by name with that pairing printed — vike-cli carries it in crates/vike-cli/src/lib.rs's RETIRED_COMMANDS, so a pasted old command tells you what to type rather than reading as a typo.

⚠ There is no --local. The standalone engine has no walk-forward driver to spawn, so unlike a plain backtest run this one has only the remote route.

The anchored out-of-sample sibling of backtest. Ship a profile's TOML verbatim to a remote vike-datahub server, run the walk-forward there — the existing vike_backtest::harness::run_walkforward, next to the data — and print the stitched out-of-sample result, with no DataFusion in this side's build graph (crates/vike-cli/src/cmd/walkforward.rs).

usage: vike-cli walkforward --profile <run.toml> [--addr 127.0.0.1:7878] [--json]
flagmeaning
--profile <path>required. A backtest profile .toml, shipped verbatim. Its [walkforward] table supplies n_splits, the number of anchored out-of-sample windows
--addr <host:port>the data service address; default 127.0.0.1:7878
--jsonprint the server's WalkForwardReport JSON
-h, --helpprint the usage to stdout and exit 0

[walkforward] is a first-class profile section like [sweep], so one file describes the whole run — see run profiles. A profile with no [walkforward] table comes back as a clean server-side error. Reach a remote server over ssh -L 7878:localhost:7878 <host>.

Bar mode, one series

A tick or multi-symbol profile is a clean error, never a silent fallback

Server-side this is bar mode over one series: the splitter divides a single bar series by index. A tick profile or a multi-symbol profile is refused outright rather than quietly running on the first symbol it finds — which would produce a plausible report about a different experiment than the one the profile describes.

Why the profile crosses the wire whole

Like the sweep sibling, this replaced a client-side profile→DTO mapping whose WireSlice/WireEngineParams pair could not carry [engine].fee and the rest of the [engine] surface. The server now parses the profile with the one BacktestProfile::from_toml_str parser, so the walk-forward honours the whole [engine] — the cost model and market impact a run was configured with are the ones it actually ran under. The Studio's DTO-shaped RunWalkforward wire verb is untouched and still serves the GUI (remote runs).

The output

One row per out-of-sample window, then the summary line. Every number is the server's own — nothing is recomputed on this side.

walk-forward: 2 out-of-sample window(s)
window  test_range             oos_return
     1  [0, 60)                    +5.00%
     2  [60, 120)                  -2.00%

oos_return = +2.90%   oos_sharpe = 0.810   wf_consistency = 50.0%

test_range is the window's half-open bar index range as the server reported it. The three summary scalars are the stitched out-of-sample return, its Sharpe, and the walk-forward consistency — the fraction of windows that came back positive. What each one is for, and the trap of reading a single number off a small number of windows, is on walk-forward and validation.

A degenerate report renders rather than breaking: a numeric field that is absent or null — which is serde_json's encoding of a non-finite f64 — reads as 0.0, so a run with no windows still prints a table instead of failing at the printer.

Under --json the bytes are the server's own WalkForwardReport, including the oos_equity_curve the human table does not draw.

The usual order is a sweep to pick a parameter point, then this verb over the winner; overfitting is why the second step is not optional. Running a backtest covers running the same profile as a single in-sample run first.

On this page