Skip to content
Friday, 13 November 2026 · LondonENع
Rayan Azhari.Sustainability · Energy · Carbon · Built Environment · Data Science
Production Quant Trading

Purged Cross-Validation and Train/Serve Skew: Four Gates Before an ML Model Trades

When the strategy is a machine-learning model, standard validation lies to you: overlapping labels leak across a naive k-fold split and manufacture a phantom score. Here are the four mechanism-level gates I make any live ML model clear before it touches capital, and the war-story of a model that looked excellent until I purged and embargoed the folds and watched it collapse.

Rayan AzhariChartered Environmentalist, MISEP · 9 min read

The first model I nearly funded looked excellent. It was an FX classifier, gradient-boosted, fed a few dozen features, and under standard five-fold cross-validation it posted a score I would have been proud to show anyone. The folds were consistent. The out-of-fold predictions tracked the labels. Every instinct I had said this thing had learned something real. Then I purged and embargoed the folds, which is to say I dropped from each training set the samples whose labels overlapped in time with the test set, and the score collapsed. Not softened. Collapsed, most of the way to a coin flip. The model had never learned to predict the market. It had learned to read its own test set through the overlap in its labels, and naive k-fold had handed it the answer key.

That is the trap I want to describe, because it is specific to machine-learning strategies and none of the disciplines that keep an ordinary rule-based system honest will catch it. A parameter set is small, static, and legible: you can diff it, eyeball it, reason about it. A fitted model is big, opaque, leaks in ways a threshold never can, and it goes stale. The moment one is in the loop, it inherits every "suspicion over celebration" rule I apply to any strategy, plus four gates that are its alone. This is a field note from the paid half of my book. I will give you the four gates and the mechanism behind each, and keep the full triple-barrier and purged-CV implementation for the book itself.

Why a model owes you more than a strategy

Draw the line cleanly, because most writing on financial machine learning blurs it. What I do not teach, in the book or here, is the alpha: which features carry signal, which architecture to fit, how to search the model space. That is a catalogue of strategies, and it is deliberately out of scope. What I insist on is the lifecycle discipline, because a fitted model is just another claim to be validated, and the moment it touches capital it owes proof.

The reason it owes more proof than a parameter set is structural. Every one of the four gates below is a way a model passes validation cleanly and then fails live, and not one of them is covered by the checks that already keep a rule-based strategy honest. A model can clear my whole ordinary promotion spine, the overfitting gate, the survival gate, the operations gate, and still be worthless, because the score that got it through the overfitting gate was a lie manufactured by leaking labels. So it gets four more.

Figure

Four gates before a model trades

A machine-learning strategy owes you these four before a single live bar. A blank on any one caps the verdict at unconfirmed.

  1. 1

    Purged and embargoed cross-validation

    kill label leakage across overlapping folds

  2. 2

    No train/serve skew

    the live feature code is the training feature code, asserted feature by feature

  3. 3

    No look-ahead in the features

    run the corrupt-the-future test across the whole feature matrix

  4. 4

    Calibration and decay monitoring

    the edge has a half-life, so pre-commit a retraining policy

A retrained model is a new, unvalidated strategy, so it re-enters at gate one.

Source: Building a Production Quant Trading System (Titan)

Gate 1: purged and embargoed cross-validation

Standard cross-validation rests on one assumption: the samples are independent. In financial machine learning they routinely are not, and the reason is the label. A useful label is usually built from a forward window: did price touch the upper barrier before the lower one within the next twenty bars? That is the triple-barrier idea, and it is sound. But it means a sample's label overlaps in time with its neighbours' labels, because their forward windows overlap. Put one neighbour in the test fold and the others in the training fold, and train and test now share information through those overlapping windows. The model is partly tested on data it trained on. The score inflates, and you deploy a model that looked predictive only because its evaluation leaked.

Two corrections make the fold boundary honest. Purge: drop from the training set every sample whose label window overlaps the test window, so no shared-information sample straddles the boundary. Embargo: drop a small buffer of training samples immediately after the test window as well, because serial correlation leaks a little past the exact overlap. The embargo is the seatbelt on the purge.

Skip this and the model's cross-validated score is the same lie as a look-ahead backtest wearing a cross-validation costume. It is worse than an ordinary look-ahead leak, because it passes every other gate: the returns in the leaked evaluation really happened, under a model that really fit the leaked data. Nothing looks broken. The only thing that catches it is refusing to trust a naive k-fold score for any label with a forward window.

Chart

What the overlapping labels were leaking

A model's cross-validated score on the same data and features under two regimes. The gap between them is the information a naive split leaks across folds. Illustrative and sanitised; the no-skill baseline sits near 0.5.

Naive k-fold (inflated)0.7Purged + embargoed CV (honest)0.5
Source: Building a Production Quant Trading System (Titan), illustrative

That figure is the whole gate in one picture. The same model, the same data, the same features: naive k-fold on the left reports a strong score, purged and embargoed CV on the right reports the honest one. The gap between them is not noise. It is the exact amount of information the overlapping labels were leaking, and it is the amount by which you would have overpaid for a phantom edge.

Gate 2: no train/serve skew

The second gate lives one layer earlier than the signal, down in the features. When I validate an ordinary strategy I prove the live signal path equals an independent research reference. For a model, the dangerous divergence moves into the inputs. The pipeline that computes a feature online, bar by bar from a streaming buffer, must compute the same number as the pipeline that computed that feature offline, in a vectorised batch, during training.

When they disagree, the model is scoring features it was never trained on, and its behaviour is undefined. The ways they disagree are mundane and lethal: a different rolling-window edge case at the start of the buffer, a different fillna, a library version that changed a default, a feature that used a full-series statistic in training and a causal one live. This is train/serve skew, and it is the single most common way a validated model underperforms live while every dashboard stays green. The model is robust enough to mask one skewed input, right up until the day it is not.

The defence is parity, pointed at the features, not the signal. Run the live feature pipeline and the training feature pipeline over the same synthetic input and assert they agree feature by feature, not just at the final prediction. A signal-level parity test can pass while a single feature quietly skews, because the model absorbs it. The portable rule: the live feature code and the training feature code must be the same code, and you must have a test that proves it, because the model is only ever as valid as its features are identical.

Gate 3: no look-ahead in the features

The third gate is one I have written about for whole strategies, and it applies with full force to a feature matrix. The definition of causality is simple: nothing computed at or before time T may depend on any price after T. So test exactly that. Pick a cut date, compute your features on the clean series and keep the slice up to the cut, then compute them again on a copy in which every value after the cut has been corrupted, wrecked, multiplied, reversed, replaced with noise, and keep that slice too. Assert the two slices are identical. If a feature before the cut moves when you poison the future, that feature is reading ahead.

For an ordinary strategy I run this on the signal. For a model I run it on the whole feature matrix, because any one leaking feature is enough to inflate the model, and the leak is often buried in exactly the routine transforms that look most innocent: a z-score over the full series, a forward-filled higher-timeframe value that time-travels back to the morning, a two-sided smoother whose current value depends on points to its right. None of these looks like cheating. Each reads as tasteful numerical code. A poisoned copy of the data does not care how tasteful the code is; it only asks whether the answer changes when data that should be invisible changes. Run corrupt-the-future across every column before the model is allowed to score a single live bar.

Gate 4: calibration and decay monitoring

The first three gates get a model to the starting line. The fourth is the one no rule-based strategy ever faces: a model goes stale. A parameter set is static, so once it is validated it stays validated. A model's edge has a half-life, and a model that was honest in January can be quietly wrong by June because the market it learned has moved on.

So a live model owes two things the moment it starts trading. First, calibration: when the model says seventy per cent, does the event happen roughly seventy per cent of the time, still, this month, not just on the validation set? A model can keep its ranking and lose its calibration, and a miscalibrated model breaks every sizing decision downstream of it. Second, decay monitoring: track the live edge against its validated baseline and pre-commit, in writing, to what you do when it fades. Do you retrain on a fixed cadence or on a trigger when drift fires? Either is defensible. Retraining by vibe is not.

The trap inside this gate is the seductive one: a retrained model is a new, unvalidated strategy, not a maintained one. "Same architecture, just newer data" quietly makes the deployed object a different thing from the validated object, and the honest move is to send the retrained model back through Gates 1 to 3 and earn a fresh verdict before it takes capital again, exactly as a brand-new model would.

The portable rule: the four-gate ML checklist

Take this if nothing else. Before a machine-learning model trades a single live pound, it clears four gates, and a blank on any line caps the verdict at "unconfirmed", which means the model does not exist yet, not that it is bad.

  1. Purged and embargoed CV. The score is computed with the label overlaps purged from training and an embargo buffer after each test window. A naive k-fold score does not count.
  2. No train/serve skew. The live feature pipeline is the same code as the training one, proven by a feature-by-feature parity test on identical input.
  3. No look-ahead in the features. Corrupt-the-future passes across the whole feature matrix: poison every price after a cut, assert no feature before the cut moves.
  4. Calibration and decay monitoring. The model is calibrated on recent live data, its edge is tracked against baseline, and there is a written retraining policy that re-runs Gates 1 to 3 on any retrained model.

Pin it above the desk next to whatever promotion spine you already run for rule-based strategies. It is not advice about what to model. It is the set of gates that decide whether you are allowed to believe a model's score yet.

Where the machinery lives

I have deliberately not shipped the implementations here: the triple-barrier labelling, the purged-and-embargoed cross-validator, the feature-parity harness, the calibration and decay monitors, the sealing that makes the deployed model byte-identical to the validated one. Those, with the exact schema and the code, are in the paid half of the book, Building a Production Quant Trading System, a living digital copy on Leanpub and a print paperback on Amazon. The sanitised, Apache-2.0 companion framework on GitHub shows the layout these gates live in and a runnable version of the corrupt-the-future test you can point at a feature matrix today.

Carry one sentence out of here: a machine-learning model's cross-validated score is a claim to be stress-tested, and if its labels have a forward window, a naive k-fold score is not a claim, it is a phantom.

This is an engineering essay, not investment advice, and it contains no tradable strategy. All figures are illustrative and sanitised, and the war-stories are about bugs, not profits.

Figure

Four gates before a model trades

A machine-learning strategy owes you these four before a single live bar. A blank on any one caps the verdict at unconfirmed.

  1. 1

    Purged and embargoed cross-validation

    kill label leakage across overlapping folds

  2. 2

    No train/serve skew

    the live feature code is the training feature code, asserted feature by feature

  3. 3

    No look-ahead in the features

    run the corrupt-the-future test across the whole feature matrix

  4. 4

    Calibration and decay monitoring

    the edge has a half-life, so pre-commit a retraining policy

A retrained model is a new, unvalidated strategy, so it re-enters at gate one.

Source: Building a Production Quant Trading System (Titan)

Chart

What the overlapping labels were leaking

A model's cross-validated score on the same data and features under two regimes. The gap between them is the information a naive split leaks across folds. Illustrative and sanitised; the no-skill baseline sits near 0.5.

Naive k-fold (inflated)0.7Purged + embargoed CV (honest)0.5
Source: Building a Production Quant Trading System (Titan), illustrative

Further reading

Quant field notes, part 18 of 25

Related posts

Cannot Trade a US ETF in the UK: Streaming Data, PRIIPs and the Substitute Pattern

Under PRIIPs, a UK or EU retail account can stream a US-listed ETF's market data yet be forbidden from ever holding it, because the fund publishes no Key Information Document. Here is the production pattern I use when my cleanest signal lives on an instrument I am not allowed to trade: compute the signal on the data-only line, trade a UCITS substitute, and match the substitute on currency, not just correlation. The broker catalogue, not the alpha, defines your tradable universe.

· 9 min

Live Trading Does Not Match the Backtest: The Code-Level Causes Nobody Names

When your live P&L drifts from the backtest you validated, the culprit is almost never psychology. It is code: the same metric computed two subtly different ways in research and in the live sizing path. Here is the parity oracle I now gate on, and the deeper rule behind it: live and research must call the same code, not two copies of it.

· 9 min

Essays in your inbox

New writing on Syria, sustainability and finance, a few times a month.

Unsubscribe anytime. Read by 4,200+ professionals.