June 2026 was a month of divergence: the large-cap indexes slipped while small caps rose, and beneath the index level, more stocks fell than rose. SPY finished at $746.32, -1.2% on the month, while IWM, the small-cap index, gained 4.2%. The month's other standout measured fact: one memory-chip maker put $995.7 billion through the tape in 21 sessions, more than SPY itself. Every number here is a stored query result; expand any panel for the exact SQL.
The month on the board
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 tickerThe split reads directly off the table: DIA 2.4% and IWM 4.2% rose while SPY fell -1.2% and QQQ finished -0.2%, the mega-cap growth index flat-to-down in the same month small caps gained four percent.
June against the five months before it
Was June's dip unusual? The trailing panel recomputes the same monthly return for every month of the half in one query, the June rows are produced identically to January's, live at generation time.
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, tickerBy that yardstick June was ordinary: SPY's -1.2% sits well inside the half's range, March fell -4.4% and April rose 9.9%. The month's character was rotation, not direction.
June against every June on the tape
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 ASCThe 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's -1.2% ranks 15 of 23 Junes since 2004 (rank 1 = best), mid-pack, slightly below the middle. An ordinary June, and ordinary is a valid finding: nothing about the month's index-level move stands out against two decades of Junes. What stood out was the rotation underneath it, the breadth panel below. Basis: regular-hours open-to-close within each calendar June, identical arithmetic every year, upper bound pinned at this month's end so the comparison set cannot silently grow.
Session by session
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_dateThe month's sharpest single-session fall came early, -2.6% on 2026-06-05, and the chart shows the shape of the month: a drift lower through mid-June, a floor near $716.58, and a partial recovery over the final sessions into the quarter turn. For the last week of that recovery in session-by-session detail, see the week recap.
Breadth: more fell than rose
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 fell on the month against 4240 that rose, negative breadth in a month where two of the four index ETFs gained. Index weighting and equal-count breadth answer different questions; June is a month where they disagreed. The liquidity filter set aside 2896 tickers under $5M of June volume, counted here rather than hidden. The day grain agrees with the ticker grain: 12 of the month's 21 sessions closed SPY lower against 9 higher.
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
)The tape's leaders
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 8MU led the entire month at $995.7 billion, SPY, in second, did 77.5% of that. NVDA put $523 billion through in fourth; its month has its own tick-by-tick deep-dive. A semiconductor theme owns the list, four of the eight names. Basis: June 1–30 regular hours; one reused-symbol June listing is excluded pending entity verification, and its first month has its own post.
The options tape: June against May
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')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')June's whole-tape options volume was 1477.9 million contracts with 34.3% trading on same-day expiries, against May's 1394.6 million and 30.3%. More volume AND a bigger same-day share: June's 0DTE share is the highest month of the half, and the January-onward evolution is in the H1 recap. A third of June's options volume expired the day it traded.
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 ASCThe cost to trade the market's biggest ticket moved the same direction: SPY's median quoted spread on the June sample session (0.409 bps, June 10) is wider than May's (0.27 bps, May 13). Basis, disclosed: single labeled sample sessions, the second Wednesday of each month, not month-wide medians; invalid quotes are counted in the panel.
Rates: the curve barely moved
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 dateThe 10-year ended June at 4.44% with the 2s10s spread at 30 basis points, a quiet month for rates against a noisier half (the H1 recap carries the six-month curve story).
The calendar: heavy quarter-end traffic, one missing filing day
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_articlesJune carried 6651 ex-dividend events, 164 splits, and 35 new listings, among them the month's headline debut, covered receipt-by-receipt in the SpaceX first-month deep-dive. One disclosure on the filing count: the SEC index shows 68388 June filings, but June 30 itself carries only 31, the index for the month's last day is materially incomplete (neighboring days carry thousands), so the June total is understated until the feed backfills, part of a 2026 month-end pattern with its own diagnostic note.
The dividend wave
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 dDividend traffic clusters at the turn of the month: June opened with 807 ex-dividend events in a single day, and the chart carries the month's full rhythm, the daily churn in the low hundreds punctuated by month-boundary spikes. What an ex-dividend date actually does to a price is covered in the ex-dividend explainer.
The shorts: both June prints on file
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')
AND settlement_date <= toDate('2026-06-30')
GROUP BY settlement
ORDER BY settlementShort interest settles twice a month and publishes on a lag. Both June prints are now on file: the 2026-06-30 settlement carries 22207 tickers, after 22178 on the June 15 file and 21987 on May 29. Daily short volume is a different dataset; its June caveat is the truncated June 29 file, carried in the week recap and the June 29 deep-dive.
The session receipt
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_juneJune ran 21 sessions, Juneteenth (June 19) shows 0 SPY bars, and the 8190 regular bars work out to exactly 21 full 390-minute sessions.
Data notes
Full data notes
- Short interest runs through the June 30 settlement, both of the month's prints are on file and carried inline above.
- The June 30 filing-index day is materially incomplete (a handful of administrative filings against thousands on neighboring days); June filing totals are understated until the feed backfills. Every 2026 month-end whose last calendar day was a weekday shows the same signature, the diagnostic note carries the receipts; the Q2 recap carries the quarter-scale caveat.
- The June 29 FINRA short-volume file is truncated market-wide, receipts in the week recap and the June 29 deep-dive.
- Volume-leader exclusion: one June listing trades under a reused symbol and is excluded from the leaderboard pending entity verification; its own post carries the verification receipts.
- Breadth compares each ticker's last June close against its last May close; tickers without both closes are excluded by construction and the liquidity filter's exclusions are counted in the panel.
Methodology
- The period is June 1–30, 2026, 21 sessions, verified from observed bars (the receipt panel above). Monthly returns are first regular-hours open to last regular-hours close within the period.
- Timestamps are stored UTC and filtered with raw UTC bounds; June 2026 is entirely EDT, so regular hours are 13:30–20:00 UTC. Dollar volume is minute close times minute volume over regular hours.
- Trailing-month comparisons are recomputed live in the same query as June's own row, never read from a stored value. The every-June history block does the same across the full minute tape (Eastern-wall-clock regular hours, the DST-safe multi-year convention, with its upper bound pinned at this month's end and a minimum-session guard shown per year); the depth verification is in the H1 recap's methodology.
- Generation runs through the gated read-only path; the public page never queries live. Warehouse state as of July 5, 2026.
This is the first edition of the standing monthly recap, July's edition will link back here. For the month's final week in session-by-session detail, see the week-of-June-29 recap; for the quarter this month closed, see the Q2 recap.