Triple RSI Strategy
Buys deep RSI(5) oversold dips inside a 200-day SPY uptrend and exits when RSI reverts above 50 — a short-term mean-reversion setup.
Performance
Real internal-backtest statistics from the registry — Internal backtest · SPY daily bars (Yahoo Finance) · 89 trades · 1993–2026.
CAGR and exposure are not published for the library yet — we show “—” rather than invent them. Max drawdown, best year and worst year are undefined for the pooled Momentum universe backtest. Win rate is a share of trades, average return is per trade, and holding period is in trading days.
Historical pattern
No fixed-window historical pattern is published for this strategy — its holding period is variable (or, for a market-wide read, there is no single held window), so a single averaged return path would misrepresent it. Use the backtest for its full trade-by-trade history instead. We never fabricate a curve.
Triple RSI buys short-term panic in an otherwise healthy market. It watches a fast 5-period RSI and only acts when four conditions line up at once — three RSI conditions plus a trend filter — then exits when RSI mean-reverts. It runs on SPY as a market-timing signal (/api/strategies) and, via the scanner, on individual stocks (/api/scan).
- Buy when all four entry conditions are true (see §3).
- Sell when RSI(5) crosses back above 50.
- Typical hold: a few trading days (mean ~5; range 1–15 in the backtest).
Best for
- Choppy-to-rising, mean-reverting markets that hold above their 200-day average and shake out weak hands on brief dips.
Avoid when
- Strong, sustained downtrends and momentum crashes, where "oversold" keeps getting more oversold. The 200-day filter reduces but does not eliminate this.
Market behaviour exploited
Short-term overreaction (mean reversion) inside a primary uptrend — the tendency of healthy markets to snap back after a fast, shallow pullback.
| Driver | Mechanism |
|---|---|
| Pullbacks in uptrends snap back | In a market above its rising 200-day MA, brief selloffs are usually profit-taking/liquidity events, not regime changes — buyers step back in. |
| Stacked confirmation | Requiring RSI oversold and still-falling and coming from a non-overbought state filters out both blow-off tops and names already turning, targeting genuine capitulation. |
| Trend filter | The 200-day gate keeps the strategy from "buying dips" in bear markets, where the edge inverts. |
The edge is a tendency, not a guarantee; mean reversion fails hard in trending bear markets, which is why the exit and the trend filter matter.
One pure core (tripleRsiSignalFromBars) backs the live SPY state, the scanner, and the backtest adapter, so the maths lives in exactly one place. Parameters (TRIPLE_RSI_PARAMS): RSI period 5, SMA period 200.
Entry — all four must be true
- RSI(5) < 30 — deeply oversold.
- RSI(5) falling for 3 consecutive sessions — momentum still washing out, not already turning.
- RSI(5) was < 60 exactly 3 sessions ago — the drop began from a non-overbought state (not a blow-off top).
- Close > 200-day SMA — the primary trend is still up.
Exit
RSI(5) crosses above 50 — the mean reversion is complete.
Position management
- The rules define no fixed price stop or profit target — the exit is condition-based (RSI reclaims 50). So
stopLoss,firstTarget,riskPercent, andrewardRiskRatioare reported asnull(never invented).entryPriceis the signal-bar close. - Risk is controlled by only entering above the 200-day trend and by the mean-reversion exit.
Scanner
The identical per-symbol logic runs across a universe via GET /api/scan?strategy=triple_rsi, returning each match's signal, a 0–100 confidence score, the passed-rule checklist, and metrics (rsi5, sma200, close).
Deterministic, from the shared buildConfidence framework. confidenceScore is a setup-quality measure (0–100), not a probability of profit. Components (maxima sum to 100):
| Component | Max | Awarded when |
|---|---|---|
trendFilter | 20 | close is above the 200-day SMA |
oversold | 15 | RSI(5) < 30 |
momentumDecline | 20 | RSI(5) fell 3 sessions in a row |
pullbackContext | 15 | RSI(5) was < 60 three sessions ago |
oversoldDepth | 30 | scaled by how far RSI(5) has pushed below 30 (deeper → higher) |
A bare BUY (all four gates met, RSI just under 30) scores ≈ 70 (Good); the more deeply oversold, the closer to 100 (Exceptional). On /api/strategies the live SPY score is null when no setup is active; on each /api/scan match it is always populated. Bands: <70 Weak · 70–79 Good · 80–89 Strong · 90–100 Exceptional.
The API returns the labels of the rules that currently pass; a full BUY shows all four:
- RSI(5) below 30 (deeply oversold)
- 3-day RSI decline (momentum still falling)
- RSI was below 60 three days ago (came from a non-overbought state)
- Above 200-day MA (primary trend up)
- Enter at the signal-bar close; no fixed stop/target — exit is RSI(5) reclaiming 50.
- High hit-rate, positive expectancy. 89.9% win rate and a 6.21 profit factor over 89 real trades and 30 years.
- Shallow drawdown. 7.4% max drawdown — the trend filter and quick exit keep losers small (worst trade −7.37%).
- Objective and mechanical. Four unambiguous numeric gates; no chart-reading or discretion.
- Dual use. The same core powers a SPY timing signal and a full stock scanner.
- Short exposure. In the market only a few days per trade, reducing overnight/regime risk.
- No hard stop. The exit is condition-based (RSI reclaims 50); a trade can run against you until it does. Worst trade was −7.37%.
- Regime-dependent. Mean reversion fails in sustained downtrends; the 200-day filter mitigates but doesn't remove this.
- Selective / bursty. Only ~3 trades/year on SPY, clustered in volatile stretches — long quiet periods with no signal.
- Close-to-close model. No commissions/slippage modelled; the backtest fills at the signal-bar close.
- Small average edge. ~1.3% per trade — sensitive to costs and execution.
| Dimension | Ideal |
|---|---|
| Market | Broad index or large-cap equities trading above a rising 200-day MA; constructive tape with periodic shallow pullbacks. |
| Trader | Active, rules-driven swing trader comfortable buying fear in an uptrend and holding through short-term volatility. |
| Timeframe | Daily bars; a few-day swing hold. |
| Avoid when | The asset is below its 200-day MA (bear market / downtrend); around binary events; or when costs would swamp the ~1.3% edge. |
- Static snapshot.
historical.*is baked as of 2026; the live/api/backtestalways recomputes from current data. - Single-vendor, close-to-close. Prices from Yahoo; SPY history starts 1993-01-29; no slippage/commissions modelled.
- **No
historicalPattern.** Deliberate — the holding window is variable, so a fixed-offset average would misrepresent the strategy. - Backtested on SPY. The scanner applies the same rules per-symbol across a universe, but the published statistics are the SPY single-symbol backtest.
API examples
Real responses from the live endpoints for this strategy.
Live strategy
GET /api/strategies?id=triple_rsi{
"strategies": [
{
"id": "triple_rsi",
"name": "Triple RSI Strategy",
"category": "Technical",
"asset": "SPY",
"description": "WHAT IT IS: The Triple RSI strategy is a technical, mean-reversion setup…",
"historical": {
"yearsTested": 34,
"winRate": 0.8989,
"averageReturn": 1.31,
"bestYear": 17.63,
"worstYear": -2.36,
"maxDrawdown": 7.37,
"averageHoldingPeriod": 5,
"profitFactor": 6.21,
"totalTrades": 89,
"source": "Internal backtest · SPY daily bars (Yahoo Finance) · 89 trades · 1993–2026"
},
"historicalPattern": null,
"status": "Upcoming",
"entryDate": "",
"exitDate": "",
"daysUntilEntry": 0,
"entryPrice": 583.12,
"stopLoss": null,
"firstTarget": null,
"riskPercent": null,
"rewardRiskRatio": null,
"confidenceScore": 12,
"confidenceBreakdown": { "trendFilter": 20, "oversold": 0, "momentumDecline": 0, "pullbackContext": 0, "oversoldDepth": 0 },
"explanation": "SPY does not currently trigger Triple RSI — 1 of 4 entry conditions in place. A signal fires only when all four align.",
"checklist": ["Above 200-day MA"],
"score": 55,
"recommended": false,
"weight": "medium"
}
]
}Scanner
GET /api/scan?strategy=triple_rsi{
"strategy": "triple_rsi",
"supported": true,
"scanned": 500,
"matches": [
{
"symbol": "XYZ",
"signal": "BUY",
"score": 88,
"reasons": { "rsiBelow30": true, "threeDayDecline": true, "priorRsiBelow60": true, "above200MA": true },
"metrics": { "rsi5": 21.4, "sma200": 142.10, "close": 151.30 },
"entryPrice": 151.30,
"stopLoss": null,
"firstTarget": null,
"riskPercent": null,
"rewardRiskRatio": null,
"confidenceScore": 88,
"confidenceBreakdown": { "trendFilter": 20, "oversold": 15, "momentumDecline": 20, "pullbackContext": 15, "oversoldDepth": 18 },
"explanation": "XYZ rates 88/100 — a strong setup by the Triple RSI rules (a measure of setup quality, not a probability of profit)…",
"checklist": ["RSI(5) below 30", "3-day RSI decline", "RSI was below 60 three days ago", "Above 200-day MA"]
}
],
"skipped": []
}Backtest
GET /api/backtest?strategy=triple_rsi{
"strategy": "triple_rsi",
"symbol": "SPY",
"range": { "requestedFrom": null, "requestedTo": null, "testedFrom": "1993-01-29", "testedTo": "2026-08-04", "barsTested": 8435 },
"metrics": {
"totalTrades": 89,
"winningTrades": 80,
"losingTrades": 9,
"winRate": 0.8989,
"averageReturn": 0.0131,
"medianReturn": 0.0132,
"bestTrade": 0.0781,
"worstTrade": -0.0737,
"averageHoldingPeriod": 4.83,
"profitFactor": 6.2147,
"totalReturn": 2.1381,
"maxDrawdown": 0.0737
},
"sampleTrades": [
{ "entryDate": "2026-03-12", "exitDate": "2026-03-31", "entryPrice": 566.10, "exitPrice": 552.74, "return": -0.0236, "holdingDays": 13 }
],
"openTradeEntryDate": null
}References
- Larry Connors & Cesar Alvarez, Short Term Trading Strategies That Work — RSI(2)/RSI mean-reversion with a long-term MA filter (the lineage this rule set draws on).
- Wilder, J. W. (1978). New Concepts in Technical Trading Systems — the original RSI.
- Backtest data: SPY daily OHLCV via Yahoo Finance, 1993–2026 (this repository's market-data layer,
lib/market-data/prices.ts).
*Past behaviour does not ensure future results. confidenceScore measures setup quality, not the probability of profit.*