r/algotrading • u/Expert_CBCD • 11h ago
Strategy Beating the Market with RSI and SPY Rotation
Hello again everyone, I want to share another strategy that I've been working on that I thought I would share with you folks to hear your thoughts.
The whole strategy is based on using the RSI indicator but instead of using it on the close, using it on the EMA 20 (RSI-EMA). I find that it is much smoother and gives stronger signals across timeframes vs. traditional RSI. A few backtests that I've done also find that the RSI-EMA is a fairly strong modification that produces more consistent wins and better results.
I of course wanted to turn this into a trading systems and had played around with various formulas, and entries and exits but believe that I finally found a system that may work well.
The set up is as follows. I use a universe of the top 20 companies in the S&P 500 by market cap (data goes back to 1989 and can be found here; my own backtest is 2010 to present). The tickers used for a current year are based on the top 20 companies from the previous year to avoid any lookahead/survivorship bias.
Within a given year, when an equity's RSI-EMA in the top 20 crosses over 30, I buy that stock. If there are multiple crossovers, I buy the one with the lowest RSI (but over 30 as it's crossing over). When there isn't an equity crossing over, capital is shifted into SPY. Exits occur after 10 trading days with all entries/exits happening at the next open. This system also uses 100% of the capital in each trade.
That's it!
With respect to exits, I tested using an ATR based exit (1.0 in either direction) and an RSI-EMA based exit (when it crosses above 70 or crosses back below 30). I also included a slippage penalty of 5 bps (0.05%).
Here are the results based on the various exits (initial capital $100,000; backtest starts in 2010):
Yearly results:
| Year | SPY B&H | 1. Time (10d) | 2. RSI Target/Redrop | 3. ATR (1.0x) |
|---|---|---|---|---|
| 2010 | 15.06% | 22.85% | 17.38% | 9.70% |
| 2011 | 1.89% | 4.07% | 3.08% | -8.03% |
| 2012 | 15.99% | 31.31% | 12.03% | 2.11% |
| 2013 | 32.31% | -0.49% | 0.65% | 16.93% |
| 2014 | 13.46% | 34.68% | 18.43% | -8.65% |
| 2015 | 1.25% | -12.50% | -12.84% | -17.62% |
| 2016 | 12.00% | 17.88% | 13.21% | 5.88% |
| 2017 | 21.70% | 21.34% | 28.49% | 9.28% |
| 2018 | -4.56% | 24.74% | -3.02% | -32.06% |
| 2019 | 31.22% | 37.67% | 18.69% | 29.36% |
| 2020 | 18.37% | 16.11% | 22.22% | -3.15% |
| 2021 | 28.75% | 10.55% | -19.53% | 2.38% |
| 2022 | -18.17% | -31.10% | -18.92% | -46.60% |
| 2023 | 26.19% | 27.41% | 24.82% | -7.01% |
| 2024 | 24.89% | 63.29% | 86.76% | 14.41% |
| 2025 | 17.72% | 20.98% | 30.48% | -20.81% |
| 2026 | 10.16% | 45.43% | 9.36% | 126.31% |
| --- | --- | --- | --- | --- |
| Avg Return | 15.13% | 19.66% | 15.96% | 4.28% |
| Std Dev | 12.60% | 21.95% | 24.52% | 37.38% |
| Sharpe | 1.20 | 0.90 | 0.65 | 0.11 |
| Strategy | Final | Net Profit | Return | Trades | Win Rate | Avg Ret | Avg Hold | Worst Trade |
|---|---|---|---|---|---|---|---|---|
| 1. Fixed 10-Day Time Limit | $1,565,613 | $1,465,613 | 1465.61% | 231 | 58.01% | 1.00% | 10.0d | -26.72% |
| 2. RSI > 70 Target (Redrop < 30 Exit) | $625,288 | $525,288 | 525.29% | 245 | 61.22% | 0.67% | 10.2d | -22.03% |
| 3. 1.0x ATR Stop (Pure Intraday) | $93,071 | -$6,929 | -6.93% | 37 | 2.70% | 1.47% | 105.7d | -5.76% |
What if we experiment with the different number of holdings days? We see that generally 12 - 16 days is the ideal hold time with returns being lower on either side of that range. To minimize slippage and the number of trades, I would likely pivot to 15 trading days instead of 10.
| Hold Days | Trades | Win Rate | CAGR | Final Equity |
|---|---|---|---|---|
| 5 | 326 | 54.3% | 8.79% | $401,551 |
| 6 | 306 | 54.6% | 8.17% | $365,193 |
| 7 | 288 | 53.8% | 9.72% | $461,591 |
| 8 | 262 | 55.3% | 13.95% | $862,307 |
| 9 | 243 | 54.3% | 13.18% | $770,630 |
| 10 | 231 | 58.0% | 18.15% | $1,565,613 |
| 11 | 220 | 54.1% | 13.75% | $837,275 |
| 12 | 206 | 57.3% | 18.59% | $1,664,395 |
| 13 | 197 | 57.4% | 17.48% | $1,424,912 |
| 14 | 189 | 58.7% | 20.72% | $2,231,678 |
| 15 | 183 | 59.0% | 23.10% | $3,082,154 |
| 16 | 177 | 55.9% | 19.40% | $1,862,937 |
| 17 | 170 | 54.7% | 12.81% | $730,494 |
| 18 | 162 | 54.9% | 11.27% | $582,300 |
| 19 | 156 | 57.1% | 11.47% | $599,320 |
| 20 | 147 | 58.5% | 8.87% | $406,290 |
And that's that! I would love to hear any feedback including criticisms, general thoughts and suggestions to improve.
EDIT: WALK-FORWARD TESTING ADDITION
To address some of the points about potential overfitting and the drop-off in CAGR between certain days, I decided to do an expanding walk forward test.
I find the number of days held from 2010 - 2015 that maximizes profit (ranging from 10 - 20) and then apply that to 2016. I continue expanding the in-sample period (for 2017, the in-sample optimization period is 2010 - 2016, for 2018 2010 - 2017, etc.) until June 30th 2026.
Yearly results, with B&H and numerical means/sd/sharpe are below with 2 bps of slippage (changed it when experimenting and don't want to re-do the table factoring in 5 - do what you will with that).
| Year | SPY B&H | Walk-Forward OOS | # Days Held |
|---|---|---|---|
| 2016 | 12.00% | 19.65% | 10 |
| 2017 | 21.71% | 23.32% | 10 |
| 2018 | -4.57% | 24.18% | 10 |
| 2019 | 31.22% | 42.50% | 10 |
| 2020 | 18.33% | 18.19% | 10 |
| 2021 | 28.73% | 11.91% | 10 |
| 2022 | -18.18% | 0.56% | 15 |
| 2023 | 26.18% | 8.62% | 15 |
| 2024 | 24.89% | 60.41% | 15 |
| 2025 | 17.72% | 23.11% | 10 |
| 2026 (YTD) | 10.31% | 59.79% | 15 |
| --- | --- | --- | |
| Avg Return | 15.30% | 26.57% | |
| Std Dev | 13.52% | 19.16% | |
| Sharpe | 1.13 | 1.39 |
Walk forward testing actually improves upon my initial results and - numerically - produces a Sharpe that is actually higher than that of SPY. Though odds are if I converted all this to CAGR we may see an underperforming sharpe.
