ML day trader
Bottom line
6 variants tried so far (monthly and intraday together), so a strategy needs t ≥ 2.6 against a risk-matched SPY to pass. The ultra-risky slot has no drawdown limit.
- ✗ FAIL Day trader (ridge): 1.9%/yr vs 11.3% for SPY · Sharpe 0.12 vs 0.58 · worst drop -17% · 1.0 trades a day · t = -1.0, needed 2.6
- ✗ FAIL Day trader (gbm): 0.5%/yr vs 11.3% for SPY · Sharpe -0.01 vs 0.58 · worst drop -22% · 2.1 trades a day · t = -1.5, needed 2.6
Scorecard
| CAGR | Sharpe | Max drawdown | Turnover / yr | Excess vs risk-matched SPY / yr | t-stat vs risk-matched SPY | Needed t | Drawdown limit | Result | |
|---|---|---|---|---|---|---|---|---|---|
| Day trader (ridge) | 1.9% | 0.12 | -17% | 24833% | -4.1% | -1.0 | 2.6 | -100% | ✗ FAIL |
| Day trader (gbm) | 0.5% | -0.01 | -22% | 52136% | -6.4% | -1.5 | 2.6 | -100% | ✗ FAIL |
| SPY, daytime only | -4.0% | -0.31 | -30% | 50400% | -12.3% | -3.1 | — | — | reference |
| Last-half-hour momentum | -3.6% | -1.29 | -23% | 27570% | -6.9% | -3.8 | — | — | reference |
| Buy & hold SPY | 11.3% | 0.58 | -34% | 0% | — | — | — | — | reference |
SPY, daytime only holds SPY from 10:00 to the close every day and nothing overnight, the simplest possible day trade. Last-half-hour momentum is a published intraday pattern: if SPY is up from yesterday's close to 10:00, hold it for the final 30 minutes.
Trading activity
Day trading lives or dies on the average gain per trade versus the cost per trade. A block's gain is before costs; each trade (buy or sell) costs 1 bp.
| Trades / day | Time in market | Win rate (blocks held) | Avg gain per block held (bps) | Cost / day (bps) | |
|---|---|---|---|---|---|
| Day trader (ridge) | 1.0 | 20% | 54.0% | +0.59 | 1.0 |
| Day trader (gbm) | 2.1 | 23% | 52.7% | +0.73 | 2.1 |
| SPY, daytime only | 2.0 | 100% | 52.4% | +0.02 | 2.0 |
| Last-half-hour momentum | 1.1 | 5% | 46.6% | -1.48 | 1.1 |
How much do trading costs matter?
The same trades, charged 0, 1 and 3 bps per dollar traded.
| CAGR @ 0 bps | CAGR @ 1 bps | CAGR @ 3 bps | Sharpe @ 0 bps | Sharpe @ 1 bps | Sharpe @ 3 bps | |
|---|---|---|---|---|---|---|
| Day trader (ridge) | 4.5% | 1.9% | -3.0% | 0.40 | 0.12 | -0.44 |
| Day trader (gbm) | 5.9% | 0.5% | -9.5% | 0.47 | -0.01 | -0.97 |
| SPY, daytime only | 1.0% | -4.0% | -13.2% | 0.05 | -0.31 | -1.05 |
| Last-half-hour momentum | -0.9% | -3.6% | -8.8% | -0.55 | -1.29 | -2.75 |
Can the model predict anything?
IC (information coefficient): the rank correlation between the predicted and actual next-30-minute returns, averaged by month. 0 means no skill; for intraday returns, even +0.02 to +0.05 that holds up would be a real, useful signal. Direction right: how often the predicted sign (up or down) was correct; 50% is a coin flip.
| Avg monthly IC | IC t-stat | Direction right | |
|---|---|---|---|
| Day trader (ridge) | +0.009 | +1.4 | 50.5% |
| Day trader (gbm) | +0.025 | +3.6 | 51.4% |
What the main (ridge) model learned
Average weight on each feature across the monthly retrains, in bps of predicted 30-minute return per standard deviation of the feature.
| Average weight (bps) | Meaning | |
|---|---|---|
| Return, last 5 minutes | -0.625 | predicts lower returns when this is high |
| Overnight gap (today's open vs yesterday's close) | +0.595 | predicts higher returns when this is high |
| Yesterday's return | -0.502 | predicts lower returns when this is high |
| Volatility, yesterday | +0.327 | predicts higher returns when this is high |
| Return, last 15 minutes | +0.317 | predicts higher returns when this is high |
| Return since today's open | +0.207 | predicts higher returns when this is high |
| Volume, last 30 min vs usual for this time | -0.192 | predicts lower returns when this is high |
| Return over the previous 5 days | +0.172 | predicts higher returns when this is high |
| Return, last 30 minutes | -0.085 | predicts lower returns when this is high |
| Volatility, last 30 minutes | -0.080 | predicts lower returns when this is high |
| QQQ rather than SPY | -0.050 | predicts lower returns when this is high |
| Time of day (block 1-12) | -0.032 | no real effect |
Year by year
Blue = up, red = down; deeper shade = bigger move.
| Day trader (ridge) | Day trader (gbm) | SPY, daytime only | Last-half-hour momentum | Buy & hold SPY | |
|---|---|---|---|---|---|
| 2017 | 2.0% | 0.4% | 3.4% | -3.7% | 21.7% |
| 2018 | 0.2% | -16.6% | -21.9% | -4.8% | -4.6% |
| 2019 | 3.4% | 1.5% | 8.0% | -0.2% | 31.2% |
| 2020 | 19.0% | 1.9% | 2.8% | 3.0% | 18.3% |
| 2021 | 2.1% | 7.8% | -1.5% | -11.2% | 28.7% |
| 2022 | -12.8% | 10.4% | -11.1% | -4.0% | -18.2% |
Every variant tried
Shared with the monthly ML strategies. Never delete rows.
| first_tried | config |
|---|---|
| 2026-10-12 | ML moderate | ridge | top 3 | features v1 |
| 2026-10-12 | ML safe | ridge | top 3 | 200-day crash filter | features v1 |
| 2026-10-12 | ML moderate | gbm | top 3 | features v1 |
| 2026-10-12 | ML safe | gbm | top 3 | 200-day crash filter | features v1 |
| 2026-10-12 | Day trader | ridge | SPY+QQQ 30-min blocks | enter above round-trip cost | features intraday-v1 |
| 2026-10-12 | Day trader | gbm | SPY+QQQ 30-min blocks | enter above round-trip cost | features intraday-v1 |
How it works
- Data: 5-minute bars from Alpaca's full-market feed since 2016, official trading hours only (early-close days end at 13:00).
- Decisions at 10:00, 10:30, …, 15:30. Each uses only bars finished by then and fills at the next bar's open; the last block ends at the closing price. Nothing is held overnight.
- Features: recent returns (5, 15, 30 minutes, since the open, the overnight gap, yesterday, the last 5 days), recent volatility, volume versus normal for that time of day, the time of day, and which ETF.
- Target: the return over the next 30 minutes (capped at ±1.5% during training).
- Rule: buy the ETF with the higher prediction when it beats the round-trip cost (2 bps); keep holding while the prediction stays positive; otherwise cash.
- Walk-forward: retrained at the start of each month on all earlier months (at least 12), so it never sees the month it trades.
- Cash earns the T-bill rate: the account is always in cash at the close, when brokers calculate interest.
- Not modeled: delays in getting real-time data, partial fills, and taxes (every gain is short-term). Past results are not a forecast.