vike
Tools

run_walk_forward

Walk a profile forward over its anchored out-of-sample windows on the datahub and get the stitched OOS report back.

Runs an anchored out-of-sample walk-forward on the remote vike-datahub server and returns the stitched WalkForwardReport. This is the tool that asks whether a sweep's winner was an edge or a fit: a grid search returns its best row either way.

Input

FieldTypeRequiredMeaning
profilestringyesProfile TOML with [data], [strategy] and [walkforward] (plus optional [engine])
scriptstringnoRhai source, injected as [strategy.params].src

There is no split-count argument. The count rides in the profile, as [walkforward].n_splits, a first-class section like [sweep] — so one file describes the whole run and the same text can be shipped verbatim to a remote runner, which is the point of the compute-to-data verb. A profile with no [walkforward] table is a clean server-side error that quotes the two lines to add; n_splits must be at least 1, and BacktestProfile::validate rejects 0 at load.

Only the split count is configurable, deliberately: the mode is always WalkMode::Anchored and the annualization is derived by periods_per_year. Those are the same two derivations the Studio's walk-forward makes, so a profile cannot disagree with the Studio about what "walk-forward" means.

{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"run_walk_forward","arguments":{
  "profile": "[data]\nvenue = \"binance\"\nsymbols = [\"BTCUSDT\"]\nkind = \"bar\"\ninterval = \"1d\"\nfrom = \"2023-01-01T00\"\nto = \"2024-06-01T00\"\n\n[strategy]\nname = \"buy_hold\"\n\n[walkforward]\nn_splits = 4\n"
}}}

Bar mode, one series, by construction

walk_forward_strategy splits a single &[Bar] series by index, so a tick-mode or multi-symbol profile is a clean validation error — never a silent fall back to the first symbol. Every precondition is checked before the window loop, because the loop's closure cannot return one.

What the profile route buys over the Studio's DTO-shaped walk-forward is the whole [engine] surface: the fee schedule, [engine.impact], [engine.resolution], [risk], snap_to_properties, attach_funding — instead of the three flat cash/fee_rate/slippage scalars a wire DTO can carry. The strategy resolves through the same strategy_by_name registry a plain run uses — once up front as a pre-flight, so a bad name fails before the window loop, then rebuilt inside the closure because each window needs a fresh strategy — the bars are loaded through the same helpers, and each window is a fresh run at engine.cash, so a walk-forward can never disagree with a single backtest about what the profile's [engine] meant.

What comes back

{ "walkforward": … } wrapping a WalkForwardReport:

FieldMeaning
windowsone entry per OOS window: test_range as (start, end) bar indices, and that window's oos_return
oos_equity_curveevery window's curve rebased onto one running equity
oos_returnthe stitched fractional return over the whole walk
oos_sharpeSharpe of the stitched curve, under the derived annualization
wf_consistencythe fraction of windows that were profitable out of sample

The stitch is what makes the curve readable as one line: each window runs fresh at engine.cash, and its curve is rebased onto the running equity that the previous window ended at. So oos_return compounds the windows rather than averaging them, and wf_consistency answers the different question — how many windows worked, not how much they made. A strategy with one enormous window and three losing ones has a good oos_return and a wf_consistency of 0.25, and the second number is the one that should stop you.

Read wf_consistency as the overfitting input, not as a score

It is the input the overfitting verdict consumes, not a verdict itself. The anti-overfitting statistics live in analytics/overfitting; walk-forward supplies them with honest out-of-sample windows.

Failure modes

Identical to the other two run tools. The profile ships verbatim, so a shape error surfaces from the server as profile parse/validate failed: … and arrives as an isError result; an unreachable datahub is cannot connect to datahub at … and never a panic (remote_run_tools_without_a_reachable_datahub_are_clean_errors); and every Run* verb is control scope on the server because it compiles client-supplied Rhai, so a keyed datahub refuses this tool at connect rather than one round trip later.

The prompt

Walk this strategy forward over four anchored splits and tell me whether the edge holds out of sample.

The natural order is run_sweep to find a candidate, then this to test it. Walk-forward is the concept page, vike-cli walkforward the human twin, and Sweep and walk-forward the worked run.

On this page