All articles
Strategies·June 3, 2026·5 min read

Walk-Forward Optimisation for Crypto Strategies in Python

Demonstrates an anchored walk-forward loop using scikit-learn's TimeSeriesSplit on Hyperliquid BTC perp minute bars, with out-of-sample parameter stability checks. Explains how to detect if a strategy is genuinely robust or just benefiting from lucky in-sample windows.

Most crypto strategy developers backtest once, find parameters that look great, and ship. That workflow produces curve-fitted noise. Walk-forward optimisation (WFO) is the corrective: you fit parameters on a rolling training window and evaluate immediately on the unseen period that follows. Repeated across many folds, it tells you whether your strategy is genuinely capturing a market edge or just memorising one regime's quirks. Here is how to do it properly on Hyperliquid BTC perpetual minute bars.

Why Standard Backtests Lie to You

A single in-sample optimisation lets you pick the best parameter set from hundreds of candidates — but the selection process itself consumes degrees of freedom. The more parameters you search, the wider the gap between in-sample and live Sharpe becomes. On a liquid, fast-moving market like Hyperliquid BTC-PERP, the overfitting premium can exceed 0.5 Sharpe units easily. The standard fix — holding out a test set — is better, but still fragile: your test set becomes implicitly contaminated the moment you look at it and decide to continue or abandon the strategy.

WFO solves this by formalising the train/test boundary and repeating it many times so you accumulate enough out-of-sample (OOS) observations to draw statistically meaningful conclusions.

Setting Up the Data and Split

Pull minute OHLCV from Hyperliquid's REST API (endpoint /info, message type candleSnapshot). For this example assume you have a DataFrame df indexed by UTC timestamp with columns open, high, low, close, volume, covering six months — roughly 260,000 rows.

from sklearn.model_selection import TimeSeriesSplit
import numpy as np, pandas as pd

N_SPLITS = 8          # 8 folds → ~3 weeks IS, ~1 week OOS each
GAP       = 1440      # 1-day gap between IS tail and OOS head (prevents look-ahead leakage)

tscv = TimeSeriesSplit(n_splits=N_SPLITS, gap=GAP)

TimeSeriesSplit with gap is the correct tool here. The gap parameter drops GAP rows between training tail and test head, which eliminates leakage from signals that span the boundary (e.g., a 4-hour momentum signal still resolving at fold edge).

Do not use the expanding-window variant blindly. Anchored (expanding) WFO is appropriate when you believe market structure is stationary and all history is informative. Rolling WFO — fixed-size training windows — is preferable when regimes shift frequently. For Hyperliquid, which launched in late 2023 and has seen multiple liquidity regimes, start with rolling windows of roughly 30 days IS and 7 days OOS.

The Optimisation Loop

Inside each fold, run a brute-force grid search or Bayesian optimisation over your parameter space. Keep the parameter space small — ideally two or three dimensions. More than four free parameters on intraday bars is almost always overfit.

results = []

for fold_idx, (train_idx, test_idx) in enumerate(tscv.split(df)):
    train = df.iloc[train_idx]
    test  = df.iloc[test_idx]

    best_params, best_is_sharpe = grid_search(train, param_grid)
    oos_sharpe = evaluate(test, best_params)

    results.append({
        "fold":        fold_idx,
        "params":      best_params,
        "is_sharpe":   best_is_sharpe,
        "oos_sharpe":  oos_sharpe,
    })

grid_search and evaluate are thin wrappers around your strategy's signal generation and PnL calculation. Keep them vectorised with NumPy; a pure-Python per-bar loop on 260k rows will be too slow to iterate.

Reading the Results Table

Once you have eight folds, the numbers you care about are:

  • IS/OOS Sharpe ratio degradation — average oos_sharpe / is_sharpe. Ratios above 0.7 are encouraging; below 0.4 suggests overfitting.
  • Parameter stability — do the best parameters cluster tightly across folds, or scatter across the full grid? High variance in winning parameters is a red flag even if OOS Sharpe looks acceptable.
  • OOS equity curve — concatenate the OOS equity from all folds into a single time-series. A drawdown in the concatenated curve that does not appear in any individual fold's IS period is a regime the strategy cannot handle.

A concrete failure mode: a mean-reversion strategy on BTC-PERP that ran beautifully during the tight-spread, range-bound weeks of early 2024 but was wiped out during the momentum-driven March rally. The WFO table showed IS Sharpe of 2.1 and OOS Sharpe of 0.3 — a degradation ratio of 0.14. That number alone would have prevented a live deployment.

Parameter Stability as a Gating Criterion

Before signing off on a parameter set for live trading, compute the coefficient of variation (CV) across folds for each parameter:

param_df = pd.DataFrame([r["params"] for r in results])
cv = param_df.std() / param_df.mean()
print(cv)

If CV for any parameter exceeds 0.5, the strategy is selecting different regimes on each fold — it has no stable edge. Acceptable CV thresholds are domain-dependent but 0.2–0.3 is a reasonable gate for intraday crypto. When parameters are stable and OOS degradation is modest, you have genuine evidence of robustness, not luck.

Deploying the Final Parameters

Do not average the best parameters across folds and deploy that average. Instead, re-fit on the full available history using the parameter range that proved stable (the tight cluster, not the full grid). This is the production parameter set. Re-run WFO monthly or after any significant structural change in the market — a new large liquidity provider, a funding rate regime shift, a major listing event — whichever comes first.

One practical note: on Hyperliquid, funding payments hit every hour and can dwarf signal PnL on short-duration strategies. Your WFO framework must account for funding in the cost model, or you will optimise for the wrong thing entirely.


If you want these techniques applied to a live strategy — with proper execution infrastructure, monitoring, and continuous re-optimisation — talk to us. TierZero designs and runs production trading bots on Hyperliquid, Solana and Polymarket.

Need a bot like this built?

We design, build and run trading bots on Solana, Hyperliquid and Polymarket.

Start a project
#strategies#python#walk-forward#optimisation#hyperliquid#backtesting#quantitative