qbuntuqbuntu

Trend Following / Donchian Breakout (US S&P 500)

slug: trend-following-us-sp500

Trend Following / Donchian Breakout (US S&P 500) backtest. Median Sharpe across 768 parameter sets is +0.10. p-value is 0.57. Max DD is -20.6%. Period: 2022-02-01 to 2026-09-01. Best Sharpe +0.80 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.

Performance summary

Sharpe (median)
+0.10
Max DD
-20.6%
Win rate
—
Alpha (ann.)
—
p-value
0.57
backtest period: 2022-02-01 → 2026-09-01
Sharpe across 768 grid runs:median 0.10best 0.80 (not representative)worst -0.87p25–p75 -0.11–0.39

Hypothesis

Donchian channel breakout: stocks breaking above N-day highs continue trending. LONG breakout stocks with configurable exit methods. Applied to S&P 500 constituents.

Why it didn't work

Across 768 grid combinations, median Sharpe=0.10, best=0.80. Primary failure mode: no_edge.

Facts (5)

Best grid Sharpe ratio is 0.80 (p=0.085).
period 2022-02-01–2026-09-01; cost=5bps
sharpe_ratio0.80
Median Sharpe across 768 grid runs is 0.10.
Full grid of 768 parameter combinations.
sharpe_ratio0.10
Median Sharpe in DOWN regime is -0.39 across 768 runs.
Regime=DOWN, N225 SMA20/SMA60 classification.
sharpe_ratio-0.39
Median Sharpe in FLAT regime is -0.17 across 768 runs.
Regime=FLAT, N225 SMA20/SMA60 classification.
sharpe_ratio-0.17
Median Sharpe in UP regime is 0.48 across 768 runs.
Regime=UP, N225 SMA20/SMA60 classification.
sharpe_ratio0.48

Runs (30)

runparamssharpeUPFLATDOWN
channel_days=20, holding_days=5, n_stocks=5, exit_method=hold, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0000
cost_bps: 5
n_stocks: 5
exit_method: "hold"
+0.43+0.16+0.91+0.56
channel_days=20, holding_days=5, n_stocks=5, exit_method=hold, cost_bps=5, regime_gate=True
r-trend-following-us-sp500-0001
cost_bps: 5
n_stocks: 5
exit_method: "hold"
+0.73+0.75+0.91+0.56
channel_days=20, holding_days=5, n_stocks=5, exit_method=hold, cost_bps=10, regime_gate=False
r-trend-following-us-sp500-0002
cost_bps: 10
n_stocks: 5
exit_method: "hold"
+0.28+0.03+0.68+0.45
channel_days=20, holding_days=5, n_stocks=5, exit_method=hold, cost_bps=10, regime_gate=True
r-trend-following-us-sp500-0003
cost_bps: 10
n_stocks: 5
exit_method: "hold"
+0.60+0.67+0.68+0.45
channel_days=20, holding_days=5, n_stocks=5, exit_method=channel_exit, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0004
cost_bps: 5
n_stocks: 5
exit_method: "channel_exit"
+0.43+0.16+0.91+0.56
channel_days=20, holding_days=5, n_stocks=5, exit_method=trailing_mid, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0008
cost_bps: 5
n_stocks: 5
exit_method: "trailing_mid"
+0.43+0.16+0.91+0.56
channel_days=20, holding_days=5, n_stocks=10, exit_method=hold, cost_bps=5, regime_gate=True
r-trend-following-us-sp500-0013
cost_bps: 5
n_stocks: 10
exit_method: "hold"
+0.80+0.81+0.88+0.67
channel_days=20, holding_days=5, n_stocks=50, exit_method=hold, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0036
cost_bps: 5
n_stocks: 50
exit_method: "hold"
+0.14-0.09+0.14+0.86
channel_days=20, holding_days=5, n_stocks=50, exit_method=trailing_mid, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0044
cost_bps: 5
n_stocks: 50
exit_method: "trailing_mid"
+0.14-0.09+0.14+0.86
channel_days=20, holding_days=10, n_stocks=20, exit_method=trailing_mid, cost_bps=5, regime_gate=True
r-trend-following-us-sp500-0081
cost_bps: 5
n_stocks: 20
exit_method: "trailing_mid"
0.00+0.54-0.45-0.43
channel_days=20, holding_days=20, n_stocks=10, exit_method=trailing_mid, cost_bps=10, regime_gate=False
r-trend-following-us-sp500-0118
cost_bps: 10
n_stocks: 10
exit_method: "trailing_mid"
-0.05+0.51-0.28-1.31
channel_days=20, holding_days=60, n_stocks=5, exit_method=hold, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0144
cost_bps: 5
n_stocks: 5
exit_method: "hold"
+0.23+0.44+0.07-0.15
channel_days=20, holding_days=60, n_stocks=10, exit_method=hold, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0156
cost_bps: 5
n_stocks: 10
exit_method: "hold"
-0.06-0.02-0.10-0.21
channel_days=40, holding_days=5, n_stocks=5, exit_method=hold, cost_bps=5, regime_gate=True
r-trend-following-us-sp500-0193
cost_bps: 5
n_stocks: 5
exit_method: "hold"
+0.64+0.85+0.82-0.02
channel_days=40, holding_days=5, n_stocks=50, exit_method=hold, cost_bps=10, regime_gate=False
r-trend-following-us-sp500-0230
cost_bps: 10
n_stocks: 50
exit_method: "hold"
+0.05+0.02+0.11-0.02
channel_days=40, holding_days=10, n_stocks=20, exit_method=hold, cost_bps=10, regime_gate=True
r-trend-following-us-sp500-0267
cost_bps: 10
n_stocks: 20
exit_method: "hold"
-0.31+0.37-0.78-1.13
channel_days=40, holding_days=20, n_stocks=10, exit_method=channel_exit, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0304
cost_bps: 5
n_stocks: 10
exit_method: "channel_exit"
+0.12+0.57+0.28-0.98
channel_days=40, holding_days=60, n_stocks=5, exit_method=channel_exit, cost_bps=5, regime_gate=True
r-trend-following-us-sp500-0341
cost_bps: 5
n_stocks: 5
exit_method: "channel_exit"
+0.54+0.78+0.63-0.39
channel_days=40, holding_days=60, n_stocks=50, exit_method=channel_exit, cost_bps=10, regime_gate=False
r-trend-following-us-sp500-0378
cost_bps: 10
n_stocks: 50
exit_method: "channel_exit"
-0.01+0.25-0.25-0.30
channel_days=60, holding_days=5, n_stocks=20, exit_method=channel_exit, cost_bps=10, regime_gate=True
r-trend-following-us-sp500-0415
cost_bps: 10
n_stocks: 20
exit_method: "channel_exit"
+0.19+0.58-0.02-0.47
channel_days=60, holding_days=10, n_stocks=10, exit_method=trailing_mid, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0452
cost_bps: 5
n_stocks: 10
exit_method: "trailing_mid"
-0.16+0.39-0.61-0.88
channel_days=60, holding_days=10, n_stocks=50, exit_method=hold, cost_bps=10, regime_gate=False
r-trend-following-us-sp500-0470
cost_bps: 10
n_stocks: 50
exit_method: "hold"
-0.87-0.07-1.56-1.21
channel_days=60, holding_days=20, n_stocks=5, exit_method=trailing_mid, cost_bps=10, regime_gate=False
r-trend-following-us-sp500-0490
cost_bps: 10
n_stocks: 5
exit_method: "trailing_mid"
-0.05+0.46-0.21-1.06
channel_days=60, holding_days=20, n_stocks=50, exit_method=trailing_mid, cost_bps=10, regime_gate=True
r-trend-following-us-sp500-0527
cost_bps: 10
n_stocks: 50
exit_method: "trailing_mid"
-0.16+1.07-0.92-0.74
channel_days=60, holding_days=60, n_stocks=50, exit_method=hold, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0564
cost_bps: 5
n_stocks: 50
exit_method: "hold"
-0.11+0.23-0.38-0.51
channel_days=120, holding_days=5, n_stocks=5, exit_method=hold, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0576
cost_bps: 5
n_stocks: 5
exit_method: "hold"
+0.65+0.47+1.23+0.21
channel_days=120, holding_days=5, n_stocks=20, exit_method=hold, cost_bps=10, regime_gate=False
r-trend-following-us-sp500-0602
cost_bps: 10
n_stocks: 20
exit_method: "hold"
-0.01+0.16-0.26-0.07
channel_days=120, holding_days=10, n_stocks=10, exit_method=hold, cost_bps=10, regime_gate=True
r-trend-following-us-sp500-0639
cost_bps: 10
n_stocks: 10
exit_method: "hold"
-0.22+0.22-0.50-0.65
channel_days=120, holding_days=20, n_stocks=5, exit_method=channel_exit, cost_bps=5, regime_gate=False
r-trend-following-us-sp500-0676
cost_bps: 5
n_stocks: 5
exit_method: "channel_exit"
+0.48+0.67+0.84-0.41
channel_days=120, holding_days=20, n_stocks=50, exit_method=channel_exit, cost_bps=5, regime_gate=True
r-trend-following-us-sp500-0713
cost_bps: 5
n_stocks: 50
exit_method: "channel_exit"
-0.01+1.10-0.47-0.70

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:15

Related strategies