STRASMORE/EXPLORE 2,309 QUERIES

worst_windows

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-09-17, from santa-claus-rally.

as of table 5×5read in context →
worst_windows — 5 rows by 5 columns, computed from US exchange, SIP and OPRA data.
labelmeasured_frommeasured_tosanta_window_pctfollowing_year_pct
Dec 2014 to Jan 2015Dec 23Jan 5-2.9-0.81
Dec 2015 to Jan 2016Dec 23Jan 5-2.269.64
Dec 2007 to Jan 2008Dec 21Jan 3-2.21-38.28
Dec 2004 to Jan 2005Dec 23Jan 4-1.613.01
Dec 2023 to Jan 2024Dec 21Jan 3-0.8323.3
Rows × columns
5 × 5
Computed
Completeness
No missing values
Source
US exchange, SIP and OPRA market data
Licence
Strasmore terms · free, no signup
Formats
JSON · CSV · the SQL below

What each column holds

Column definitions for worst_windows, derived from the stored result.
ColumnTypeRangeNotes
label text 5 distinct values
measured_from text 2 distinct values (Dec 21, Dec 23)
measured_to text 3 distinct values (Jan 3, Jan 4, Jan 5)
santa_window_pct number -2.9 to -0.83 percent
following_year_pct number -38.28 to 23.3 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.

the exact SQL behind every number
WITH
    spy_days AS
    (
        SELECT
            date,
            toYear(date)                                   AS y,
            toMonth(date)                                  AS m,
            argMax(toFloat64(close), _ingest_time)         AS close
        FROM global_markets.stocks_daily_aggs
        WHERE ticker = 'SPY'
        GROUP BY date
    ),
    ranked AS
    (
        SELECT
            date,
            y,
            m,
            close,
            row_number() OVER (PARTITION BY y, m ORDER BY date DESC) AS sessions_from_end,
            row_number() OVER (PARTITION BY y, m ORDER BY date ASC)  AS sessions_from_start
        FROM spy_days
        WHERE m IN (12, 1)
    ),
    windows AS
    (
        SELECT
            toUInt16(if(m = 1, y - 1, y))                       AS year,
            toUInt16(year + 1)                                  AS next_year,
            anyIf(date, m = 12 AND sessions_from_end = 6)       AS base_date,
            anyIf(date, m = 1 AND sessions_from_start = 2)      AS end_date,
            anyIf(close, m = 12 AND sessions_from_end = 6)      AS base_close,
            anyIf(close, m = 12 AND sessions_from_end = 1)      AS december_close,
            anyIf(close, m = 1 AND sessions_from_start = 2)     AS end_close
        FROM ranked
        GROUP BY year
        HAVING countIf(m = 12 AND sessions_from_end = 6) = 1
           AND countIf(m = 1 AND sessions_from_start = 2) = 1
    ),
    year_ends AS
    (
        SELECT
            y,
            argMax(close, date)                                 AS year_end_close
        FROM spy_days
        WHERE m = 12
          AND date < toStartOfYear(today())
        GROUP BY y
    )
SELECT
    concat('Dec ', toString(w.year), ' to Jan ', toString(w.next_year))                 AS label,
    concat(formatDateTime(w.base_date, '%b '), toString(toDayOfMonth(w.base_date)))     AS measured_from,
    concat(formatDateTime(w.end_date, '%b '), toString(toDayOfMonth(w.end_date)))       AS measured_to,
    round((w.end_close / w.base_close - 1) * 100, 2)                                    AS santa_window_pct,
    round((n.year_end_close / w.december_close - 1) * 100, 2)                           AS following_year_pct
FROM windows AS w
INNER JOIN year_ends AS n ON n.y = w.next_year
ORDER BY santa_window_pct ASC
LIMIT 5

Run your own version of this

The same 22 years of US equities and 12 years of options data are queryable in SQL or plain English. A free account runs 100 queries a day and takes no card.

More from this analysissanta-claus-rally
santa_windows table 23×5 window_vs_december table 3×8 folklore_test table 2×6 window_volume ranking 7×4 The 2s10s spread, every print of the half table 124×2 The 2s10s spread, every print of the half table 124×2 See all 2,309 queries →