Note

Point-in-time data and the shapes lookahead takes

Lookahead is rarely a line of code that reads tomorrow's price. It is usually a dataset that quietly knows how the story ended, and the correction is a property of the data rather than of the model.

Research method

Everyone knows not to use future information. Almost every backtest does anyway, because the information does not arrive labelled as future. It arrives inside a dataset that was assembled after the fact and reflects, in a dozen small ways, knowledge of how things turned out.

The defence is not vigilance in the model. It is a property of the data: every value must be retrievable as it stood at the moment the strategy would have seen it, and not as it stands today. That property is what point-in-time means, and most conveniently available data does not have it.

Restatement

Fundamental data is revised. Earnings are restated, macroeconomic series are revised for months after first release, and index-level aggregates are rebuilt as constituents change. A database that stores one value per field per period stores the final value, which is the one nobody had at the time.

A point-in-time store needs two time axes, not one: the period the value describes, and the date on which that value became known. A query then asks for what was known as of a given date, which is a different question from what is true about a given quarter. Databases built without that second axis cannot answer it later, because the information was discarded on overwrite rather than being unavailable.

The effect is not evenly distributed. Revisions correlate with conditions. A macro series revised heavily is usually revised around turning points, which is exactly where a strategy is being asked to act.

Survivorship, and its quieter relatives

Survivorship is the widely known case: a universe of instruments that exist today omits those that failed, and a strategy tested on it has been handed the answer to the only question that mattered.

Two related forms are less discussed and equally damaging.

Index membership. Testing a strategy on current index constituents over a long history embeds every addition decision. Firms are added after they grow. A strategy that buys index members has, on that data, been buying firms selected partly for having already performed. The correct object is the membership list as of each date, which is a separate and harder dataset to obtain.

Delisting returns. Even a survivorship-free universe usually mishandles the end. An instrument that stops trading has a final return that is often severely negative and is frequently recorded as missing. Dropping it treats a total loss as no observation, which biases every aggregate computed from it.

Corporate actions and the reconstructed past

Adjusted price series are convenient and are a reconstruction. A split-adjusted history did not exist before the split; a dividend-adjusted series encodes payments that had not been declared.

For most signal research this is acceptable and standard. It stops being acceptable at two points. Where a strategy depends on price levels rather than returns, such as anything involving round numbers, strike selection or nominal thresholds, adjusted history is simply the wrong series. And where the adjustment factor itself is revised, which happens, the history changes retroactively and a result computed last year will not reproduce today.

Timestamps, which are the most common failure

The largest single source of lookahead in intraday work is not conceptual at all. It is that a timestamp means something other than what was assumed.

A bar labelled 09:30 may open at 09:30 or close at 09:30. A vendor timestamp may record when an event occurred at the venue, when the vendor received it, or when it was written. A fundamental record may carry the period end rather than the release datetime. Each of these differences is small and each is enough to leak the future, because a bar closing at 09:30 contains everything up to 09:30 and acting on it at 09:30 is acting on information from an instant that has not finished.

The discipline is mechanical. Establish for every field what its timestamp denotes, in writing. Convert everything to a single convention, preferably event time in UTC with the venue session recorded separately. Then apply the rule that a strategy may only use data whose timestamp is strictly earlier than its decision time, and enforce it in the engine rather than trusting each piece of research to remember.

Label leakage, which is lookahead in the target

In supervised work the target is constructed from the future by definition. That is not the problem. The problem is when the target's window overlaps the features of a later observation, so that samples share outcome information and are no longer independent.

A label defined over the next twenty bars means consecutive observations share nineteen bars of outcome. Under random cross-validation, a training sample and a validation sample can be one bar apart and share almost all of their future. The model does not need to generalise; it needs to recognise. The reported score is high and unattainable.

Purging removes training samples whose label windows overlap the validation set, and embargoing additionally drops a buffer after it to account for serial correlation. Both are necessary and neither is sufficient on its own. The general form of the problem, and why splitting time series at all requires care, is taken up in walk-forward validation for intraday strategies.

The universe was chosen with hindsight too

The subtlest form is selection of the research object. An instrument chosen because it is known to have been interesting, a period chosen because it is known to contain a regime, a parameter range chosen because a first pass suggested where the good region was. Each individually feels like reasonable judgement. Together they are a search conducted with knowledge of the answer, and the resulting result carries none of the significance it appears to.

This does not have a technical fix. It has a procedural one: state the universe, the period and the parameter ranges in writing before running anything, and record how many specifications were tried. A result from the twentieth specification is a different claim from a result from the first, and the difference cannot be recovered afterwards from the final number alone.

What to actually check

  • Two time axes on every fundamental or macro field: as-of date and effective period.
  • Universe membership reconstructed per date, including delisted names with their final returns.
  • A written statement, per field, of what its timestamp denotes, and a single enforced convention.
  • Strict inequality between data timestamp and decision timestamp, enforced by the engine.
  • Purged and embargoed splits wherever labels are built from overlapping windows.
  • A record of specifications tried, kept from the beginning rather than reconstructed.

Most failures to reproduce a research result are failures on this list rather than in the model. It is also the cheapest list to work through, since almost all of it is checkable before any modelling begins.