sigma_bands
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-10-01, from real-returns-vs-random-walks.
| sigma_band | spy_moves | normal_model_moves | sample_size |
|---|---|---|---|
| 0 to 1 sigma | 4214 | 3561.6 | 5217 |
| 1 to 2 sigma | 756 | 1418 | 5217 |
| 2 to 3 sigma | 163 | 223.3 | 5217 |
| 3 to 4 sigma | 45 | 13.8 | 5217 |
| 4 to 5 sigma | 20 | 0.3 | 5217 |
| 5 sigma plus | 19 | 0 | 5217 |
- Rows × columns
- 6 × 4
- 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 |
|---|---|---|---|
sigma_band |
text | 6 distinct values (0 to 1 sigma, 1 to 2 sigma, 2 to 3 sigma…) | |
spy_moves |
number | 19 to 4,214 | |
normal_model_moves |
number | 0 to 3,561.6 | |
sample_size |
number | every row is 5,217 |
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 date, argMax(toFloat64(close), _ingest_time) AS px FROM global_markets.stocks_daily_aggs WHERE ticker = 'SPY' AND date >= '2006-01-01' AND date <= '2026-09-30' GROUP BY date),
rets AS (SELECT date, px / prev_px - 1 AS ret FROM (SELECT date, px, lagInFrame(px) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_px FROM daily) WHERE prev_px > 0),
stats AS (SELECT avg(ret) AS mu, stddevPop(ret) AS sd, count() AS n FROM rets),
banded AS (SELECT least(toUInt8(floor(abs(r.ret - s.mu) / s.sd)), 5) AS band, s.n AS n FROM rets AS r CROSS JOIN stats AS s)
SELECT
if(band = 5, '5 sigma plus', concat(toString(band), ' to ', toString(band + 1), ' sigma')) AS sigma_band,
count() AS spy_moves,
round(any(n) * (erf((band + 1) / sqrt(2)) - erf(band / sqrt(2))), 1) AS normal_model_moves,
any(n) AS sample_size
FROM banded
GROUP BY band
ORDER BY band
Work with this data in your AI assistant
Opens ready to query, with this page's data. Free, no account.