Week 01 · 23 August 2026
None of the 4 indicators beat buy & hold once costs were applied.
Tested on 763 S&P 500 and FTSE 350 companies, measured over 1 August 2023 to 21 August 2026 — data the rules had never seen. Buy & hold returned a Sharpe ratio of 1.50 over the same window. MACD, VWAP, EMA produced a negative Sharpe after costs — they lost money net of what it cost to trade them.
The decay curve
In-sample, out-of-sample, and after costs
Results
Every number, in one table
763 companies — MMM, AOS, ABT, ABBV, ACN, ADBE and 757 others — over 17 August 2016 to 21 August 2026, costed at 8 basis points per side.
| Indicator | In-sample Sharpe |
Out-of-sample Sharpe (gross) |
Out-of-sample Sharpe (net) |
Trades | Cost paid | Max drawdown | Verdict |
|---|---|---|---|---|---|---|---|
| RSI | 0.12 | 0.56 | 0.48 | 86717 | 9.4% | -6.4% | WEAKENED |
| MACD | 0.15 | -0.35 | -0.62 | 249638 | 52.3% | -25.0% | FAILED |
| VWAP | -0.19 | -0.30 | -0.70 | 378989 | 79.4% | -27.1% | FAILED |
| EMA | -0.15 | -0.79 | -0.85 | 60426 | 12.6% | -30.6% | FAILED |
| Buy & hold | 0.86 | 1.50 | 1.50 | 0 | 0.1% | -14.3% | benchmark |
SURVIVED — positive out-of-sample Sharpe after costs,
and beat buy & hold.
WEAKENED — still positive after costs, but lost to
buy & hold.
FAILED — out-of-sample Sharpe was zero or negative
once costs were applied.
Thresholds are fixed in code, not judged by eye, so the standard cannot drift week to week to suit the result.
Indicator by indicator
What happened, and why
RSI
WEAKENEDMean-reversion: buy below RSI 30, short above RSI 70, flatten back at 50.
Posted a Sharpe ratio of 0.12 in-sample, 0.56 on data it had never seen, and 0.48 once trading costs were applied — across 86717 trades that paid away 9.4% of notional.
MACD
FAILEDTrend-following: long while the MACD line (EMA12-EMA26) is above its 9-day signal line.
Posted a Sharpe ratio of 0.15 in-sample, -0.35 on data it had never seen, and -0.62 once trading costs were applied — across 249638 trades that paid away 52.3% of notional.
VWAP
FAILEDTrend-following: long while the close is above the 20-day rolling volume-weighted average price.
Posted a Sharpe ratio of -0.19 in-sample, -0.30 on data it had never seen, and -0.70 once trading costs were applied — across 378989 trades that paid away 79.4% of notional.
EMA
FAILEDTrend-following: long while the 20-day EMA is above the 50-day EMA.
Posted a Sharpe ratio of -0.15 in-sample, -0.79 on data it had never seen, and -0.85 once trading costs were applied — across 60426 trades that paid away 12.6% of notional.
Walk-forward check
Did it hold up repeatedly, or once?
A single 70/30 split gives one reading, and one reading can be luck. Each indicator is re-tested across rolling three-year training windows with the following year held out, giving many independent out-of-sample readings instead of one.
The column that matters is not the mean — it is how often the indicator was positive. A strategy averaging 0.4 on the back of one spectacular year and four flat ones is a very different proposition from one that earns 0.4 every year.
| Indicator | Windows | Mean Sharpe (net) | Windows positive | Worst window |
|---|---|---|---|---|
| RSI | 6 | 0.13 | 50% | -0.65 |
| MACD | 6 | -0.39 | 50% | -2.06 |
| VWAP | 6 | -0.87 | 17% | -1.96 |
| EMA | 6 | -0.43 | 17% | -1.50 |
Cumulative
Growth of 1.00, net of costs
Sensitivity
How wrong could the cost assumption be?
The obvious objection to any cost-adjusted backtest is that the cost number was chosen by the author. Showing the whole curve is a better answer than defending one point on it. Where each line crosses zero is the highest trading cost that indicator could tolerate and still break even.
Caveats
What this study cannot tell you
Stated every week, because they do not go away.
- Survivorship bias. The universe uses current index membership, so companies delisted or dropped along the way are absent. This flatters absolute returns. It affects the in-sample versus out-of-sample comparison far less, since both halves share the bias — which is why that comparison, not the absolute return, is the headline.
- One cost assumption, applied uniformly. Real spreads vary by stock and by day, and widen exactly when you most want to trade. The sensitivity analysis shows how conclusions change across the full range rather than defending a single number.
- What is labelled VWAP is a rolling volume-weighted moving average. True VWAP is intraday: it resets each session and cannot be computed from daily bars at all. The daily-chart “VWAP” used across retail trading is the rolling version tested here.
- No position sizing, leverage or borrow costs. Every position is the same size, and shorting is assumed free. It is not.
Reproduce this. Every figure above comes from one
command against public data:
python run_pipeline.py --universe all --week 1.
The plain-text report and the
underlying data are both published.