S&P 500 tracker (SPY): down sessions by calendar year, 2016 to mid-2026
Answered against 22 years of US equities and 12 years of US options data and published with the query that produced it. This result is stored as of 2026-08-15, from The 3-5-7 Rule in Options, Examined.
| year | sessions | days_down_1pct | days_down_3pct | worst_day_pct |
|---|---|---|---|---|
| 2016 | 252 | 22 | 1 | -3.61 |
| 2017 | 251 | 4 | 0 | -1.77 |
| 2018 | 251 | 32 | 5 | -4.12 |
| 2019 | 252 | 15 | 0 | -2.98 |
| 2020 | 253 | 45 | 16 | -11.63 |
| 2021 | 252 | 21 | 0 | -2.45 |
| 2022 | 251 | 65 | 8 | -4.34 |
| 2023 | 250 | 28 | 0 | -1.99 |
| 2024 | 252 | 19 | 0 | -2.97 |
| 2025 | 250 | 30 | 3 | -5.98 |
| 2026 | 123 | 15 | 0 | -2.59 |
- Rows × columns
- 11 × 5
- Computed
- Completeness
- No missing values
- Source
- US exchange, SIP and OPRA market data
- Licence
- Strasmore terms · free, no signup
What each column holds
| Column | Type | Range | Notes |
|---|---|---|---|
year |
number | 2,016 to 2,026 | |
sessions |
number | 123 to 253 | |
days_down_1pct |
number | 4 to 65 | |
days_down_3pct |
number | 0 to 16 | |
worst_day_pct |
number | -11.63 to -1.77 | percent |
Computed from Strasmore's warehouse of US exchange, SIP and OPRA market data. Equity prices are delayed; options greeks and implied volatility are end-of-day. This result is stored, not recomputed on load — it is exactly the numbers that were returned on , and the query below is what returned them.
Run it yourself
This is the exact query behind the result above. Change a ticker, a date or a column and run it against the warehouse — no account, no key. The no-signup tier is smaller than the one this page was computed on; a query that reaches past it comes back saying which plan runs it.
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
toFloat64(argMax(close, window_start)) AS px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2015-12-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-06-30')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY d
),
moves AS (
SELECT d,
100 * (px / any(px) OVER (ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) - 1) AS move_pct
FROM daily
)
SELECT toYear(d) AS year,
count() AS sessions,
countIf(move_pct <= -1) AS days_down_1pct,
countIf(move_pct <= -3) AS days_down_3pct,
round(min(move_pct), 2) AS worst_day_pct
FROM moves
WHERE isFinite(move_pct) AND toYear(d) >= 2016
GROUP BY year
ORDER BY year
Работайте с этими данными в своём ИИ-ассистенте
Открывается готовым к запросам, с данными этой страницы. Бесплатно, без аккаунта.