qbuntuqbuntu

Cross-Sectional Momentum (US S&P 500)

slug: momentum-cross-sectional-us-sp500

Cross-Sectional Momentum (US S&P 500) backtest. Median Sharpe across 960 parameter sets is +0.65. p-value is 0.18. Max DD is -15.0%. Period: 2022-04-01 to 2026-09-01. Best Sharpe +2.08 is not the representative figure.

Verdict: marginal. Some parameter set has a p-value under 0.10, but the median itself misses promising (Sharpe > 0.5 and p-value < 0.05). Primary reason: no_edge. It is not regime, frequency, or cost, and the median does not clear the bar.

What was tested

Cross-sectional momentum buys recent winners and sells recent losers. The page records the median of that rule, not the parameter cell that looks best. A positive Sharpe in one corner of the grid is not the strategy.

Performance summary

Sharpe (median)
+0.65
Max DD
-15.0%
Win rate
—
Alpha (ann.)
—
p-value
0.18
backtest period: 2022-04-01 → 2026-09-01
Sharpe across 960 grid runs:median 0.65best 2.08 (not representative)worst -0.77p25–p75 0.26–0.93

Hypothesis

Jegadeesh & Titman (1993): stocks with high past returns continue to outperform over intermediate horizons. LONG winners, SHORT losers. Applied to S&P 500 constituents.

Why it didn't work

Across 960 grid combinations, median Sharpe=0.65, best=2.08. Primary failure mode: no_edge.

Facts (5)

Best grid Sharpe ratio is 2.08 (p=0.00025).
period 2022-04-01–2026-09-01; cost=5bps
sharpe_ratio2.08
cite ↗ /cite/momentum-cross-sectional-us-sp500-fact-best-sharpevia r-momentum-cross-sectional-us-sp500-0869
Median Sharpe across 960 grid runs is 0.65.
Full grid of 960 parameter combinations.
sharpe_ratio0.65
Median Sharpe in DOWN regime is 1.06 across 960 runs.
Regime=DOWN, N225 SMA20/SMA60 classification.
sharpe_ratio1.06
Median Sharpe in FLAT regime is -0.01 across 960 runs.
Regime=FLAT, N225 SMA20/SMA60 classification.
sharpe_ratio-0.01
Median Sharpe in UP regime is 1.05 across 960 runs.
Regime=UP, N225 SMA20/SMA60 classification.
sharpe_ratio1.05

Runs (30)

runparamssharpeUPFLATDOWN
formation_days=60, holding_days=1, n_stocks=5, skip_days=0, cost_bps=5, regime_gate=False
r-momentum-cross-sectional-us-sp500-0000
cost_bps: 5
n_stocks: 5
skip_days: 0
+0.56+1.70-0.34+0.29
formation_days=60, holding_days=1, n_stocks=5, skip_days=0, cost_bps=5, regime_gate=True
r-momentum-cross-sectional-us-sp500-0001
cost_bps: 5
n_stocks: 5
skip_days: 0
+0.20+0.81-0.34+0.29
formation_days=60, holding_days=1, n_stocks=5, skip_days=0, cost_bps=10, regime_gate=False
r-momentum-cross-sectional-us-sp500-0002
cost_bps: 10
n_stocks: 5
skip_days: 0
+0.41+1.51-0.47+0.17
formation_days=60, holding_days=1, n_stocks=5, skip_days=0, cost_bps=10, regime_gate=True
r-momentum-cross-sectional-us-sp500-0003
cost_bps: 10
n_stocks: 5
skip_days: 0
+0.08+0.70-0.47+0.17
formation_days=60, holding_days=1, n_stocks=5, skip_days=21, cost_bps=5, regime_gate=False
r-momentum-cross-sectional-us-sp500-0008
cost_bps: 5
n_stocks: 5
skip_days: 21
-0.44+0.65-1.20-0.89
formation_days=60, holding_days=1, n_stocks=50, skip_days=0, cost_bps=5, regime_gate=False
r-momentum-cross-sectional-us-sp500-0036
cost_bps: 5
n_stocks: 50
skip_days: 0
+0.09+1.16-0.72-0.26
formation_days=60, holding_days=5, n_stocks=5, skip_days=0, cost_bps=10, regime_gate=False
r-momentum-cross-sectional-us-sp500-0050
cost_bps: 10
n_stocks: 5
skip_days: 0
+0.46+0.56+0.06+1.39
formation_days=60, holding_days=5, n_stocks=50, skip_days=21, cost_bps=10, regime_gate=True
r-momentum-cross-sectional-us-sp500-0095
cost_bps: 10
n_stocks: 50
skip_days: 21
-0.05+0.84-1.45+0.96
formation_days=60, holding_days=10, n_stocks=50, skip_days=21, cost_bps=5, regime_gate=False
r-momentum-cross-sectional-us-sp500-0140
cost_bps: 5
n_stocks: 50
skip_days: 21
-0.58-0.20-1.09-0.06
formation_days=60, holding_days=20, n_stocks=50, skip_days=5, cost_bps=5, regime_gate=True
r-momentum-cross-sectional-us-sp500-0185
cost_bps: 5
n_stocks: 50
skip_days: 5
+0.20+1.54-0.67-0.48
formation_days=60, holding_days=60, n_stocks=5, skip_days=0, cost_bps=5, regime_gate=False
r-momentum-cross-sectional-us-sp500-0192
cost_bps: 5
n_stocks: 5
skip_days: 0
+0.58+0.92+0.41-0.57
formation_days=60, holding_days=60, n_stocks=50, skip_days=0, cost_bps=10, regime_gate=True
r-momentum-cross-sectional-us-sp500-0231
cost_bps: 10
n_stocks: 50
skip_days: 0
+0.49+1.18+0.24-0.63
formation_days=120, holding_days=1, n_stocks=50, skip_days=0, cost_bps=5, regime_gate=False
r-momentum-cross-sectional-us-sp500-0276
cost_bps: 5
n_stocks: 50
skip_days: 0
-0.05+0.89-0.87-0.61
formation_days=120, holding_days=1, n_stocks=50, skip_days=21, cost_bps=10, regime_gate=False
r-momentum-cross-sectional-us-sp500-0286
cost_bps: 10
n_stocks: 50
skip_days: 21
-0.77-0.18-1.45-1.52
formation_days=120, holding_days=5, n_stocks=20, skip_days=21, cost_bps=10, regime_gate=False
r-momentum-cross-sectional-us-sp500-0322
cost_bps: 10
n_stocks: 20
skip_days: 21
+0.32+0.09-0.34+2.48
formation_days=120, holding_days=10, n_stocks=20, skip_days=5, cost_bps=10, regime_gate=True
r-momentum-cross-sectional-us-sp500-0367
cost_bps: 10
n_stocks: 20
skip_days: 5
+0.46+1.47-0.47+1.46
formation_days=120, holding_days=20, n_stocks=20, skip_days=5, cost_bps=5, regime_gate=False
r-momentum-cross-sectional-us-sp500-0412
cost_bps: 5
n_stocks: 20
skip_days: 5
+0.69+1.32-0.19+1.47
formation_days=120, holding_days=60, n_stocks=20, skip_days=0, cost_bps=5, regime_gate=True
r-momentum-cross-sectional-us-sp500-0457
cost_bps: 5
n_stocks: 20
skip_days: 0
+1.18+1.41+1.09+0.51
formation_days=180, holding_days=1, n_stocks=10, skip_days=21, cost_bps=10, regime_gate=False
r-momentum-cross-sectional-us-sp500-0502
cost_bps: 10
n_stocks: 10
skip_days: 21
+0.05+0.45-0.68-0.22
formation_days=180, holding_days=5, n_stocks=10, skip_days=5, cost_bps=10, regime_gate=True
r-momentum-cross-sectional-us-sp500-0547
cost_bps: 10
n_stocks: 10
skip_days: 5
+1.11+1.17+0.47+2.43
formation_days=180, holding_days=10, n_stocks=10, skip_days=5, cost_bps=5, regime_gate=False
r-momentum-cross-sectional-us-sp500-0592
cost_bps: 5
n_stocks: 10
skip_days: 5
+0.97+1.14+0.32+2.03
formation_days=180, holding_days=20, n_stocks=10, skip_days=0, cost_bps=5, regime_gate=True
r-momentum-cross-sectional-us-sp500-0637
cost_bps: 5
n_stocks: 10
skip_days: 0
+0.93+2.04-0.41+1.36
formation_days=180, holding_days=60, n_stocks=5, skip_days=21, cost_bps=10, regime_gate=False
r-momentum-cross-sectional-us-sp500-0682
cost_bps: 10
n_stocks: 5
skip_days: 21
+0.79+0.82+0.47+1.24
formation_days=250, holding_days=1, n_stocks=5, skip_days=0, cost_bps=5, regime_gate=False
r-momentum-cross-sectional-us-sp500-0720
cost_bps: 5
n_stocks: 5
skip_days: 0
+0.68+1.51-0.48-0.14
formation_days=250, holding_days=1, n_stocks=5, skip_days=21, cost_bps=5, regime_gate=False
r-momentum-cross-sectional-us-sp500-0728
cost_bps: 5
n_stocks: 5
skip_days: 21
+0.57+1.62-1.14+0.20
formation_days=250, holding_days=5, n_stocks=5, skip_days=5, cost_bps=5, regime_gate=True
r-momentum-cross-sectional-us-sp500-0773
cost_bps: 5
n_stocks: 5
skip_days: 5
+1.59+1.55+1.48+2.15
formation_days=250, holding_days=10, n_stocks=5, skip_days=0, cost_bps=10, regime_gate=False
r-momentum-cross-sectional-us-sp500-0818
cost_bps: 10
n_stocks: 5
skip_days: 0
+1.01+1.10+0.66+1.32
formation_days=250, holding_days=10, n_stocks=50, skip_days=21, cost_bps=10, regime_gate=True
r-momentum-cross-sectional-us-sp500-0863
cost_bps: 10
n_stocks: 50
skip_days: 21
+1.02+1.48+0.36+1.67
formation_days=250, holding_days=20, n_stocks=5, skip_days=5, cost_bps=5, regime_gate=True
r-momentum-cross-sectional-us-sp500-0869
cost_bps: 5
n_stocks: 5
skip_days: 5
+2.08+2.37+1.73+1.65
formation_days=250, holding_days=20, n_stocks=50, skip_days=21, cost_bps=5, regime_gate=True
r-momentum-cross-sectional-us-sp500-0909
cost_bps: 5
n_stocks: 50
skip_days: 21
+1.20+1.68+0.39+1.25

Target universe

S&P 500 constituents, ~503 stocks

Related strategies

source: qbuntu-analysis · kabu STATION REST API + J-Quants daily bars
computed asof: 2026-09-24T02:22:14

Related strategies