Quant Memo
Core

Causal Padding and Look-Ahead Leakage

Standard convolution padding centers each kernel on its position and secretly uses future timesteps to compute the present; causal padding pads only on the past side so a prediction at time t can never depend on data after t.

Prerequisites: Receptive Fields and Dilation, One-Dimensional Convolutions for Price Series

A convolution layer slides a small kernel across a sequence, and the standard ("same") padding scheme centers that kernel on each output position so the output shape matches the input shape. For images, centering is harmless — there is no "before" or "after" a pixel. For a time series, centering means the kernel's output at time tt silently includes inputs from after tt too, which is exactly the information a real forecast at time tt would never actually have.

The analogy: never read tomorrow's newspaper

A detective solving today's case must never sneak a look at tomorrow's newspaper for clues — that would invalidate the whole investigation, even if the peek happens buried inside some innocuous-looking procedure. Any layer that lets a prediction at time tt depend, even partially, on data from after tt has done exactly this, whether or not it looks like cheating on the surface.

The mechanics

For a kernel of size kk and dilation dd, "same" padding splits (k1)×d(k-1) \times d padding values evenly across both sides of the sequence, so the kernel window centered at position tt reaches both before and after tt. Causal padding instead places all (k1)×d(k-1) \times d padding on the left (past) side only:

outputt=j=0k1wjxtjd\text{output}_t = \sum_{j=0}^{k-1} w_j \, x_{t - j \cdot d}

In words: the output at time tt is a weighted sum built exclusively from xtx_t and earlier values — never from xt+1x_{t+1} or beyond — because every index in the sum is tt minus something non-negative.

Worked example 1: which positions get touched

Kernel size 3, sequence x1,,x6x_1, \dots, x_6. Under same padding, the output at position 44 uses x3,x4,x5x_3, x_4, x_5 — it depends on x5x_5, which lies in the future relative to t=4t=4. Under causal padding, the output at position 4 uses x2,x3,x4x_2, x_3, x_4 — entirely past-and-present, never future.

Worked example 2: a value that shouldn't matter but does

Weights w=(0.2,0.5,0.3)w=(0.2, 0.5, 0.3) (oldest to newest in the window), and suppose x3=1,x4=2x_3=1, x_4=2. Under causal padding, output4=0.2(x2)+0.5(x3)+0.3(x4)\text{output}_4 = 0.2(x_2) + 0.5(x_3) + 0.3(x_4) — changing x5x_5 afterward has zero effect on this number, by construction. Under same padding, output4=0.2(x3)+0.5(x4)+0.3(x5)\text{output}_4 = 0.2(x_3)+0.5(x_4)+0.3(x_5): if x5x_5 later changes from 33 to 3030, the already computed output at position 4 changes too — a live model, computing this in real time, could never have known x5x_5 yet, so this "prediction" for time 4 was never actually producible at time 4.

causal padding only past padded same padding future leaks in
Causal padding (left) pads only the past side, so the output for a position (red outline) never reaches past itself. Same padding (right) centers the kernel, so the output secretly depends on a future position.
causal: output(4) depends on x2, x3, x4 only same: output(4) depends on x3, x4, x5 — future leaks in
Red is the output position (t=4); accent circles are the past positions it legitimately depends on; the amber circle under "same" padding is a future position leaking into a supposedly present-time output.

Standard "same" padding centers a convolution kernel on each position, which for time-ordered data means the output at time t silently depends on inputs after t; causal padding places all padding on the past side only, guaranteeing the output at t depends exclusively on data at or before t.

What this means in practice

This exact bug is one of the most common ways a backtested time-series model looks excellent in-sample and then fails once deployed live — if any layer touching time-ordered data used symmetric or "same" padding, the reported validation accuracy is contaminated by future information the model would never actually have at prediction time.

The leakage from non-causal padding is silent. The model trains normally, the loss goes down, and offline validation metrics look fine — because during offline evaluation, "future" data is sitting right there in the dataset too. The failure only shows up live, where the future genuinely doesn't exist yet, which is exactly why every convolutional or sequence layer touching time-ordered financial data needs to be explicitly checked for causal padding, not just RNNs, which are causal by construction.

Related concepts

Practice in interviews

Further reading

  • van den Oord et al., WaveNet: A Generative Model for Raw Audio (2016)
ShareTwitterLinkedIn