WalkForward.Net 0.3.0-beta.1

This is a prerelease version of WalkForward.Net.
dotnet add package WalkForward.Net --version 0.3.0-beta.1
                    
NuGet\Install-Package WalkForward.Net -Version 0.3.0-beta.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="WalkForward.Net" Version="0.3.0-beta.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="WalkForward.Net" Version="0.3.0-beta.1" />
                    
Directory.Packages.props
<PackageReference Include="WalkForward.Net" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add WalkForward.Net --version 0.3.0-beta.1
                    
#r "nuget: WalkForward.Net, 0.3.0-beta.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package WalkForward.Net@0.3.0-beta.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=WalkForward.Net&version=0.3.0-beta.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=WalkForward.Net&version=0.3.0-beta.1&prerelease
                    
Install as a Cake Tool

WalkForward.Net

License

Time-series cross-validation without lookahead bias for .NET.

The Problem

Random k-fold cross-validation is broken for time series. It shuffles data, so your "test" fold may contain Tuesday's data while "training" on Wednesday's. The model learns the future to predict the past -- results look great, production performance is terrible. This is called lookahead bias.

WalkForward.Net generates temporally-correct train/test splits that respect the arrow of time, with configurable embargo gaps to prevent subtle information leakage.

Installation

dotnet add package WalkForward.Net

Targets .NET 8.0 and .NET 9.0. Zero runtime dependencies.

Quick Start

Backward-Looking Mode

using WalkForward;

// Generate folds from 10,000 data points at 15-minute frequency
var folds = new FoldBuilder()
    .WithDataPoints(10000)
    .WithDataFrequency(TimeSpan.FromMinutes(15))
    .BackwardLooking()
    .WithTrainingWindow(TimeSpan.FromDays(90))
    .WithTestWindow(TimeSpan.FromDays(7))
    .WithEmbargo(TimeSpan.FromHours(4))
    .Build();

// Use folds with your own model/strategy
var returns = new double[folds.Count];
for (var i = 0; i < folds.Count; i++)
{
    var trainData = allData[folds[i].TrainRange];
    var testData  = allData[folds[i].TestRange];

    returns[i] = MyModel.Train(trainData).Evaluate(testData);
}

// Compute aggregate consistency metrics
var metrics = Consistency.Compute(returns);
// metrics.ConsistencyPercent   -> 60.0  (3 of 5 folds profitable)
// metrics.MagnitudeConsistency -> 0.72  (Sortino-like, [0,1])
// metrics.WorstFold            -> -0.02
// metrics.AverageReturn        -> 0.022

Forward-Looking Mode

var folds = new FoldBuilder()
    .WithDataPoints(50000)
    .WithDataFrequency(TimeSpan.FromMinutes(15))
    .ForwardLooking()
    .WithTrainingWindow(TimeSpan.FromDays(30))
    .WithTestWindow(TimeSpan.FromDays(7))
    .WithStride(TimeSpan.FromDays(3))
    .WithEmbargo(TimeSpan.FromHours(4))
    .Build();

API Reference

Type Description
FoldBuilder Entry point. Configure data points and frequency, then select a mode.
BackwardLookingBuilder Backward-looking mode configuration: training/test windows, embargo, warmup, max folds.
ForwardLookingBuilder Forward-looking mode configuration: adds stride to backward-looking options.
Fold Single fold with int boundaries and Range properties for array slicing.
BackwardLookingOptions Backward-looking configuration record (used internally by BackwardLookingBuilder).
ForwardLookingOptions Forward-looking configuration record (used internally by ForwardLookingBuilder).
FoldMode Enum: BackwardLooking, ForwardLooking.
Consistency Static methods: Compute() for returns, ForClassifier() for ML accuracy.
ConsistencyMetrics Returns-based metrics: consistency %, magnitude consistency, worst fold, average return.
ClassifierConsistencyMetrics Classifier metrics: average accuracy, log-loss, consistency above baseline.

Modes

Backward-Looking

Starts from the most recent data and works backwards. Each fold uses the same fixed-size training window, placed just before its test window. Fold 1 tests the newest data, fold 2 tests the next-oldest chunk, and so on.

Use this when recent data matters most and you want to evaluate how a model trained on a fixed history performs across successive past periods.

Time ──────────────────────────────────────────────────────────►

Data:   [==================================================]

                                                         newest
                                                            ▼
Fold 1:                  [===TRAIN===]~embargo~[==TEST==]   │
Fold 2:        [===TRAIN===]~embargo~[==TEST==]             │
Fold 3: [===TRAIN===]~embargo~[==TEST==]                    │
         ▲
       oldest

All training windows are the same size. Folds are built right-to-left from the end of the dataset.

Forward-Looking

Starts from the oldest data and slides forward. Each fold advances by a configurable stride. Both training and test windows stay the same size throughout.

Use this when you want to simulate deploying a model repeatedly over time -- train on a fixed lookback, test on the next period, advance, repeat.

Time ──────────────────────────────────────────────────────────►

Data:   [==================================================]

       oldest
         ▼
Fold 1:  [===TRAIN===]~embargo~[==TEST==]
Fold 2:        [===TRAIN===]~embargo~[==TEST==]
Fold 3:              [===TRAIN===]~embargo~[==TEST==]
                                                      ▲
                                                    newest
              |------|
               stride (how far each fold shifts forward)

The stride defaults to the test window size (no overlap between test windows), but you can set it smaller for overlapping tests or larger for gaps.

Embargo

The embargo gap between training and test windows prevents information leakage from autocorrelated features. If your model predicts 4 hours ahead, the last training sample's label was computed using data that overlaps with the test window. The embargo excludes this zone.

Without embargo:  [====TRAIN====][==TEST==]
                              ^-- label leakage

With embargo:     [====TRAIN====][///GAP///][==TEST==]
                                 ^-- excluded zone

Embargo is specified as a TimeSpan and automatically converted to the correct number of data points based on your data frequency.

Classifier Consistency

For ML classification models, use Consistency.ForClassifier() with per-fold accuracy and log-loss arrays:

var metrics = Consistency.ForClassifier(
    foldAccuracies: new[] { 0.61, 0.58, 0.63, 0.60, 0.55 },
    foldLogLosses: new[] { 0.65, 0.68, 0.62, 0.64, 0.70 },
    baselineAccuracy: 0.50);

// metrics.AverageAccuracy          -> 0.594
// metrics.AverageLogLoss           -> 0.658
// metrics.ConsistencyAboveBaseline -> 100.0  (all folds above 0.50)
// metrics.FoldCount                -> 5

Requirements

  • .NET 8.0+ or .NET 9.0+
  • Zero runtime dependencies
  • AOT and trimming compatible

License

Apache 2.0

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.0-beta.1 92 3/30/2026
0.2.0-beta.1 64 3/29/2026
0.1.0-beta.1 121 3/28/2026