Strasmore Research
Deep Dives · 2026-07-04

Sector Scorecard, H1 2026: Returns and Cost to Trade

All eleven sector ETFs, H1 2026: a forty-point spread between best and worst, an energy round trip the half number hides, and what each sector costs to trade.

Which parts of the market actually made the first half's money — and what does it cost to trade each of them? The eleven SPDR sector ETFs answer the first question the way any return table can; the second question needs a quote tape, and that is where this page goes further than a scorecard usually can. Every number is a stored query result; expand any panel for the exact SQL.

The scorecard: H1, split into its two quarters

QueryThe eleven sector ETFs: H1 2026 return, Q1 and Q2 split, and H1 dollar volume
The exact SQL behind every number
SELECT ticker,
    round((argMaxIf(toFloat64(close), window_start, 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)
         / argMinIf(toFloat64(open), window_start, toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-01-01') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS h1_return_pct,
    round((argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-03-31') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)
         / argMinIf(toFloat64(open), window_start, toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-01-01') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS q1_return_pct,
    round((argMaxIf(toFloat64(close), window_start, 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)
         / argMinIf(toFloat64(open), window_start, toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-04-01') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS q2_return_pct,
    round(sumIf(toFloat64(close) * toFloat64(volume), (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) / 1e9, 1) AS h1_dollar_bn
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('XLB', 'XLC', 'XLE', 'XLF', 'XLI', 'XLK', 'XLP', 'XLRE', 'XLU', 'XLV', 'XLY')
  AND window_start >= toDateTime('2026-01-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')
GROUP BY ticker
ORDER BY ticker

The dispersion is the story: technology (XLK) finished the half up 30.8% — with a 42% second quarter — while communication services (XLC) finished -9.3%, a spread of roughly forty percentage points between the best and worst sector in six months. Owning "the market" meant owning both ends of that.

The rotation the half-year number hides

Energy is the panel's cautionary tale about long windows: XLE shows a healthy 18.8% half — built from a 36.9% FIRST quarter followed by a -11% second. It was the market's strongest large sector in the quarter the indexes fell, and among its weakest in the quarter they recovered. Financials (XLF) ran the same movie backwards: -9.9% in Q1, then 7.7% in Q2. A single H1 number flattens both round trips; the quarter split is the honest view.

What it costs to trade each sector

Return tables are everywhere; quote tapes are not. This panel measures each sector ETF's median bid-ask spread across one full representative session — 123 sessions in the half, and June 29 is the one measured here, labeled as such — from every NBBO update that day.

QueryMedian quoted spread by sector ETF, one representative session (June 29, 2026), regular hours
The exact SQL behind every number
SELECT ticker,
    round(quantileDeterministicIf(0.5)((toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2) * 10000, toUInt64(toUnixTimestamp64Micro(sip_timestamp)), bid_price > 0 AND ask_price >= bid_price), 2) AS med_spread_bps,
    round(count() / 1e6, 2) AS quote_updates_m,
    countIf(NOT (bid_price > 0 AND ask_price > 0 AND ask_price >= bid_price)) AS invalid_dropped
FROM global_markets.cache_stocks_quotes
WHERE ticker IN ('XLB', 'XLC', 'XLE', 'XLF', 'XLI', 'XLK', 'XLP', 'XLRE', 'XLU', 'XLV', 'XLY')
  AND sip_timestamp >= toDateTime64('2026-06-29 13:30:00', 9) AND sip_timestamp < toDateTime64('2026-06-29 20:00:00', 9)
GROUP BY ticker
ORDER BY med_spread_bps

Every one of the eleven quotes at a few basis points or less — the cheapest at 0.62 bps (XLV), the widest at 2.23 bps (XLRE) — which is the practical meaning of "sector ETFs are liquid": the cost of entering any sector view is measured in hundredths of a percent. For scale against individual stocks, the June 29 deep-dive measures a thin name's spread at hundreds of times these levels, on the same session.

The session receipt

Query123 sessions in the half, verified from the tape
The exact SQL behind every number
SELECT
    (SELECT uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) FROM global_markets.delayed_stocks_minute_aggs
     WHERE ticker = 'SPY' AND window_start >= toDateTime('2026-01-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')) AS h1_sessions

Data notes

Full data notes
  • Sector definitions here are the SPDR select-sector ETFs, not index classifications — an ETF's return includes its expense drag and premium/discount noise, which is also exactly what a tradeable sector position experiences.
  • The spread panel measures ONE full session (June 29, 2026, a verified regular session) rather than the whole half — a half-year, eleven-ticker quote scan exceeds this page's query budget. The session is labeled everywhere it is used; invalid quotes are counted in the panel, not silently dropped.
  • Returns are first regular-hours open to last regular-hours close per window, Eastern-clock session filter (the half spans EST and EDT months).
  • The index-level view of the same half is in the H1 recap; the market-cap-size divergence (small caps leading) is covered there.

Methodology

  • Period: January 1 – June 30, 2026 (123 sessions, verified from observed bars). Timestamps stored UTC; date ranges filter on raw UTC bounds; the regular-hours condition uses the Eastern clock.
  • Spread medians are deterministic quantiles over every valid NBBO update in the measured session; basis points are computed against the quote midpoint.
  • Generation runs through the gated read-only path; the public page never queries live. Warehouse state as of July 4, 2026.

Every panel is one stored object — chart, table, and SQL. Take any sector further on the Strasmore terminal.