{"slug":"etf-relative-strength-alpha-attribution","qid":"monthly_leaders","label":"Strongest and weakest sleeve versus SPY, by calendar month","post_title":"ETF Relative Strength and Alpha Attribution","post_url":"/blog/etf-relative-strength-alpha-attribution#q-monthly_leaders","columns":["month","leading_etf","leader_excess_pct","laggard_excess_pct"],"rows":[{"month":"2025-07","leading_etf":"XLK","leader_excess_pct":2.35,"laggard_excess_pct":-6.93},{"month":"2025-08","leading_etf":"IWM","leader_excess_pct":5.67,"laggard_excess_pct":-5.48},{"month":"2025-09","leading_etf":"GLD","leader_excess_pct":5.13,"laggard_excess_pct":-5.35},{"month":"2025-10","leading_etf":"XLK","leader_excess_pct":3.61,"laggard_excess_pct":-3.95},{"month":"2025-11","leading_etf":"XLV","leader_excess_pct":9.13,"laggard_excess_pct":-5.2},{"month":"2025-12","leading_etf":"XLF","leader_excess_pct":3.31,"laggard_excess_pct":-3.78},{"month":"2026-01","leading_etf":"XLE","leader_excess_pct":10.54,"laggard_excess_pct":-4},{"month":"2026-02","leading_etf":"GLD","leader_excess_pct":14.61,"laggard_excess_pct":-3.46},{"month":"2026-03","leading_etf":"XLE","leader_excess_pct":12.65,"laggard_excess_pct":-6.93},{"month":"2026-04","leading_etf":"XLK","leader_excess_pct":8.55,"laggard_excess_pct":-12.91},{"month":"2026-05","leading_etf":"XLK","leader_excess_pct":13.04,"laggard_excess_pct":-9.55},{"month":"2026-06","leading_etf":"XLV","leader_excess_pct":8.87,"laggard_excess_pct":-8.87},{"month":"2026-07","leading_etf":"XLE","leader_excess_pct":12.59,"laggard_excess_pct":-5.7}],"shape":"series","sql":"WITH monthly AS\n(\n    SELECT\n        toStartOfMonth(date)           AS m,\n        ticker,\n        argMin(toFloat64(close), date) AS first_close,\n        argMax(toFloat64(close), date) AS last_close\n    FROM global_markets.stocks_daily_aggs\n    WHERE ticker IN ('SPY', 'QQQ', 'IWM', 'XLK', 'XLE', 'XLF', 'XLV', 'XLU', 'GLD', 'EFA')\n      AND date >= toStartOfMonth(today() - 400)\n      AND date <  toStartOfMonth(today())\n    GROUP BY m, ticker\n)\nSELECT\n    formatDateTime(x.m, '%Y-%m')   AS month,\n    argMax(x.ticker, x.excess_pct) AS leading_etf,\n    round(max(x.excess_pct), 2)    AS leader_excess_pct,\n    round(min(x.excess_pct), 2)    AS laggard_excess_pct\nFROM\n(\n    SELECT\n        sleeve.m      AS m,\n        sleeve.ticker AS ticker,\n        (sleeve.last_close / sleeve.first_close - 1) * 100\n          - (bench.spy_last / bench.spy_first - 1) * 100 AS excess_pct\n    FROM monthly AS sleeve\n    INNER JOIN\n    (\n        SELECT\n            m,\n            first_close AS spy_first,\n            last_close  AS spy_last\n        FROM monthly\n        WHERE ticker = 'SPY'\n    ) AS bench USING (m)\n    WHERE sleeve.ticker != 'SPY'\n) AS x\nGROUP BY x.m\nORDER BY x.m","computed_at":"2026-08-22T04:05:29.316706+00:00","elapsed":0.050514913}