VWAP Rejection Strategy Backtest
480 trading days · SPY 5-minute bars · Alpaca SIP feed · 7 parameter configurations
Methodology
This backtest evaluates the VWAP rejection signal on SPY using 5-minute intraday bars over 480 trading days (approximately 2 years). All data comes from Alpaca's SIP feed, which aggregates all US exchange activity. This is the same data institutional algorithms use.
Session VWAP is calculated cumulatively from the 9:30 AM ET open using each bar's volume-weighted average price (vw) and volume (v). The formula: VWAP = sum(vw * v) / sum(v) across all bars from open to the current bar. This matches the VWAP displayed on professional platforms like ThinkOrSwim and Bloomberg Terminal.
The backtest runs each trading day independently with no overnight carry and no multi-day positions. Each day starts fresh with zero state, processes all 5-minute bars sequentially, and tracks up to 3 trades per session with a 2-bar (10-minute) cooldown between exits and new entries.
Signal Definition
The VWAP rejection signal identifies moments where price approaches VWAP from the losing side and fails to reclaim it, confirming the existing trend. It is a trend continuation signal, not a reversal.
Entry Conditions (ALL must be true)
- Established trend: Price has closed on the same side of VWAP for 5+ consecutive 5-minute candles. This confirms a directional bias exists.
- VWAP approach: At least one of the last 3 candles wicked within 0.04% of price from VWAP. For a bullish rejection, the bar low must approach VWAP from above. For bearish, the bar high must approach from below.
- Rejection confirmed: The completed candle closes back on the trending side of VWAP, at least 0.03% away. The approach failed and VWAP held.
- Volume confirmation:The rejection candle's volume must be at least 1.0x the average of the prior 3 completed candles.
Additional Filters
- First 2 candles after open (9:30-9:40 AM) are skipped
- Maximum 3 trades per session
- 2-bar cooldown after any exit before a new signal is eligible
Exit Rules
Three exit mechanisms are evaluated in priority order:
- Entry candle stop:If a subsequent 5-minute bar closes below the entry candle's low (for longs) or above the entry candle's high (for shorts), the position is closed. This is a structural invalidation. The buying/selling pressure that created the signal has been broken.
- Trailing stop: The high watermark tracks the maximum favorable move in SPY points. When the current move retraces below (1 - trailing_pct) * high_watermark, the position is closed. Multiple trailing percentages are tested: 50%, 35%, and 25%.
- Time stop: Any position still open at 3:45 PM ET is closed. This prevents 0DTE theta collapse in the final 15 minutes.
Parameter Sweep: 7 Configurations
Rather than optimizing a single parameter set (which risks curve-fitting), we test 7 configurations against the same 480 days of data. All configurations are profitable, suggesting the edge is structural rather than parameter-dependent.
| Config | Stop Bars | Trail % | ATR | Trades | WR% | R:R | Total Pts |
|---|---|---|---|---|---|---|---|
| wide_stop | 2 | 50% | N | 1,217 | 41.7% | 1.59 | +57.1 |
| baseline | 1 | 50% | N | 1,224 | 40.7% | 1.66 | +55.5 |
| wide+loose+atr | 2 | 35% | Y | 1,144 | 45.3% | 1.29 | +23.1 |
| very_loose+atr | 2 | 25% | Y | 1,147 | 46.6% | 1.22 | +21.5 |
| loose_trail | 1 | 35% | N | 1,258 | 43.2% | 1.37 | +15.5 |
| very_loose | 2 | 25% | N | 1,256 | 46.2% | 1.20 | +12.7 |
| wide+loose | 2 | 35% | N | 1,250 | 44.8% | 1.27 | +12.2 |
Stop Bars: Number of bars used to define the structural stop zone. 1 = entry candle only, 2 = entry + prior candle (wider stop, fewer false exits).
Trail %: The trailing stop retracement threshold. 50% means the trade is closed when the move retraces 50% from peak. Lower values exit sooner (tighter).
ATR Filter:When enabled, skips entries where the current bar's true range exceeds 1.5x the 10-bar rolling ATR. Filters out high-volatility noise bars.
Key Findings
1. The edge comes from asymmetric payoffs, not win rate
The best configuration wins only 41.7% of the time, but winners average +$0.93 pts while losers average -$0.59 pts (1.59 R:R). This asymmetry is created by the trailing stop: winners are allowed to run on trend days while losers are cut quickly by the entry candle stop.
Why a sub-50% win rate can still be profitable
What matters is not how often you win, but how much you win relative to how much you lose. With a 1.59 R:R ratio, each winner recovers 1.59 losers. Over 100 trades:
41 wins × $0.93 avg = $38.13 gained
59 losses × $0.59 avg = $34.81 lost
Net: +$3.32 profit
The breakeven win rate at 1.59 R:R is 1 / (1 + 1.59) = 38.6%. Our 41.7% clears that by 3.1 percentage points. Most retail strategies chase high win rates with tight profit targets and wide stops, which inverts the ratio. A single bad loss wipes out many small wins. This strategy does the opposite: lose small, win big.
2. The 50% trailing stop outperforms tighter settings
Tighter trailing stops (35%, 25%) increase win rate but reduce average win size. The 50% setting captures trend day runners, trades that move +2-5 pts when SPY trends directionally all day. These “time stop” trades (held to 3:45 PM) average +2.75 pts and are the primary source of edge.
3. Rejection signals are the workhorse
Rejection signals (845 trades) generate more total profit than cross signals (379 trades). Rejections trade with the established trend, which has a natural tailwind on trend days. Cross signals have a slightly higher win rate (44% vs 39%) but smaller average wins.
4. Short trades have a slight edge over longs
Short trades average +0.10 pts vs -0.01 pts for longs. This may reflect that SPY selloffs tend to be faster and more volatile than rallies, giving the trailing stop more room to capture moves. However, both directions are profitable in the best configurations.
5. All configurations are profitable
Every parameter set tested is net positive over 480 days. This suggests the edge is structural. VWAP rejection is a real phenomenon in intraday markets, not an artifact of parameter optimization. The robustness across configurations is more important than the specific numbers of any single config.
Exit Type Breakdown (Best Config)
| Exit Reason | Count | Avg P/L | Interpretation |
|---|---|---|---|
| trailing_stop | 776 | +0.14 pts | Small winners that moved, then retraced |
| entry_candle_stop | 344 | -0.92 pts | Signal invalidated quickly, controlled loss |
| time_stop | 95 | +2.80 pts | Trend day runners held to close. The money makers. |
The 95 time-stop trades (7.8% of total) contribute disproportionate profit. These are trend days where SPY moves directionally all session and the position never hits the trailing stop. On 0DTE options, a +2.80 pt SPY move translates to roughly 150-300% on an ATM call/put.
Live Trade Example: May 6, 2026
Here is a real trade taken on this strategy using Alpaca paper trading. This shows how the signal detection works on live data and how the position plays out on a trend day.
Signal Detection
Starting at 9:30 AM ET, each 5-minute bar is classified as GREEN (close above VWAP) or RED (close below VWAP). By 9:50 AM, five consecutive bars had closed above VWAP, making rejection signals eligible.
| Bar | Close | VWAP | Side | Count |
|---|---|---|---|---|
| 9:30 | 729.13 | 728.65 | GREEN | 1 |
| 9:35 | 729.08 | 728.68 | GREEN | 2 |
| 9:40 | 729.13 | 728.76 | GREEN | 3 |
| 9:45 | 729.08 | 728.82 | GREEN | 4 |
| 9:50 | 729.66 | 728.86 | GREEN | 5 |
The Rejection Candle (9:50 AM)
The 9:50 bar is where the signal fires. It opened at 729.08, dropped to a low of 728.32 (well below VWAP at 728.86), then reversed and closed at 729.66. All four conditions passed:
- 5 consecutive GREEN bars (trend established)
- Bar low 728.32 wicked through VWAP at 728.86 (approach confirmed)
- Close at 729.66, which is $0.80 above VWAP (rejection confirmed, well above the 0.03% minimum of $0.22)
- Volume 650,728 vs. avg of prior 3 bars 566,672 (1.15x, passes the 1.0x filter)
The signal triggered a buy of 2x SPY 729C (0DTE) at $1.51 per contract. The entry candle's low of 728.32 became the structural stop level.
How the Trade Played Out
| Time | SPY | 729C Mid | P/L (2 contracts) |
|---|---|---|---|
| 9:57 (entry) | $729.18 | $1.51 | $0 |
| 10:01 | $729.91 | $1.75 | +$48 |
| 10:30 | $729.65 | $1.66 | +$30 |
| 12:00 | $731.50 | $2.85 | +$268 |
| 2:00 PM | $733.00 | $4.10 | +$518 |
| 3:36 PM (EOD) | $733.83 | $4.70 | +$638 |
SPY trended above VWAP for the entire session, never triggering the entry candle stop (728.32) or the trailing stop. Under the strategy rules, this position would be held until the 3:45 PM time stop for a total gain of +$638 (+211%) on $302 of risk.
Theta vs. Delta on 0DTE
At entry: $0.66 intrinsic + $0.85 extrinsic = $1.51
At EOD: $4.83 intrinsic + $0.00 extrinsic = $4.83
Theta destroyed $0.85 of time value.
Delta generated $4.17 of intrinsic value.
Delta wins 5:1 on a trend day.
When a 0DTE option goes deep in-the-money, it becomes almost entirely intrinsic value. Theta has nothing left to decay. This is why trend days are so profitable for 0DTE directional strategies: the option effectively becomes a leveraged proxy for the underlying move.
Data and Limitations
- Data source: Alpaca Markets SIP feed, 5-minute OHLCV bars with bar-level VWAP (vw field).
- Period: 480 trading days ending May 5, 2026.
- Slippage: Not modeled. Entries and exits use bar close prices. Real 0DTE option fills may have 1-3 cent spread impact.
- Option pricing: Not modeled. Results are in SPY points. ATM 0DTE options have approximately 0.50 delta at entry, increasing toward 1.0 as they go ITM. Actual option P/L will be higher on winning trades (convexity) and roughly equal on losers (delta decay).
- No look-ahead bias: Each bar is processed sequentially using only prior data. VWAP is cumulative from open. Signals use only completed candles (second-to-last bar).
- Survivorship bias: Not applicable. SPY is the sole instrument.
Get Early Access
Join the waitlist to receive daily premarket scans and trade setups before the market opens.