The Edge That Wasn't
All 81 experiments › #75

#75 — FX factor suite (carry / value / momentum / composite) at OANDA-retail cost

2026-07-07
Verdict: negative · ⛔ classic FX risk premia do not survive retail costs
Carry-gated (PRIMARY) IS net -34.1 p/rebalance (ungated -53.4) vs R10-null p95 +15.5 across 44 monthly rebalances (2020-11 to 2024-08) - gates 3-4 fail, program closed, OOS sealed.

Hypothesis — what it tests

Whether the classic academic FX risk premia - carry, momentum(12-1), PPP value, and an equal-weight composite - survive OANDA-retail spread and broker-truth carry costs at a monthly cross-sectional rebalance horizon across 8 currencies.

Description

Pre-registered (locked 2026-07-07) academic-style monthly FX risk-premia test on 8 currencies (via 12 pairs): carry (PRIMARY, broker-truth carry_model cross-sectional ranks, SPX500 SMA(200) risk-off gate as the confirmatory cell) plus three exploratory secondaries - momentum(12-1), PPP-value, and an equal-weight composite - each long top-3/short bottom-3 currencies, equal-risk 63-day-vol sized, monthly rebalanced, benchmarked against an R10 null of 200 random-weight portfolios on identical rebalance dates. Over 44 IS monthly rebalances (2020-11-11 to 2024-08-30, small-N disclosed in the pre-reg), gated carry nets -34.1 p/rebalance (ungated -53.4) versus the null's p95 of +15.5 - gate 3 fails, and WF halves (-39.4 / -28.9) both stay negative - gate 4 fails. Value is worse (-60.0 p/rebalance) and the composite -54.2; momentum(12-1) is the lone positive secondary at +27.4 p/rebalance but is flagged exploratory/single-pass and explicitly not promotable without its own pre-registration - a caveat borne out when the dedicated momentum_confirm follow-up study later found the +27.4 was a decade-stale window artifact. Apparatus gates (harness self-test, carry-accrual parity vs carry_model) both passed clean, so the failure is attributed to the factors themselves, not the test rig. Per the pre-registration's own decision rule, the program stopped at IS - OOS was never touched and remains sealed for one future amended shot.

Key result

carry_gated: n=44, mean=-34.136 p/rebal, cum=-1502.0p, maxDD=-1640.3p; carry_ungated: mean=-53.418p, cum=-2350.4p; composite: mean=-54.226p, cum=-2386.0p; momentum: mean=+27.448p, cum=+1207.7p, maxDD=-874.1p (secondary, unconfirmed); value: mean=-59.958p, cum=-2638.1p; R10 null (n_seeds=200): mean=-15.993p, p95=+15.471p, p5=-48.410p, std=17.887p; WF halves: first(n=22)=-39.374p, second(n=22)=-28.899p; gates: 1=PASS, 2=PASS, 3=FAIL, 4=FAIL.

Indicators

Carry rank (broker-truth carry_model)SPX500 SMA(200) risk-off gate12-month minus 1-month currency momentumPPP real-exchange-rate deviation (value)63-day realized volatility (position sizing)Equal-weight composite rank

Algorithms

Monthly cross-sectional rebalance engine (rebalance_engine.py)R10 null: 200 random-weight portfolios on identical rebalance datesWalk-forward IS-halves split8-currency USD-numeraire triangulation (currency_index.py)

Code

Interactive version (search, filters, figures): the experiment explorer.

← #74 London-fix fade (16:00 pre-fix drift reversion)#76 Momentum confirmation Stage 1 (deep-history FX momentum(12-1)) →
This page is one experiment from the audited record behind the book The Edge That Wasn'tget the book · about the project.