Statistics for Traders #15: Stationary bootstrap on the 196-release NFP × USDJPY |move_pips| series — the plain iid bootstrap gives [33.03, 43.67] for the mean, the block-bootstrap correction (E[L]=10) widens it 74% to [28.99, 47.48]
Stats #10 showed the 196-release NFP × USDJPY 15m |move_pips| series has lag-1 autocorrelation +0.26 — canonical volatility clustering, well outside the ±0.14 IID band. Stats #12 used Efron 1979’s plain iid bootstrap and flagged in-body that the correct upgrade for autocorrelated series is the Politis-Romano 1994 stationary bootstrap (yesterday’s Paper Trail #14). Today is that upgrade, worked end-to-end.
Sample statistic to estimate: θ̂ = mean |move_pips| = 38.19p across all 196 non-contaminated NFP × USDJPY releases. The plain iid bootstrap gives a 95% CI of [33.03, 43.67] pips, width 10.63p. That’s wrong — under the plain bootstrap’s iid assumption, and the assumption doesn’t hold here. The Politis-Romano stationary bootstrap with mean block length E[L] = 10 (p = 0.10) gives [28.99, 47.48], width 18.49p — 74% wider than the iid CI. That widening is the price of admitting the autocorrelation.
![Horizontal comparison of bootstrap 95% confidence intervals for the mean |move_pips| of the 196-release NFP × USDJPY 15m series. Four bars: plain percentile bootstrap (iid) at [33.03, 43.67] width 10.63 pips in green, and three stationary bootstrap CIs — p=0.20 E[L]=5 at [30.57, 46.33] width 15.77p in green, p=0.10 E[L]=10 at [28.99, 47.48] width 18.49p in coral (the ledger's default choice), and p=0.05 E[L]=20 at [27.72, 48.11] width 20.39p in green. All four bars center near the sample mean θ̂ = 38.19p; the stationary bootstrap CIs are visibly wider than the iid one, and the width grows monotonically with block length. Vertical black line marks the sample mean.](/insights/stats-for-traders-stationary-bootstrap/ci-widths.png)
scripts/insights-charts/stationaryBootstrap.ts with mulberry32 seed 42, B = 20,000 resamples per column.The comparison table
| Method | p | E[L] | 95% CI lo | 95% CI hi | Width | vs iid |
|---|---|---|---|---|---|---|
| Plain percentile (iid) | 1.00 | 1 | 33.03 | 43.67 | 10.63p | baseline |
| Stationary bootstrap | 0.20 | 5 | 30.57 | 46.33 | 15.77p | +48% |
| Stationary bootstrap | 0.10 | 10 | 28.99 | 47.48 | 18.49p | +74% |
| Stationary bootstrap | 0.05 | 20 | 27.72 | 48.11 | 20.39p | +92% |
All four rows use B = 20,000 resamples with the same seeded PRNG (mulberry32, seed 42) so the differences across rows come entirely from the sampling procedure, not from Monte-Carlo noise. The CI center is essentially the same in all four rows (~38.2p), matching θ̂ — bootstrap estimates the distribution of the statistic, not the value.
Walking through the algorithm on this sample
For each of the B = 20,000 bootstrap iterations at p = 0.10 (E[L] = 10):
- Pick a starting index i_0 uniformly at random on {1, ..., 196}.
- For t = 1 to 195: draw u ~ Uniform(0, 1). If u < 0.10, restart: draw i_t uniformly on {1, ..., 196}. Otherwise continue: i_t = (i_{t-1} + 1) mod 196.
- Form the pseudo-series Y_t = |X|_{i_t} of length 196.
- Compute θ*_b = mean(Y_1, ..., Y_196). Store it.
After 20,000 iterations, sort the {θ*_b} values and take the 2.5% and 97.5% percentiles. Those are the CI bounds. The exponential block-length distribution means most blocks are short (mode 1) but a heavy tail includes occasional long blocks — E[L] = 10 with P(L=1) = 0.10 and P(L ≥ 30) ≈ 0.042.
Why the widening is exactly what theory predicts
For a stationary process with autocovariance sequence R_k, the variance of the sample mean is
Var(X̄) = (1/n) · [ R_0 + 2·Σ_{k=1..n-1} (1 - k/n) · R_k ] Under iid: R_k = 0 for k ≥ 1, so Var(X̄) = R_0 / n = σ² / n. Under autocorr: Σ ρ_k · (1 - k/n) is POSITIVE, so Var(X̄) inflates.
For this |move_pips| series with sample sd = 37.66p and n = 196:
iid variance = σ²/n = 37.66² / 196 ≈ 7.24 iid SE(X̄) = √7.24 ≈ 2.69p iid 95% CI half-width = 1.96 · 2.69 ≈ 5.27p → CI width ≈ 10.55p AR(1) inflation (Stats #10) = (1 + rho) / (1 - rho) = 1.702 n_eff (AR(1)) = 196 / 1.702 ≈ 115 AR(1) SE(X̄) = 37.66 / √115 ≈ 3.51p AR(1) 95% CI half-width = 1.96 · 3.51 ≈ 6.88p → CI width ≈ 13.77p
The plain bootstrap CI width (10.63p) essentially matches the iid formula (10.55p) — as expected because the plain bootstrap IS the iid formula’s nonparametric analog. The stationary bootstrap CI at E[L] = 5 is width 15.77p— wider than the AR(1) formula’s 13.77p, because the AR(1) formula only counts lag-1 autocorrelation; the stationary bootstrap implicitly counts all lags in the block-length distribution. The lag-2 (+0.244) and lag-4 (+0.212) autocorrelations Stats #10 documented are picked up by the block structure and inflate the variance further.
Sensitivity to block-length choice
The Politis-Romano 1994 paper’s big practical claim (as recounted in yesterday’s Paper Trail #14) is that the SB is less sensitive to block-length misspecificationthan the moving-block or non-overlapping-block alternatives. That’srelative, not invariant — the table above shows the CI width grows monotonically from 15.77p at E[L] = 5 to 20.39p at E[L] = 20, a factor of 1.29×.
For this sample the “right” choice by the crude rule of thumb is E[L] ≈ N^(1/3) = 196^(1/3) ≈ 5.8, close to the p = 0.20 (E[L] = 5) column: [30.57, 46.33] width 15.77p. That’s a defensible operational answer. If you want a more conservative CI use E[L] = 10 (the coral row): the extra ~3p of width covers the residual autocorrelation at lags 2-4 that a short block might under-count. Either is a better answer than the plain iid CI.
The Politis-White 2004 automatic estimator is the principled way to settle this. It requires spectral-density estimation via flat-top lag windows and is one more chart script we haven’t built yet; deferred to a future Stats installment.
When to use each
Plain iid bootstrap (Stats #12): appropriate when the sample is genuinely iid — most commonly, a bucket-filtered sample where each observation is a distinct macro release separated by weeks or months (like the CAD Retail big_miss n=15 sample Stats #12 used). Autocorrelation between successive same-bucket releases is negligible; the iid assumption holds.
Stationary bootstrap (today): appropriate when the sample is a contiguous time serieswhere nearby observations share regime (like the 196-release rolling |move_pips| series used here, or a rolling window of daily returns, or a 30-day series of hourly ranges). Stats #10’s autocorrelation diagnostic is the direct check: if lag-1 |ρ| > 1.96/√n, the iid bootstrap is under-covering and the stationary bootstrap is the required replacement.
What this doesn’t say
Bootstrap doesn’t fix bias. If the sample itself is not representative of the population, no bootstrap CI recovers the truth. The NFP × USDJPY sample here spans 2010-2026; earlier NFP dynamics (pre-QE) look meaningfully different from post-QE dynamics, and future NFP under a different Fed regime could look different again. The bootstrap CI is a conditional-on-sample object, not a conditional-on-population one.
Small-n bootstrap CIs under-cover. Efron 1979 (Paper Trail #13) noted the bootstrap works asymptotically; at finite n it can under-cover by 5-8 percentage points for skewed distributions. The |move_pips| distribution is right-skewed (median 27.6p vs mean 38.2p) so nominal 95% probably runs at true 88-93% coverage. The BCa refinement (Stats #14, 2026-08-14) is the fix for that — but BCa on a contiguous series would need to be combined with the block structure of today’s post, which is its own future installment.
The rho values themselves are noisy estimates. Stats #10’s ±0.14 IID band is the 95% acceptance region for a null of zero autocorrelation; the observed +0.26 at lag-1 is only ~2 SDoutside the band. The block structure of the stationary bootstrap accommodates that uncertainty by construction (the resampled series has whatever autocorrelation the blocks impose), but if the true ρ_1 is closer to 0.15 than 0.26, the stationary bootstrap is over-widening the CI relative to the truth. Politis-White 2004’s automatic b_opt formula partially corrects for this by data-driven block-length choice.
Open the tool → Free forever. No signup. No email required.