Strasmore Research
Market Recap

Wetin happun for market June 2026

Matt ConnorBy Matt Connor Updated 2026-07-25

June 2026 na month wey show say things no dey move the same way: di big-cap indexes drop small while small caps rise, and under di index level, stocks wey fall pass di ones wey rise. SPY close at $746.32, -1.2% for di month, while IWM — di small-cap index — gain 4.2%. Anoda standout measured fact for di month: one memory-chip maker put $995.7 billion through di tape for 21 sessions, wey pass even SPY itself. Every number here na stored query result; expand any panel to see di exact SQL.

Di month wey show for board

QueryJune 2026: open to close, range, and regular-hours turnover for the four index ETFs
The exact SQL behind every number
SELECT ticker,
    round(argMinIf(toFloat64(open), window_start, (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199), 2) AS month_open,
    round(argMaxIf(toFloat64(close), window_start, (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199), 2) AS month_close,
    round((argMaxIf(toFloat64(close), window_start, (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199) / argMinIf(toFloat64(open), window_start, (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199) - 1) * 100, 1) AS month_return_pct,
    round(maxIf(toFloat64(high), (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199), 2) AS month_high,
    round(minIf(toFloat64(low), (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199), 2) AS month_low,
    round(sumIf(toFloat64(close) * toFloat64(volume), (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199) / 1e9, 1) AS rth_dollar_bn
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'QQQ', 'DIA', 'IWM')
  AND window_start >= toDateTime('2026-06-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')
GROUP BY ticker
ORDER BY ticker

Di split dey clear for di table: DIA 2.4% and IWM 4.2% go up while SPY fall -1.2% and QQQ end -0.2% — di mega-cap growth index flat-to-down for di same month wey small caps gain four percent.

June against di five months wey dey before am

E get as June fall take be like sey e no normal? Di trailing panel dey recalculate di same monthly return for every month inside di half-year with just one query — di June rows dem produce am exactly di same way dem produce January own, live as dem dey generate am.

QueryMonthly returns, January through June 2026, recomputed live (SPY and QQQ)
The exact SQL behind every number
SELECT toString(toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York')))) AS period_start, ticker,
    round((argMaxIf(toFloat64(close), window_start, (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199) / argMinIf(toFloat64(open), window_start, (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199) - 1) * 100, 1) AS month_return_pct,
    round(argMaxIf(toFloat64(close), window_start, (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199), 2) AS month_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'QQQ')
  AND window_start >= toDateTime('2026-01-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')
GROUP BY period_start, ticker
ORDER BY period_start, ticker

If you use dat measurement, June just be ordinary: SPY own -1.2% dey well inside di range wey di half get — March fall -4.4% and April rise 9.9%. Wetin characterize di month na rotation, no be any special move.

June against every June wey dey for record

QueryEvery June on the tape: SPY, recomputed identically by year (session counts shown)
The exact SQL behind every number
SELECT toYear(toTimeZone(window_start, 'America/New_York')) AS y,
       uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions,
       round((argMax(toFloat64(close), window_start) / argMin(toFloat64(open), window_start) - 1) * 100, 1) AS june_return_pct
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY')
  AND window_start >= toDateTime('2003-01-01 00:00:00')
  AND window_start < toDateTime('2026-07-01 00:00:00')
  AND toMonth(toTimeZone(window_start, 'America/New_York')) = 6
  AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY y
HAVING sessions >= 17
ORDER BY y ASC
QueryThe rank receipt: this June against every prior one (rank 1 = best; self-excluded)
The exact SQL behind every number
SELECT round(anyIf(ret, y = 2026), 1) AS june_2026_pct,
       arrayCount(x -> x > anyIf(ret, y = 2026), groupArrayIf(ret, y != 2026)) + 1 AS rank_best,
       count() AS junes_compared,
       min(y) AS first_year,
       anyIf(sessions, y = 2026) AS sessions_2026
FROM (
    SELECT toYear(toTimeZone(window_start, 'America/New_York')) AS y,
           uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions,
           (argMax(toFloat64(close), window_start) / argMin(toFloat64(open), window_start) - 1) * 100 AS ret
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker IN ('SPY')
      AND window_start >= toDateTime('2003-01-01 00:00:00')
      AND window_start < toDateTime('2026-07-01 00:00:00')
      AND toMonth(toTimeZone(window_start, 'America/New_York')) = 6
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
    GROUP BY y
    HAVING sessions >= 17
)

SPY im -1.2% rank na 15 out of 23 Junes since 2004 (rank 1 na im be the best) — e dey middle pack, small below center. Na ordinary June, and ordinary sef na valid finding: nothing about the month index-level move stand out against twenty years of Junes. Wetin stand out na the rotation wey dey under am — the breadth panel wey dey below. Basis: regular-hours open-to-close inside each calendar June, same arithmetic every year, upper bound tie to dis month end so the comparison set no fit silently grow.

Session by session

QuerySPY, all 21 June sessions: close and close-over-close change
The exact SQL behind every number
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
    round(argMaxIf(toFloat64(close), window_start, (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199), 2) AS spy_close,
    round((argMaxIf(toFloat64(close), window_start, (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199) / any(prev) - 1) * 100, 1) AS change_pct
FROM global_markets.delayed_stocks_minute_aggs
INNER JOIN (
    SELECT d, lagInFrame(c) OVER (ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev
    FROM (
        SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d, argMaxIf(toFloat64(close), window_start, (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199) AS c
        FROM global_markets.delayed_stocks_minute_aggs
        WHERE ticker = 'SPY' AND window_start >= toDateTime('2026-05-29 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')
        GROUP BY d
    )
) AS p ON toDate(toTimeZone(window_start, 'America/New_York')) = p.d
WHERE ticker = 'SPY' AND window_start >= toDateTime('2026-06-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')
GROUP BY et_date
ORDER BY et_date

Di sharpest single-session fall for di month happen early — -2.6% on 2026-06-05 — and di chart show di shape of di month: e dey drift go down through mid-June, e find floor near $716.58, and e get partial recovery over di final sessions as quarter dey turn. For di last week of dat recovery in session-by-session detail, check di week recap.

Breadth: more fall dan rise

QueryAdvancers vs decliners for June (close vs the last May close), liquidity filter disclosed
The exact SQL behind every number
SELECT
    countIf(chg > 0 AND NOT dropped) AS advancers,
    countIf(chg < 0 AND NOT dropped) AS decliners,
    countIf(chg = 0 AND NOT dropped) AS unchanged,
    countIf(dropped) AS dropped_by_liquidity_filter
FROM (
    SELECT ticker,
        argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-06-01') AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199)
      - argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-05-29') AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199) AS chg,
        sumIf(toFloat64(close) * toFloat64(volume), toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-06-01')) < 5e6 AS dropped
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE window_start >= toDateTime('2026-05-29 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')
    GROUP BY ticker
    HAVING countIf(toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-05-29') AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199) > 0
       AND countIf(toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-06-01') AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199) > 0
)

4608 tickers fall for di month against 4240 wey rise — negative breadth for one month wey two of di four index ETFs gain. Index weighting and equal-count breadth dey answer different questions; June na month wey dem disagree. Di liquidity filter comot 2896 tickers wey dia June volume no reach $5M, wey dem count here instead of hide am. Di day grain gree with di ticker grain: 12 of di month 21 sessions close SPY lower against 9 higher.

QuerySPY sessions up vs down across the month, one cheap receipt
The exact SQL behind every number
SELECT countIf(day_ret > 0) AS up_sessions,
       countIf(day_ret < 0) AS down_sessions,
       countIf(day_ret = 0) AS flat_sessions,
       count() AS sessions_total
FROM (
    SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
           round((argMax(toFloat64(close), window_start) / argMin(toFloat64(open), window_start) - 1) * 100, 2) AS day_ret
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'SPY'
      AND window_start >= toDateTime('2026-06-01 00:00:00')
      AND window_start < toDateTime('2026-07-01 00:00:00')
      AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199
    GROUP BY d
)

Di leaders for di tape

QueryJune regular-hours dollar volume, whole tape (one reused-symbol listing excluded pending entity verification)
The exact SQL behind every number
SELECT ticker,
    round(sum(toFloat64(close) * toFloat64(volume)) / 1e9, 1) AS dollar_bn,
    round(100 * sum(toFloat64(close) * toFloat64(volume)) / max(sum(toFloat64(close) * toFloat64(volume))) OVER (), 1) AS pct_of_leader
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= toDateTime('2026-06-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')
  AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199
  AND ticker NOT IN ('SPCX')
GROUP BY ticker
ORDER BY dollar_bn DESC
LIMIT 8

MU lead di whole month with $995.7 billion — SPY, wey dey second, do 77.5% of dat one. NVDA push $523 billion through for fourth; di month get im own tick-by-tick deep-dive. One semiconductor theme dey own di list — four out of di eight names. Basis: June 1–30 regular hours; dem exclude one reused-symbol June listing pending entity verification, and im first month get im own post.

Di options tape: June against May

QueryJune: whole-tape options contract volume and same-day-expiry share (one scan)
The exact SQL behind every number
SELECT round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm,
       round(100.0 * sumIf(toFloat64(volume), toDateOrNull(concat('20', substring(ticker, length(ticker) - 14, 6))) = toDate(toTimeZone(window_start, 'America/New_York'))) / sum(toFloat64(volume)), 1) AS zero_dte_pct,
       uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions
FROM global_markets.options_minute_aggs
WHERE window_start >= toDateTime('2026-06-01 00:00:00')
  AND window_start < toDateTime('2026-07-01 00:00:00')
QueryMay, recomputed identically for contrast (one scan)
The exact SQL behind every number
SELECT round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm,
       round(100.0 * sumIf(toFloat64(volume), toDateOrNull(concat('20', substring(ticker, length(ticker) - 14, 6))) = toDate(toTimeZone(window_start, 'America/New_York'))) / sum(toFloat64(volume)), 1) AS zero_dte_pct,
       uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions
FROM global_markets.options_minute_aggs
WHERE window_start >= toDateTime('2026-05-01 00:00:00')
  AND window_start < toDateTime('2026-06-01 00:00:00')

Di whole-tape options volume for June na 1477.9 million contracts, and 34.3% of dem trade on same-day expiry — against May wey get 1394.6 million and 30.3%. Volume high pass, and di same-day share big pass: June 0DTE share na di highest month for di half, and di January-onward evolution dey inside di H1 recap. One-third of June options volume expire di same day dem trade am.

QuerySPY median quoted spread: the June sample session against May's (second Wednesdays)
The exact SQL behind every number
SELECT toDate(toTimeZone(sip_timestamp, 'America/New_York')) AS session,
       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), 3) 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 = 'SPY'
  AND ((sip_timestamp >= toDateTime64('2026-05-13 13:30:00', 9) AND sip_timestamp < toDateTime64('2026-05-13 20:00:00', 9))
    OR (sip_timestamp >= toDateTime64('2026-06-10 13:30:00', 9) AND sip_timestamp < toDateTime64('2026-06-10 20:00:00', 9)))
GROUP BY session
ORDER BY session ASC

Di cost to trade di market biggest ticket move di same direction: SPY median quoted spread for di June sample session (0.409 bps, June 10) wide pass May own (0.27 bps, May 13). Basis, disclosed: single labeled sample sessions — di second Wednesday of each month — no be month-wide medians; invalid quotes dey counted inside di panel.

Rates: di curve no really move

QueryTreasury yields through June: 10-year, 2-year, and the 2s10s spread
The exact SQL behind every number
SELECT toString(date) AS d,
    round(yield_10_year, 2) AS y10,
    round(yield_2_year, 2) AS y2,
    round((yield_10_year - yield_2_year) * 100, 0) AS spread_2s10s_bp
FROM global_markets.treasury_yields
WHERE date >= toDate('2026-06-01') AND date <= toDate('2026-06-30')
  AND isNotNull(yield_10_year) AND isNotNull(yield_2_year)
ORDER BY date

Di 10-year close June for 4.44% and di 2s10s spread stand for 30 basis points — na quiet month for rates against one half wey get plenty noise (di H1 recap get di six-month curve tori).

Di calendar: heavy quarter-end traffic, one filing day wey miss

QueryJune's corporate calendar — dividends, splits, listings, filings (June 30 index gap disclosed)
The exact SQL behind every number
SELECT
    (SELECT count() FROM global_markets.stocks_dividends WHERE ex_dividend_date >= toDate('2026-06-01') AND ex_dividend_date <= toDate('2026-06-30')) AS ex_div_events,
    (SELECT count() FROM global_markets.stocks_splits WHERE execution_date >= toDate('2026-06-01') AND execution_date <= toDate('2026-06-30')) AS splits,
    (SELECT count() FROM global_markets.stocks_ipos WHERE listing_date >= toDate('2026-06-01') AND listing_date <= toDate('2026-06-30')) AS ipos,
    (SELECT uniqExact(accession_number) FROM global_markets.stocks_sec_edgar_index WHERE filing_date >= toDate('2026-06-01') AND filing_date <= toDate('2026-06-30')) AS june_filings,
    (SELECT uniqExact(accession_number) FROM global_markets.stocks_sec_edgar_index WHERE filing_date = toDate('2026-06-30')) AS filings_jun30,
    (SELECT count() FROM global_markets.stocks_news WHERE published_utc >= toDateTime('2026-06-01 00:00:00') AND published_utc < toDateTime('2026-07-01 00:00:00')) AS news_articles

June carry 6651 ex-dividend events, 164 splits, and 35 new listings — among dem na di month headline debut, wey dem cover receipt-by-receipt for di SpaceX first-month deep-dive. One disclosure on di filing count: di SEC index show 68388 June filings, but June 30 itself get only 31 — di index for di month last day no complete materially (days wey dey near get thousands), so di June total dey understated until di feed backfill — e be part of one 2026 month-end pattern wey get im own diagnostic note.

Di dividend wave

QueryEx-dividend events by day through June
The exact SQL behind every number
SELECT toString(ex_dividend_date) AS d, count() AS ex_div_events
FROM global_markets.stocks_dividends
WHERE ex_dividend_date >= toDate('2026-06-01') AND ex_dividend_date <= toDate('2026-06-30')
GROUP BY d
ORDER BY d

Dividend traffic dey cluster for di turn of di month: June open with 807 ex-dividend events for just one day, and di chart carry di full rhythm of di month — di daily churn for di low hundreds wey month-boundary spikes dey punctuate. Wetin ex-dividend date actually dey do to price dey inside di ex-dividend explainer.

Di shorts: both June prints dey for file

QueryShort-interest settlements on file: May 29, June 15, and June 30
The exact SQL behind every number
SELECT toString(settlement_date) AS settlement, count() AS tickers
FROM global_markets.stocks_short_interest
WHERE settlement_date >= toDate('2026-05-20')
GROUP BY settlement
ORDER BY settlement

Short interest dey settle two times for month and dem dey publish am with delay. Both June prints don dey for file now: di 2026-06-30 settlement get 22207 tickers, afta 22178 for di June 15 file and 21987 for May 29. Daily short volume na different dataset; di June caveat for am na di June 29 file wey dem cut short, wey dey inside di week recap and di June 29 deep-dive.

Di session receipt

Query21 sessions, verified from the tape (Juneteenth closure receipt included)
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-06-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')) AS june_sessions,
    (SELECT count() FROM global_markets.delayed_stocks_minute_aggs
     WHERE ticker = 'SPY' AND window_start >= toDateTime('2026-06-19 00:00:00') AND window_start < toDateTime('2026-06-20 00:00:00')) AS juneteenth_spy_bars,
    (SELECT countIf((toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199) FROM global_markets.delayed_stocks_minute_aggs
     WHERE ticker = 'SPY' AND window_start >= toDateTime('2026-06-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')) AS regular_bars_june

June run 21 sessions — Juneteenth (June 19) show 0 SPY bars, and di 8190 regular bars work out to exactly 21 full 390-minute sessions.

Data notes

Full data notes
  • Short interest dey run through di June 30 settlement — di two prints for di month dey for file and dem carry am inline for up.
  • Di June 30 filing-index day no complete materially (small handful of administrative filings against thousands for nearby days); June filing totals dey understated until di feed backfill. Every 2026 month-end wey im last calendar day be weekday show di same signature — di diagnostic note carry di receipts; di Q2 recap carry di quarter-scale caveat.
  • Di June 29 FINRA short-volume file dey truncated market-wide — receipts dey inside di week recap and di June 29 deep-dive.
  • Volume-leader exclusion: one June listing dey trade under reused symbol and dem exclude am from di leaderboard pending entity verification; im own post carry di verification receipts.
  • Breadth dey compare each ticker last June close against im last May close; tickers wey no get both closes dem exclude by construction and di liquidity filter exclusions dem count inside di panel.

How We Do Am

  • Di period na June 1–30, 2026 — 21 sessions, wey we confam from di bars wey we see (di receipt panel for up). Monthly returns na from first regular-hours open to last regular-hours close inside di period.
  • We store timestamps for UTC and filter dem with raw UTC bounds; June 2026 na entirely EDT, so regular hours na 13:30–20:00 UTC. Dollar volume na minute close times minute volume over regular hours.
  • We dey recompute trailing-month comparisons live inside di same query wey get June own row — we no dey ever read am from stored value. Di every-June history block dey do di same tin across di full minute tape (Eastern-wall-clock regular hours — di DST-safe multi-year convention — with im upper bound pinned for dis month end and minimum-session guard wey dey show per year); di depth verification dey inside H1 recap im methodology.
  • Generation dey run through di gated read-only path; di public page no dey ever query live. Warehouse state as of July 5, 2026.

Dis na di first edition of di standing monthly recap — July own edition go link back here. For di month final week in session-by-session detail, check di week-of-June-29 recap; for di quarter wey dis month close, check di Q2 recap.