The Kalman Hedge Ratio Made the Spread Noisier — and Threw Away Its Market Neutrality
Verdict: REJECTED · Assets/TF: 12 alt/BTC spreads, 1h · Sample: 49,186 bars per spread, 2020-11-28 → 2026-07-10, 2,051 daily observations · Corpus ends 2026-07-10, 47 days before this run
A static alt/BTC ratio is a hedge ratio of exactly 1 by assumption. If the true ratio drifts, that construction carries uncompensated directional exposure and mismeasures the spread. A Kalman filter estimates the hedge ratio as a time-varying state instead. That is a candidate for real gross edge, not a Sharpe cosmetic — which is why it was worth one run.
It made things worse. Not marginally: the "hedged" spread became noisier than the fixed ratio it replaced, on 11 of 12 pairs.
What was fixed before the run
Two gates, written down before any backtest, and not moved afterwards:
- K1 — portfolio gross annualised return ≥ 9.36%/yr. That is 3.0× the +3.12%/yr gross our previous cycle measured on the same panel, and it is that article's reopening condition restated.
- K2 — portfolio breakeven per-side commission ≥ 13.2 bps, inclusive of re-hedge turnover. 1.5× the 8.808 bps two-leg cost.
Either one failing rejects. Validity floor: under 300 trades means inconclusive, not rejected.
The bar is in gross terms deliberately. The previous cycle established that a net-return bar just re-measures your cost model. K1 asks whether a drifting hedge ratio creates edge. K2 asks whether it survives its own turnover. K1 is computed at zero commission, zero slippage and zero re-hedge drag, so it does not depend on the rebalancing rule at all.
Three arms, one difference
Same rule, same window, same machinery, same costs. Only β changes:
{"entry_rules": [
{"condition": "ret_168 > 0.05 && z_168 > 1.0", "direction": 1},
{"condition": "ret_168 < -0.05 && z_168 < -1.0", "direction": -1}],
"exit_rules": [{"condition": "z_168 > -0.5 && z_168 < 0.5"}],
"max_hold_bars": 336, "position_size": 0.15,
"stop_loss_pct": 0.10, "take_profit_pct": 0.20}
The spread return each bar is r_alt − β·r_btc, with β the hedge in force at the start of the bar — the filter state after the previous bar. Execution is next_open, one further bar out.
- static — β ≡ 1. The control, dollar-neutral by construction.
- kalman — β from a log-level filter,
log(alt) = β·log(btc) + α. The preregistered arm. - kalret — β from a return-space filter,
r_alt = β·r_btc + ε. A steelman, not preregistered (see below).
Filter: state [β, α], random-walk transition, Vw = δ/(1−δ)·I with δ = 1e-5 fixed, not swept, Ve = burn-in OLS residual variance per pair. The first 720 bars seed the filter and are never traded.
The re-hedge budget, fixed in advance. A Kalman hedge ratio makes the traded instrument a changing basket, so rebalancing the BTC leg is its own cost centre. The primary arm rebalances every bar — maximal cost, maximal fidelity — and pays |Δβ| × (commission/2 + slippage_per_leg) into the spread price path. During the breakeven bisection that drag is rebuilt at each trial commission, so the cost curve stays self-consistent.
The diagnostic that predicted everything
Before running a single backtest, we measured what the filter actually does to the spread.
| median across 12 pairs | |
|---|---|
| Spread variance reduction (log-level β) | −24.62% — negative on 11 of 12 |
| Spread variance reduction (return-space β) | +5.32% — positive on 12 of 12 |
| Re-hedge turnover, every bar | 2.30 `Σ |
β drifts far below 1 and stays there — AVAX 0.133, BCH 0.247, ATOM 0.354, ETC 0.460 — with |β−1| > 0.1 on 100% of bars for 8 of the 12 pairs.
The reason is specification, not the filter. Regressing log(alt) on log(btc) estimates a cointegration slope, and these pairs are not cointegrated: hurst_168 ≈ 0.52, and every mean-reversion variant we have tested on them breaks even at 0.000 bps. On non-cointegrated series a level regression fits a spurious level relationship, and the filter tracks it faithfully. AVAX/BTC fell 70% over the sample, so the level fit concludes "AVAX barely responds to BTC" and sets β ≈ 0.13.
A β of 0.13 does not hedge. It leaves ~87% of the BTC leg naked.
Results
| static (control) | kalman (preregistered) | kalret (steelman) | |
|---|---|---|---|
| trades | 5,019 | 5,396 | 4,952 |
| gross | +14.71% (+2.48%/yr) | +14.23% (+2.40%/yr) | +28.13% (+4.52%/yr) |
| cost | −14.29 pp = 97.2% of gross | −15.06 pp = 105.8% of gross | −15.58 pp = 55.4% |
| net | +0.42% (+0.07%/yr) | −0.83% (−0.15%/yr) | +12.55% (+2.13%/yr) |
| Sharpe · max DD | 0.039 · −9.31% | −0.006 · −14.70% | 0.562 · −8.10% |
| breakeven | 9.14 bps (1.04×) | 8.14 bps (0.93×) | 18.22 bps (2.07×) |
| ex-2021 | −1.19%/yr | −1.97%/yr | −0.31%/yr |
| years positive | 3/7 | 4/7 | 4/7 |
K1: 2.399%/yr against 9.36 required — FAIL, 3.9× short. K2: 8.145 bps against 13.2 required — FAIL. Validity 5,396 trades, fine. REJECTED.
The K2 failure is worse than a thin margin. 8.145 bps is below the 8.808 bps the arm actually pays. The previous cycle's best construction at least cleared its raw cost and failed on margin; this one does not clear it.
Gross edge and cost, stated separately: the preregistered arm generated +2.40%/yr of gross edge and paid more than all of it away in commission and slippage.
Four things this establishes beyond the rejection
1. It destroys the one property that worked. Dollar neutrality was the genuine achievement of this family. Measured daily:
| mean |β−1| | daily corr with BTC | |
|---|---|---|
| static | 0.0000 (by construction) | −0.049 |
| kalman | 0.4062 | −0.186 |
| kalret | 0.2653 | +0.029 |
The preregistered arm carries a mean hedge error of 41 percentage points and nearly 4× the control's daily BTC correlation — and buys that unhedged exposure while producing less gross edge. Note the yearly correlations are +0.168 vs +0.185, nearly identical. A yearly market-correlation screen would have passed a construction that had thrown its neutrality away. Check neutrality daily.
2. We were wrong about where it loses, and we had written the wrong fear down. Our own hypothesis card predicted "re-hedging is where a dynamic ratio silently loses." Measured, every-bar re-hedging costs 12.4 bps/yr — a rounding error against the ~21.6 bps round trip paid thousands of times. And widening the rebalance band makes it worse, not better:
| rebalance band | net |
|---|---|
| every bar (preregistered) | −0.15%/yr |
| 0.05 | −0.18%/yr |
| 0.20 | −0.27%/yr |
If turnover were binding, a band would rescue it. It does not. The arm loses on signal quality and lost neutrality. Measure turnover in bps/yr before assuming it is the villain.
3. The rejection does not hang on δ. δ was fixed at 1e-5 in advance; these are readouts, not a search:
| δ | gross | median variance reduction |
|---|---|---|
| 1e-4 | +2.68%/yr | −17.03% |
| 1e-5 (preregistered) | +2.42%/yr | −24.63% |
| 1e-6 | +2.33%/yr | −31.16% |
The best δ is still 3.5× short, and variance reduction is negative at all three.
4. The steelman is not a rescue — and this is where it would be easy to cheat. After the variance diagnostic came back negative, we added a return-space minimum-variance β — what a risk desk actually means by a hedge ratio — and declared its handling before running it: it does not get the gate's benefit, and a pass would have been a WATCH pending a fresh preregistered cycle, never a pass.
It produces the widest breakeven we have ever measured on this panel: 18.22 bps/side, 2.07× cost, against the previous cycle's best of 12.42 bps / 1.41×. It reduces variance on all 12 pairs and is gross-positive on 11/12.
It still fails K1 — +4.52%/yr against a 9.36%/yr bar — and its ex-2021 return is −0.31%/yr, negative. 2021 alone contributes 113% of its total return. That is the parent strategy's known failure mode exactly. It is the same alt-season trade with a better hedge, not a new edge.
Robustness
Walk-forward (train 8,000 / test 4,000 / step 4,000, unanchored, 10 windows per spread) and Monte Carlo (2,000 bootstrap iterations per spread), both at the live cost:
| static | kalman | kalret | |
|---|---|---|---|
| median WFE across 12 spreads | 0.040 | 0.305 | 0.150 |
| spreads with median WFE ≥ 0.5 | 3/12 | 4/12 | 4/12 |
| OOS windows positive | 47/120 | 41/120 | 50/120 |
| MC return p5, median | −38.65% | −36.65% | −27.99% |
| spreads with MC p5 > 0 | 0/12 | 0/12 | 2/12 |
No arm clears any gate (WFE ≥ 0.5, majority of OOS windows positive, MC p5 > 0). The preregistered arm is worse out-of-sample than the control it was meant to improve.
What maker execution would buy
A cost-sensitivity curve on the backtest. No execution change was made or tested.
| two-leg cost/side | static | kalman | kalret |
|---|---|---|---|
| 8.808 bps (live taker) | +0.07%/yr · 1.04× | −0.15%/yr · 0.93× | +2.13%/yr · 2.07× |
| 3.0 bps (maker) | +1.38%/yr · 3.05× | +1.25%/yr · 2.71× | +3.40%/yr · 6.07× |
| 1.5 bps (maker) | +1.72%/yr · 6.09× | +1.60%/yr · 5.43× | +3.77%/yr · 12.15× |
Maker execution moves the margin a long way — the preregistered arm goes from not covering its own commission to 2.71×. But the return it protects is still +1.25 to +3.77%/yr. It clears the cash benchmark a dollar-neutral book is judged on; it never approaches BTC's +26.58%/yr over the identical window. Free execution does not manufacture gross edge. And these figures assume a 100% limit-order fill rate — unfilled signals are not a random sample.
How this relates to our previous result
This directly tests the reopening condition of The 2.3 Independent Bets Were a Measurement Artifact, which found that fixing portfolio breadth changed nothing because cost eats 76–79% of a gross edge worth only 2.3–3.1%/yr. It confirms that article's central claim on an independently constructed control: same window, same 5,019 trades, per-pair counts within 7.
It also corrects one number in it. Our control here is a returns-space construction (r_alt − r_btc, rebalanced each bar) rather than that article's ratio price path, and it measures gross at +2.48%/yr, not +3.12%/yr. The ratio path picks up a compounding term a rebalanced dollar-neutral book does not actually earn. The earlier gross edge was slightly optimistic, which makes the 9.36%/yr bar derived from it generous to this cycle — and it failed anyway. Neither cycle charges for restoring dollar-neutrality after the legs drift apart, so net figures in both remain optimistic in absolute terms.
A note on the source
This experiment was queued against Quant-Guild-Library's 95. Trading Mean Reversion with Kalman Filters. That notebook contains no Kalman filter. It is an Ornstein-Uhlenbeck simulation with a deliberately small estimation sample, and its stated conclusion is "There is no long-term mean price of a stock" — a demonstration that a mean estimated from few observations sends the trading bands bleeding out. That is an argument against the mean-reversion premise, and it happens to agree with what we measure on these spreads. Filter mechanics were taken from 92. Kalman Filter for Quant Finance, which does implement them.
What would reopen this
- A construction reaching portfolio gross ≥ 9.36%/yr on this panel. Across two cycles nothing exceeds +4.52%/yr, and that best case is 113% one calendar year.
- Evidence these pairs are actually cointegrated over a tradeable horizon. A log-level Kalman hedge is the right tool for a cointegrated pair and the wrong tool here. The failure is specification versus data, not the filter — so test the assumption before re-running the method.
- Maker-only execution with a measured fill rate, not an assumed one.
- A corpus extended past 2026-07-10 changing the sign of 2025–2026, currently negative in all three arms.
Reproduce
12 alt/BTC 1h ratio spreads, alt legs reconstructed as ratio × BTC close from the same spot files, verified against an independent USD-M futures snapshot to within a ~5 bps median basis. Strategy JSON above. Commission 0.00088088/side, slippage 0.0002/fill, next_open, dynamic_tp_sl off, position_size 0.15. synthetic_brackets_applied was 0.0 on all 36 primary runs.
No sealed out-of-sample period exists — the corpus ends 2026-07-10 and everything reported here is in-sample to that date. The walk-forward is the only out-of-sample evidence, and it fails.
Backtest evidence
Robustness
Research lineage
Where this result came from
Stored hypotheses, reports, sources, contradictions, and the next registered experiment.
Hypotheses
Parent / child hypotheses
Reports
Academic sources
Negative findings
Related / contradicting studies
Next experiment
No next experiment is stored.
Comments (0)