June 30, 2026 market recap: numbers wey matter
Quarter end na tech-led up day for market wey mostly red, with memory complex on top and same-day options tape for close. See all figures and SQL.
Tuesday, June 30, 2026, wey be the quarter’s last trading session, na technology-led up day for market wey mostly dey red: QQQ gain 1.63% and SPY 0.73%, but na only 4 out of 10 S&P sector funds close higher (3,349 liquid names up, 3,033 down). For the previous session, read the June 29 recap. Every number wey dey below come from stored query; expand any panel to see the SQL.
The scoreboard
Every change compares June 30's last regular-session minute bar with Monday June 29's.
| ticker | prior close | day open | day close | pct change | day high | day low | shares traded m |
|---|---|---|---|---|---|---|---|
| DIA | 521.68 | 522.35 | 522.28 | 0.12 | 523.14 | 519.59 | 2.7 |
| IWM | 298.95 | 298.56 | 300.42 | 0.49 | 300.98 | 297.44 | 19.7 |
| QQQ | 723.95 | 724.18 | 735.76 | 1.63 | 737.62 | 723.91 | 35.7 |
| SPY | 740.88 | 741.29 | 746.32 | 0.73 | 748.02 | 740.89 | 42.7 |
The exact SQL behind every number
WITH prior AS (
SELECT ticker, argMax(close, window_start) AS prior_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'QQQ', 'DIA', 'IWM')
AND window_start >= '2026-06-29 13:30:00' AND window_start < '2026-06-29 20:00:00'
GROUP BY ticker
),
sess AS (
SELECT ticker,
argMin(open, window_start) AS day_open,
argMax(close, window_start) AS day_close,
max(high) AS day_high,
min(low) AS day_low,
round(toFloat64(sum(volume)) / 1e6, 1) AS shares_traded_m
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'QQQ', 'DIA', 'IWM')
AND window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00'
GROUP BY ticker
)
SELECT
s.ticker AS ticker,
round(toFloat64(p.prior_close), 2) AS prior_close,
round(toFloat64(s.day_open), 2) AS day_open,
round(toFloat64(s.day_close), 2) AS day_close,
round((toFloat64(s.day_close) / toFloat64(p.prior_close) - 1) * 100, 2) AS pct_change,
round(toFloat64(s.day_high), 2) AS day_high,
round(toFloat64(s.day_low), 2) AS day_low,
s.shares_traded_m AS shares_traded_m
FROM sess s
JOIN prior p ON s.ticker = p.ticker
ORDER BY s.tickerSPY open for $741.29 and e finish for $746.32, close to e high of $748.02. QQQ's 1.63% against DIA's 0.12% na the shape of the day: growth run, blue chips barely move, IWM 0.49%.
Di quarter wey close today
June 30 close di last of 62 sessions for second quarter, and di day’s direction resemble di quarter for small.
| ticker | quarter first session | quarter sessions | quarter open | quarter close | quarter pct | up sessions |
|---|---|---|---|---|---|---|
| QQQ | 2026-04-01 | 62 | 581.48 | 735.76 | 26.53 | 38 |
| IWM | 2026-04-01 | 62 | 249.92 | 300.42 | 20.21 | 35 |
| SPY | 2026-04-01 | 62 | 653.9 | 746.32 | 14.13 | 36 |
| DIA | 2026-04-01 | 62 | 466 | 522.28 | 12.08 | 34 |
The exact SQL behind every number
WITH q2 AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMin(toFloat64(open), window_start) AS d_open,
argMax(toFloat64(close), window_start) AS d_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'QQQ', 'DIA', 'IWM')
AND window_start >= toDateTime('2026-04-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 ticker, d
)
SELECT
ticker,
toString(min(d)) AS quarter_first_session,
count() AS quarter_sessions,
round(argMin(d_open, d), 2) AS quarter_open,
round(argMax(d_close, d), 2) AS quarter_close,
round((argMax(d_close, d) / argMin(d_open, d) - 1) * 100, 2) AS quarter_pct,
countIf(d_close > d_open) AS up_sessions
FROM q2
GROUP BY ticker
ORDER BY quarter_pct DESC, ticker ASCFrom April 1 open reach June 30 close: QQQ +26.53%, IWM 20.21%, SPY 14.13%, DIA 12.08%. QQQ lead for di quarter and for June 30 itself, but di middle position change: SPY pass IWM small for di day, while IWM lead SPY across di quarter. QQQ close higher for 38 out of 62 sessions (di Q2 recap dey show am panel by panel).
Day unusual be?
| day move pct | abs move rank | sessions compared | first session |
|---|---|---|---|
| 0.68 | 7 | 21 | 2026-06-01 |
The exact SQL behind every number
SELECT round(anyIf(oc_pct, d = toDate('2026-06-30')), 2) AS day_move_pct,
arrayCount(x -> x > abs(anyIf(oc_pct, d = toDate('2026-06-30'))), groupArrayIf(abs(oc_pct), d != toDate('2026-06-30'))) + 1 AS abs_move_rank,
count() AS sessions_compared,
toString(min(d)) AS first_session
FROM (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
(argMax(toFloat64(close), window_start) / argMin(toFloat64(open), window_start) - 1) * 100 AS oc_pct
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
)From open to close inside the session, this one na different way to look am from the close-over-close scoreboard. SPY move 0.68%, and e rank 7 out of 21 trailing sessions by absolute size. The index calm, but the trading underneath no be.
Breadth: small positive edge
| advancers | decliners | unchanged | liquid tickers | tickers traded both sessions | dropped by liquidity filter | advancer pct | sector funds counted | sector funds up |
|---|---|---|---|---|---|---|---|---|
| 3349 | 3033 | 88 | 6470 | 11525 | 5055 | 51.8 | 10 | 4 |
The exact SQL behind every number
WITH per_ticker AS (
SELECT
ticker,
toFloat64(argMaxIf(close, window_start, window_start < '2026-06-30 00:00:00')) AS prior_close,
toFloat64(argMaxIf(close, window_start, window_start >= '2026-06-30 00:00:00')) AS day_close,
sumIf(toFloat64(close) * toFloat64(volume), window_start >= '2026-06-30 00:00:00') AS day_dollar_volume
FROM global_markets.delayed_stocks_minute_aggs
WHERE (window_start >= '2026-06-29 13:30:00' AND window_start < '2026-06-29 20:00:00')
OR (window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00')
GROUP BY ticker
)
SELECT
countIf(day_close > prior_close AND day_dollar_volume >= 1000000) AS advancers,
countIf(day_close < prior_close AND day_dollar_volume >= 1000000) AS decliners,
countIf(day_close = prior_close AND day_dollar_volume >= 1000000) AS unchanged,
countIf(day_dollar_volume >= 1000000) AS liquid_tickers,
count() AS tickers_traded_both_sessions,
count() - countIf(day_dollar_volume >= 1000000) AS dropped_by_liquidity_filter,
round(100.0 * countIf(day_close > prior_close AND day_dollar_volume >= 1000000)
/ countIf(day_dollar_volume >= 1000000), 1) AS advancer_pct,
countIf(ticker IN ('XLB', 'XLE', 'XLF', 'XLI', 'XLK', 'XLP', 'XLRE', 'XLU', 'XLV', 'XLY')) AS sector_funds_counted,
countIf(ticker IN ('XLB', 'XLE', 'XLF', 'XLI', 'XLK', 'XLP', 'XLRE', 'XLU', 'XLV', 'XLY')
AND day_close > prior_close) AS sector_funds_up
FROM per_ticker
WHERE prior_close > 0 AND day_close > 03,349 advancers, 3,033 decliners, 88 unchanged: 51.8% of the liquid tape rise, and na coin flip under a 1.63% growth-index print. The liquidity filter drop 5,055 of 11,525 dual-session tickers (under $1 million traded). We count dem here; we no hide dem.
Sector wan dey go: where money really land
To count every name as one vote no dey show where money sit. The ten funds below each hold one part of the S&P 500. The gap between the best and worst one show how uneven the session be.
| ticker | prior close | day close | pct chg | is up | pts behind leader | day dollar bn |
|---|---|---|---|---|---|---|
| XLK | 185.44 | 190.42 | 2.69 | 1 | 0 | 1.62 |
| XLI | 182.77 | 185.22 | 1.34 | 1 | 1.35 | 1.08 |
| XLB | 50.66 | 50.84 | 0.36 | 1 | 2.33 | 0.41 |
| XLY | 117.1 | 117.27 | 0.15 | 1 | 2.54 | 0.58 |
| XLF | 53.7 | 53.61 | -0.17 | 0 | 2.85 | 1.39 |
| XLE | 53.57 | 53.14 | -0.8 | 0 | 3.49 | 1.36 |
| XLV | 160.74 | 158.67 | -1.29 | 0 | 3.97 | 1.78 |
| XLU | 46.02 | 45.34 | -1.48 | 0 | 4.16 | 0.77 |
| XLP | 84.37 | 83.08 | -1.53 | 0 | 4.21 | 0.99 |
| XLRE | 44.92 | 44.02 | -2 | 0 | 4.69 | 0.38 |
The exact SQL behind every number
WITH per_name AS (
SELECT
ticker,
toFloat64(argMaxIf(close, window_start, window_start < '2026-06-30 00:00:00')) AS prior_close,
toFloat64(argMaxIf(close, window_start, window_start >= '2026-06-30 00:00:00')) AS day_close,
round(sumIf(toFloat64(close) * toFloat64(volume), window_start >= '2026-06-30 00:00:00') / 1e9, 2) AS day_dollar_bn
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('XLB', 'XLE', 'XLF', 'XLI', 'XLK', 'XLP', 'XLRE', 'XLU', 'XLV', 'XLY')
AND ((window_start >= '2026-06-29 13:30:00' AND window_start < '2026-06-29 20:00:00')
OR (window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00'))
GROUP BY ticker
)
SELECT
ticker,
round(prior_close, 2) AS prior_close,
round(day_close, 2) AS day_close,
round((day_close / prior_close - 1) * 100, 2) AS pct_chg,
if(day_close > prior_close, 1, 0) AS is_up,
round(max((day_close / prior_close - 1) * 100) OVER () - (day_close / prior_close - 1) * 100, 2) AS pts_behind_leader,
day_dollar_bn
FROM per_name
ORDER BY pct_chg DESC, ticker ASCTechnology (XLK) gain 2.69% and stand alone. Industrials 1.34%, materials 0.36% and discretionary 0.15% na the only other sectors wey close green. The board turn red from financials (-0.17%) reach utilities (-1.48%), staples (-1.53%) and real estate last at -2%. Best minus worst: 4.69 percentage points, with 4 of 10 funds green. Index rise less than one percent, but the spread underneath reach four points: na one sector carry the day.
Market-wide, the biggest movers for the day
Breadth dey count how many names rise. This one show the names wey move pass, with top and bottom five by percentage change among names wey trade $10 million or more.
| board | ticker | prior close | day close | pct chg | abs pct chg | dollar volume m | split record dey file |
|---|---|---|---|---|---|---|---|
| top gainers | JEM | 1.11 | 3.96 | 256.76 | 256.76 | 141 | 0 |
| top gainers | CUPR | 4.45 | 6.56 | 47.42 | 47.42 | 138 | 0 |
| top gainers | ABVX | 96.17 | 133.25 | 38.56 | 38.56 | 942 | 0 |
| top gainers | AVXX | 5.03 | 6.84 | 35.98 | 35.98 | 23 | 0 |
| top gainers | CRCD | 5.16 | 6.99 | 35.47 | 35.47 | 18 | 0 |
| top decliners | CRCA | 19.71 | 12.78 | -35.16 | 35.16 | 56 | 0 |
| top decliners | CRCG | 13.27 | 8.6 | -35.19 | 35.19 | 64 | 0 |
| top decliners | NVCT | 28.52 | 18.36 | -35.62 | 35.62 | 51 | 0 |
| top decliners | UNCY | 7.7 | 4.69 | -39.09 | 39.09 | 55 | 0 |
| top decliners | SOC | 6.96 | 3.07 | -55.89 | 55.89 | 306 | 0 |
The exact SQL behind every number
WITH per_ticker AS (
SELECT
ticker,
toFloat64(argMaxIf(close, window_start, window_start < '2026-06-30 00:00:00')) AS prior_close,
toFloat64(argMaxIf(close, window_start, window_start >= '2026-06-30 00:00:00')) AS day_close,
sumIf(toFloat64(close) * toFloat64(volume), window_start >= '2026-06-30 00:00:00') AS day_dollar_volume
FROM global_markets.delayed_stocks_minute_aggs
WHERE (window_start >= '2026-06-29 13:30:00' AND window_start < '2026-06-29 20:00:00')
OR (window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00')
GROUP BY ticker
HAVING prior_close > 1 AND day_close > 0 AND day_dollar_volume >= 10000000 AND ticker NOT IN ('SPCX')
)
SELECT
board,
ticker,
prior_close,
day_close,
pct_chg,
round(abs(pct_chg), 2) AS abs_pct_chg,
dollar_volume_m,
if(ticker IN (SELECT ticker FROM global_markets.stocks_splits
WHERE execution_date >= '2026-06-29' AND execution_date <= '2026-06-30'), 1, 0) AS split_record_on_file
FROM (
SELECT 'top gainers' AS board, ticker, round(prior_close, 2) AS prior_close, round(day_close, 2) AS day_close,
round((day_close / prior_close - 1) * 100, 2) AS pct_chg, round(day_dollar_volume / 1e6, 0) AS dollar_volume_m
FROM per_ticker
ORDER BY (day_close / prior_close) DESC, ticker ASC
LIMIT 5
UNION ALL
SELECT 'top decliners' AS board, ticker, round(prior_close, 2) AS prior_close, round(day_close, 2) AS day_close,
round((day_close / prior_close - 1) * 100, 2) AS pct_chg, round(day_dollar_volume / 1e6, 0) AS dollar_volume_m
FROM per_ticker
ORDER BY (day_close / prior_close) ASC, ticker ASC
LIMIT 5
)
ORDER BY if(board = 'top gainers', 0, 1) ASC, pct_chg DESC, ticker ASCNone of the two boards look like the index. JEM lead with +256.76% on $141 million traded. SOC lose 55.89% on $306 million. ABVX rise 38.56% on $942 million, the heaviest turnover for either board. NVCT fall 35.62%, while UNCY fall 39.09%. The split-record column keep the board honest. A 1-for-10 reverse split fit print as +900% “gain” for unadjusted tape. Every name here carry a 0: real prints.
Three rows na one trade showing two times. CRCA (-35.16%) and CRCG (-35.19%) fall, while CRCD rise 35.47%. Each one dey close to twice the -17.53% move of the crypto-adjacent name below: leveraged single-stock wrappers.
The main thing for today: semiconductors enter the quarter turn
Six names, one theme, but outcomes dey very different. Data only show say dem move together and by how much; e no explain why.
| ticker | prior close | day close | pct chg | day high | day high ET | day low | day low ET | range % | day dollar bn |
|---|---|---|---|---|---|---|---|---|---|
| AMD | 539.28 | 580.82 | 7.7 | 584.73 | 15:21 | 545.57 | 09:30 | 7.18 | 15.92 |
| INTC | 131.69 | 139.5 | 5.93 | 142.35 | 13:48 | 131.52 | 09:30 | 8.23 | 12.9 |
| MU | 1145 | 1151.01 | 0.52 | 1168.68 | 15:15 | 1124.66 | 09:44 | 3.91 | 37.41 |
| SNDK | 2051.29 | 2272.59 | 10.79 | 2280.8 | 15:53 | 2070 | 09:30 | 10.18 | 21.19 |
| TSM | 455.12 | 477.24 | 4.86 | 479 | 15:55 | 453 | 09:30 | 5.74 | 5.87 |
| WDC | 651.7 | 638.57 | -2.01 | 663.98 | 10:35 | 630.3 | 09:30 | 5.34 | 4.5 |
The exact SQL behind every number
WITH per_name AS (
SELECT
ticker,
toFloat64(argMaxIf(close, window_start, window_start < '2026-06-30 00:00:00')) AS prior_close,
toFloat64(argMaxIf(close, window_start, window_start >= '2026-06-30 00:00:00')) AS day_close,
maxIf(toFloat64(high), window_start >= '2026-06-30 00:00:00') AS day_high,
minIf(toFloat64(low), window_start >= '2026-06-30 00:00:00') AS day_low,
argMinIf(window_start, toFloat64(low), window_start >= '2026-06-30 00:00:00') AS low_bar,
argMaxIf(window_start, toFloat64(high), window_start >= '2026-06-30 00:00:00') AS high_bar,
round(sumIf(toFloat64(close) * toFloat64(volume), window_start >= '2026-06-30 00:00:00') / 1e9, 2) AS day_dollar_bn
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('AMD', 'INTC', 'MU', 'SNDK', 'TSM', 'WDC')
AND ((window_start >= '2026-06-29 13:30:00' AND window_start < '2026-06-29 20:00:00')
OR (window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00'))
GROUP BY ticker
)
SELECT
ticker,
round(prior_close, 2) AS prior_close,
round(day_close, 2) AS day_close,
round((day_close / prior_close - 1) * 100, 2) AS pct_chg,
round(day_high, 2) AS day_high,
formatDateTime(toTimeZone(high_bar, 'America/New_York'), '%H:%i') AS day_high_et,
round(day_low, 2) AS day_low,
formatDateTime(toTimeZone(low_bar, 'America/New_York'), '%H:%i') AS day_low_et,
round((day_high / day_low - 1) * 100, 2) AS range_pct,
day_dollar_bn
FROM per_name
ORDER BY tickerSanDisk jump 10.79%, AMD 7.7%, Intel 5.93%, TSMC 4.86%. MU, wey get the biggest ticket for the tape with $37.41 billion turnover, close only 0.52% higher. Western Digital (-2.01%) no join the move. Na this complex drive technology’s 2.69% sector print (MU for June, tick by tick).
The opposite move show for crypto-adjacent financials, even as the tape dey green:
| ticker | prior close | day close | pct chg | day high | day high ET | day low | day low ET | range % | day dollar bn |
|---|---|---|---|---|---|---|---|---|---|
| COIN | 151.66 | 146.19 | -3.61 | 148.86 | 09:30 | 142.3 | 11:06 | 4.61 | 1.07 |
| CRCL | 75.97 | 62.65 | -17.53 | 73.2 | 09:32 | 62.52 | 15:59 | 17.08 | 2.24 |
| HOOD | 101.83 | 100.27 | -1.53 | 103.06 | 11:29 | 99.66 | 14:12 | 3.41 | 1.53 |
| MSTR | 92.68 | 86.93 | -6.2 | 88.26 | 10:30 | 83.42 | 11:06 | 5.8 | 2.52 |
The exact SQL behind every number
WITH per_name AS (
SELECT
ticker,
toFloat64(argMaxIf(close, window_start, window_start < '2026-06-30 00:00:00')) AS prior_close,
toFloat64(argMaxIf(close, window_start, window_start >= '2026-06-30 00:00:00')) AS day_close,
maxIf(toFloat64(high), window_start >= '2026-06-30 00:00:00') AS day_high,
minIf(toFloat64(low), window_start >= '2026-06-30 00:00:00') AS day_low,
argMinIf(window_start, toFloat64(low), window_start >= '2026-06-30 00:00:00') AS low_bar,
argMaxIf(window_start, toFloat64(high), window_start >= '2026-06-30 00:00:00') AS high_bar,
round(sumIf(toFloat64(close) * toFloat64(volume), window_start >= '2026-06-30 00:00:00') / 1e9, 2) AS day_dollar_bn
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('COIN', 'CRCL', 'HOOD', 'MSTR')
AND ((window_start >= '2026-06-29 13:30:00' AND window_start < '2026-06-29 20:00:00')
OR (window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00'))
GROUP BY ticker
)
SELECT
ticker,
round(prior_close, 2) AS prior_close,
round(day_close, 2) AS day_close,
round((day_close / prior_close - 1) * 100, 2) AS pct_chg,
round(day_high, 2) AS day_high,
formatDateTime(toTimeZone(high_bar, 'America/New_York'), '%H:%i') AS day_high_et,
round(day_low, 2) AS day_low,
formatDateTime(toTimeZone(low_bar, 'America/New_York'), '%H:%i') AS day_low_et,
round((day_high / day_low - 1) * 100, 2) AS range_pct,
day_dollar_bn
FROM per_name
ORDER BY tickerCRCL print -17.53%. E reach e low of $62.52 at 15:59 ET, for the final minute of the session. MSTR -6.2%, COIN -3.61% and HOOD -1.53% move alongside am. We observe say dem move together; we no dey claim the cause.
Wetin the news feed carry
A recap wey no wan talk the causes plainly still owe reader wetin dem actually publish that day.
| ticker | articles today | latest ET | publisher name | latest headline |
|---|---|---|---|---|
| NVDA | 21 | 16:28 | Investing.com | These Stocks Could Benefit as the Robotaxi Race Heats Up |
| MU | 7 | 15:38 | Investing.com | S&P 500 Earnings Depend on AI Infrastructure Doing the Heavy Lifting |
| JEM | 1 | 04:00 | GlobeNewswire Inc. | 707 Cayman Holdings Appoints New Executive Director |
| SNDK | 1 | 15:12 | The Motley Fool | Why Sandisk Stock Is Skyrocketing Today |
| ABVX | 0 | none | no article in our feed this session | no article in our feed this session |
| CRCL | 0 | none | no article in our feed this session | no article in our feed this session |
| SOC | 0 | none | no article in our feed this session | no article in our feed this session |
The exact SQL behind every number
SELECT
names.n AS ticker,
countIf(has(tickers, names.n)) AS articles_today,
if(countIf(has(tickers, names.n)) = 0, 'none',
formatDateTime(toTimeZone(argMaxIf(published_utc, (published_utc, id), has(tickers, names.n)), 'America/New_York'), '%H:%i')) AS latest_et,
if(countIf(has(tickers, names.n)) = 0, 'no article in our feed this session',
JSONExtractString(argMaxIf(publisher, (published_utc, id), has(tickers, names.n)), 'name')) AS publisher_name,
if(countIf(has(tickers, names.n)) = 0, 'no article in our feed this session',
argMaxIf(title, (published_utc, id), has(tickers, names.n))) AS latest_headline
FROM global_markets.stocks_news
CROSS JOIN (SELECT arrayJoin(['NVDA', 'MU', 'SNDK', 'CRCL', 'SOC', 'ABVX', 'JEM']) AS n) AS names
WHERE published_utc >= '2026-06-30 04:00:00' AND published_utc < '2026-07-01 04:00:00'
GROUP BY names.n
ORDER BY articles_today DESC, ticker ASCThe name wey dem cover pass na NVDA, with 21 articles. E no dey among the day movers at all. The last piece for the session (16:28 ET, Investing.com) get title "These Stocks Could Benefit as the Robotaxi Race Heats Up". MU get 7 articles. SanDisk get only one article (The Motley Fool), and na the only headline for the whole day wey name an actual move: "Why Sandisk Stock Is Skyrocketing Today".
Na here the finding dey: the day biggest decliner, the strongest gainer and the crypto-adjacent name wey fall pass all get 0, 0 and 0 articles, zero each, inside feed wey get 211 pieces. Coverage no be proxy for price action.
Wey money trade
| ticker | leaderboard | dollar volume bn | dollar value m | shares m | % of board leader |
|---|---|---|---|---|---|
| MU | by dollars traded | 37.41 | None | 32.5 | 100 |
| SPY | by dollars traded | 31.84 | None | 42.7 | 85.1 |
| QQQ | by dollars traded | 26.2 | None | 35.7 | 70 |
| SNDK | by dollars traded | 21.19 | None | 9.6 | 56.6 |
| NVDA | by dollars traded | 20.69 | None | 104.3 | 55.3 |
| AMD | by dollars traded | 15.92 | None | 27.9 | 42.6 |
| SOXS | by shares traded | 1.72 | None | 515.5 | 100 |
| YHC | by shares traded | 0.04 | 42 | 340 | 66 |
| BIYA | by shares traded | 0.13 | 133 | 273 | 53 |
| TZA | by shares traded | 0.87 | 866 | 226.6 | 44 |
The exact SQL behind every number
SELECT ticker, leaderboard, dollar_volume_bn, if(dollar_volume_bn < 1, dollar_volume_m, NULL) AS dollar_value_m, shares_m,
round(100 * if(leaderboard = 'by dollars traded', dollar_volume_bn, shares_m)
/ max(if(leaderboard = 'by dollars traded', dollar_volume_bn, shares_m)) OVER (PARTITION BY leaderboard), 1) AS pct_of_board_leader
FROM (
SELECT
'by dollars traded' AS leaderboard,
ticker,
round(sum(toFloat64(close) * toFloat64(volume)) / 1e9, 2) AS dollar_volume_bn,
round(sum(toFloat64(close) * toFloat64(volume)) / 1e6, 0) AS dollar_volume_m,
round(sum(toFloat64(volume)) / 1e6, 1) AS shares_m
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00'
AND ticker NOT IN ('SPCX')
GROUP BY ticker
ORDER BY dollar_volume_bn DESC
LIMIT 6
UNION ALL
SELECT
'by shares traded' AS leaderboard,
ticker,
round(sum(toFloat64(close) * toFloat64(volume)) / 1e9, 2) AS dollar_volume_bn,
round(sum(toFloat64(close) * toFloat64(volume)) / 1e6, 0) AS dollar_volume_m,
round(sum(toFloat64(volume)) / 1e6, 1) AS shares_m
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00'
AND ticker NOT IN ('SPCX')
GROUP BY ticker
ORDER BY shares_m DESC
LIMIT 4
)
ORDER BY leaderboard ASC, if(leaderboard = 'by dollars traded', dollar_volume_bn, shares_m) DESCBy dollar value, MU pass everything, including index funds: $37.41 billion against SPY wey get $31.84 billion. Na the second session straight wey e trade pass the flagship index fund (Monday recap get the first one). But share count tell another story: SOXS, one 3x-leveraged inverse semiconductor ETF (515.5 million shares), plus two sub-dollar names wey their value be rounding error compared with MU for the day. Volume fit get two interpretations.
We leave one name out of both boards on purpose. Na June listing be that, and another unrelated company don use the ticker before. So vendor feeds dey tag two different entities with the same three letters (receipts dey here).
| ET time | shares bn | % of biggest bucket |
|---|---|---|
| 09:30 | 2.05 | 44.3 |
| 10:00 | 1.55 | 33.5 |
| 10:30 | 1.36 | 29.4 |
| 11:00 | 1.19 | 25.7 |
| 11:30 | 0.97 | 21 |
| 12:00 | 0.9 | 19.5 |
| 12:30 | 0.88 | 19 |
| 13:00 | 0.82 | 17.7 |
| 13:30 | 0.78 | 16.9 |
| 14:00 | 0.8 | 17.3 |
| 14:30 | 0.92 | 19.9 |
| 15:00 | 1.08 | 23.3 |
| 15:30 | 4.63 | 100 |
The exact SQL behind every number
SELECT
et_time,
round(sum(shares) / 1e9, 2) AS shares_bn,
round(100 * sum(shares) / max(sum(shares)) OVER (), 1) AS pct_of_biggest_bucket
FROM
(
SELECT
formatDateTime(toStartOfInterval(toTimeZone(window_start, 'America/New_York'), INTERVAL 30 MINUTE), '%H:%i') AS et_time,
toFloat64(volume) AS shares
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00'
UNION ALL
SELECT
'15:30' AS et_time,
toFloat64(size) AS shares
FROM global_markets.stocks_trades
WHERE sip_timestamp >= '2026-06-30 20:00:00' AND sip_timestamp < '2026-06-30 20:15:00'
AND has(conditions, 8)
)
GROUP BY et_time
ORDER BY et_time2.05 billion shares trade for the first half hour. E reach 0.78 billion trough at 13:30. Then the biggest bucket for the day, 4.63 billion, enter as quarter-end close near. Na that time closing auction and rebalancing flows dey print. The June 29 deep dive dey under the bars.
The options tape
| option prints m | contracts m | call % of volume | same-day expiry % | Thu Jul 2 expiry contracts m | Fri Jul 3 expiry prints | SPY contracts m | QQQ contracts m | SPY put-call ratio | SPY 0DTE OTM calls m | SPY 0DTE ITM calls m | SPY 0DTE OTM puts m | SPY 0DTE ITM puts m | top contract underlying | top contract strike | top contract type | top contract expiry | top contract volume | top contract avg price | top strike minus spy close |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 10.06 | 61.95 | 57.3 | 28 | 10.52 | 0 | 12.04 | 7.1 | 1.09 | 2.28 | 1.77 | 3.33 | 0.63 | SPY | 747 | C | 2026-06-30 | 821361 | 0.641 | 0.68 |
The exact SQL behind every number
WITH
(
SELECT (any(underlying_symbol), any(toFloat64(strike_price)), any(option_type),
any(toDateOrNull(concat('20', substring(ticker, length(ticker) - 14, 6)))),
sum(size), count(), round(avg(toFloat64(price)), 3))
FROM global_markets.options_trades
WHERE sip_timestamp >= '2026-06-30 00:00:00' AND sip_timestamp < '2026-07-01 00:00:00'
GROUP BY ticker
ORDER BY sum(size) DESC
LIMIT 1
) AS top_contract,
(
SELECT round(toFloat64(argMax(close, window_start)), 2)
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY' AND window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00'
) AS spy_close
SELECT
round(count() / 1e6, 2) AS option_prints_m,
round(toFloat64(sum(size)) / 1e6, 2) AS contracts_m,
round(100.0 * sumIf(size, option_type = 'C') / sum(size), 1) AS call_pct_of_volume,
round(100.0 * sumIf(size, substring(ticker, length(ticker) - 14, 6) = '260630') / sum(size), 1) AS same_day_expiry_pct,
round(toFloat64(sumIf(size, substring(ticker, length(ticker) - 14, 6) = '260702')) / 1e6, 2) AS thu_jul2_expiry_contracts_m,
countIf(substring(ticker, length(ticker) - 14, 6) = '260703') AS fri_jul3_expiry_prints,
round(toFloat64(sumIf(size, underlying_symbol = 'SPY')) / 1e6, 2) AS spy_contracts_m,
round(toFloat64(sumIf(size, underlying_symbol = 'QQQ')) / 1e6, 2) AS qqq_contracts_m,
round(toFloat64(sumIf(size, underlying_symbol = 'SPY' AND option_type = 'P'))
/ toFloat64(sumIf(size, underlying_symbol = 'SPY' AND option_type = 'C')), 2) AS spy_put_call_ratio,
round(toFloat64(sumIf(size, underlying_symbol = 'SPY' AND option_type = 'C'
AND substring(ticker, length(ticker) - 14, 6) = '260630' AND toFloat64(strike_price) > spy_close)) / 1e6, 2) AS spy_0dte_otm_calls_m,
round(toFloat64(sumIf(size, underlying_symbol = 'SPY' AND option_type = 'C'
AND substring(ticker, length(ticker) - 14, 6) = '260630' AND toFloat64(strike_price) <= spy_close)) / 1e6, 2) AS spy_0dte_itm_calls_m,
round(toFloat64(sumIf(size, underlying_symbol = 'SPY' AND option_type = 'P'
AND substring(ticker, length(ticker) - 14, 6) = '260630' AND toFloat64(strike_price) < spy_close)) / 1e6, 2) AS spy_0dte_otm_puts_m,
round(toFloat64(sumIf(size, underlying_symbol = 'SPY' AND option_type = 'P'
AND substring(ticker, length(ticker) - 14, 6) = '260630' AND toFloat64(strike_price) >= spy_close)) / 1e6, 2) AS spy_0dte_itm_puts_m,
top_contract.1 AS top_contract_underlying,
top_contract.2 AS top_contract_strike,
top_contract.3 AS top_contract_type,
top_contract.4 AS top_contract_expiry,
top_contract.5 AS top_contract_volume,
round(top_contract.7, 3) AS top_contract_avg_price,
round(top_contract.2 - spy_close, 2) AS top_strike_minus_spy_close
FROM global_markets.options_trades
WHERE sip_timestamp >= '2026-06-30 00:00:00' AND sip_timestamp < '2026-07-01 00:00:00'Options traders exchange 61.95 million contracts across 10.06 million prints. Calls make up 57.3% of all volume, while 28% expire that Tuesday. SPY move the opposite way: 12.04 million contracts with a put/call ratio of 1.09. Puts pass calls, even as the fund rise that day.
When we compare SPY same-day expiries with its $746.32 closing price, the skew clear. There are 3.33 million out-of-the-money puts, with strikes below the close, and 2.28 million out-of-the-money calls. There are also 1.77 million in-the-money calls and 0.63 million in-the-money puts. Puts with downside strikes wey expire worthless be the busiest group for SPY 0DTE day. No contract with Friday, July 3 expiry code print at all (0 prints), because market close that Friday. The Thursday weekly get 10.52 million contracts.
| contract | expires | expires label | na same day? | contracts | avg premium | pct of busiest |
|---|---|---|---|---|---|---|
| SPY $747 call | 2026-06-30 | June 30, 2026 | 1 | 821361 | 0.641 | 100 |
| SPY $748 call | 2026-06-30 | June 30, 2026 | 1 | 558347 | 0.346 | 68 |
| SPY $746 put | 2026-06-30 | June 30, 2026 | 1 | 551942 | 0.79 | 67.2 |
| SPY $746 call | 2026-06-30 | June 30, 2026 | 1 | 543804 | 0.936 | 66.2 |
| KWEB $29 call | 2026-12-18 | December 18, 2026 | 0 | 534459 | 1.171 | 65.1 |
| SPY $745 call | 2026-06-30 | June 30, 2026 | 1 | 497450 | 1.227 | 60.6 |
The exact SQL behind every number
SELECT
concat(underlying, ' $', toString(strike), ' ', if(typ = 'C', 'call', 'put')) AS contract,
toString(expiry) AS expires,
formatDateTimeInJodaSyntax(expiry, 'MMMM d, yyyy') AS expires_label,
if(expiry = toDate('2026-06-30'), 1, 0) AS is_same_day,
contracts,
round(avg_px, 3) AS avg_premium,
round(100 * contracts / max(contracts) OVER (), 1) AS pct_of_busiest
FROM (
SELECT any(underlying_symbol) AS underlying,
any(toFloat64(strike_price)) AS strike,
any(option_type) AS typ,
any(toDateOrNull(concat('20', substring(ticker, length(ticker) - 14, 6)))) AS expiry,
sum(size) AS contracts,
avg(toFloat64(price)) AS avg_px,
any(ticker) AS occ
FROM global_markets.options_trades
WHERE sip_timestamp >= '2026-06-30 00:00:00' AND sip_timestamp < '2026-07-01 00:00:00'
GROUP BY ticker
ORDER BY contracts DESC, occ ASC
LIMIT 6
)
ORDER BY contracts DESC, contract ASCThe busiest contract for the whole market na same-day SPY $747 call. E trade 821,361 contracts for average option premium of $0.641. E finish $0.68 above SPY last regular bar, but e expire worthless. The activity around am show the main lesson: five of the six busiest contracts for the whole tape be same-day SPY strikes wey dey one dollar apart around the close (SPY $748 call next). Each one trade for just cents. The exception, with 65.1% of the leader volume, na KWEB $29 call wey expire December 18, 2026. E no be same-day contract. Na one six-month position among five afternoon lottery tickets.
Rates: long end rise as half-year dey close
| curve point | Jun30 yield pct | one day change bp |
|---|---|---|
| 1 month | 3.7 | -1 |
| 3 month | 3.87 | 0 |
| 1 year | 3.98 | 1 |
| 2 year | 4.14 | 4 |
| 5 year | 4.19 | 5 |
| 10 year | 4.44 | 6 |
| 30 year | 4.91 | 5 |
| 2s10s spread | 0.3 | 2 |
The exact SQL behind every number
SELECT
t.1 AS curve_point,
round(t.2, 2) AS jun30_yield_pct,
round((t.2 - t.3) * 100) AS one_day_change_bp
FROM (
SELECT arrayJoin([
('1 month', toFloat64(d.yield_1_month), toFloat64(p.yield_1_month)),
('3 month', toFloat64(d.yield_3_month), toFloat64(p.yield_3_month)),
('1 year', toFloat64(d.yield_1_year), toFloat64(p.yield_1_year)),
('2 year', toFloat64(d.yield_2_year), toFloat64(p.yield_2_year)),
('5 year', toFloat64(d.yield_5_year), toFloat64(p.yield_5_year)),
('10 year', toFloat64(d.yield_10_year), toFloat64(p.yield_10_year)),
('30 year', toFloat64(d.yield_30_year), toFloat64(p.yield_30_year)),
('2s10s spread', toFloat64(d.yield_10_year - d.yield_2_year), toFloat64(p.yield_10_year - p.yield_2_year))
]) AS t
FROM (SELECT * FROM global_markets.treasury_yields WHERE date = '2026-06-30') AS d,
(SELECT * FROM global_markets.treasury_yields WHERE date = '2026-06-29') AS p
)Long end rise for the final day of the half-year: the 10-year rise 6 bp reach 4.44%, the 2-year rise 4 bp reach 4.14%, and 2s10s spread steepen 2 bp reach 0.3 points. Long yields rise during session wey the weakest sector, real estate (-2%), and the third-weakest, utilities (-1.48%), both dey classically sensitive to rates. Na co-occurrence wey worth noting, but no be mechanism wey this data fit prove (H1 recap carry the half-year curve).
Calendar wey dey behind the day
| ex-dividend records | splits executed | IPOs listed | SEC filings | insider Form 4 filings | 8-K filings | IPO names | news articles | news publishers | most covered ticker | most covered articles | filings for prior session |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 704 | 7 | 2 | 31 | 0 | 0 | AACU — Ares Acquisition Corp III; OSPRU — Osprey Acquisition Corp. III | 211 | 3 | NVDA | 21 | 4439 |
The exact SQL behind every number
WITH
(
SELECT (count(), uniqExact(publisher))
FROM global_markets.stocks_news
WHERE toDate(toTimeZone(published_utc, 'America/New_York')) = '2026-06-30'
) AS news,
(
SELECT (argMax(t, n), max(n))
FROM (
SELECT t, count() AS n
FROM (
SELECT arrayJoin(tickers) AS t
FROM global_markets.stocks_news
WHERE toDate(toTimeZone(published_utc, 'America/New_York')) = '2026-06-30'
)
WHERE t != 'SPCX'
GROUP BY t
)
) AS top_news
SELECT
(SELECT count() FROM global_markets.stocks_dividends WHERE ex_dividend_date = '2026-06-30') AS ex_dividend_records,
(SELECT count() FROM global_markets.stocks_splits WHERE execution_date = '2026-06-30') AS splits_executed,
(SELECT count() FROM global_markets.stocks_ipos WHERE listing_date = '2026-06-30') AS ipos_listed,
(SELECT uniqExact(accession_number) FROM global_markets.stocks_sec_edgar_index WHERE filing_date = '2026-06-30') AS sec_filings,
(SELECT uniqExactIf(accession_number, form_type = '4') FROM global_markets.stocks_sec_edgar_index WHERE filing_date = '2026-06-30') AS insider_form4_filings,
(SELECT uniqExactIf(accession_number, form_type = '8-K') FROM global_markets.stocks_sec_edgar_index WHERE filing_date = '2026-06-30') AS filings_8k,
(SELECT arrayStringConcat(groupArray(concat(ticker, ' — ', issuer_name)), '; ') FROM (
SELECT ticker, issuer_name FROM global_markets.stocks_ipos WHERE listing_date = '2026-06-30' ORDER BY ticker
)) AS ipo_names,
news.1 AS news_articles,
news.2 AS news_publishers,
top_news.1 AS most_covered_ticker,
top_news.2 AS most_covered_articles,
(SELECT uniqExact(accession_number) FROM global_markets.stocks_sec_edgar_index WHERE filing_date = toDate('2026-06-29')) AS filings_prior_session704 dividend records went ex-dividend for the quarter’s last day. Na quarter-end wave be this, as most US companies dey pay quarterly. E get 7 splits and 2 new listings (AACU — Ares Acquisition Corp III; OSPRU — Osprey Acquisition Corp. III). The filing column na the main data-quality headline. The SEC index hold 31 filings for June 30: 0 insider Form 4s, 0 8-Ks, against 4439 the session before. The feed show month-end pattern, as the month-end gap note explain. Any count wey include this day still low until the backfill complete.
Session wey dem verify
| first SPY bar ET | last SPY bar ET | SPY minute bars | regular session bars | day sessions |
|---|---|---|---|---|
| 04:00 | 19:59 | 860 | 390 | 1 |
The exact SQL behind every number
SELECT
formatDateTime(min(toTimeZone(window_start, 'America/New_York')), '%H:%i') AS first_spy_bar_et,
formatDateTime(max(toTimeZone(window_start, 'America/New_York')), '%H:%i') AS last_spy_bar_et,
count() AS spy_minute_bars,
countIf(window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00') AS regular_session_bars,
uniqExactIf(toDate(toTimeZone(window_start, 'America/New_York')), window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00') AS day_sessions
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY' AND window_start >= '2026-06-30 00:00:00' AND window_start < '2026-07-01 00:00:00'SPY bars dey run from 04:00 to 19:59 New York time, with exactly 390 bars for regular trading window. Na complete session, and tape don verify am. Exchange-calendar dataset only get closures wey dey come.
Wetin the session add up to
One 0.73% SPY print with 51.8% names higher, 4 of 10 sector funds green, and 4.69 points between the best and worst no be broad rally. Na one sector rally wey dey wear index clothes, plus e happen during the heaviest half-hour of a quarter-end auction. Index change na average, and technology carry this one while most sectors fall. Check the dispersion before you trust the direction.
FAQ
How stock market do for June 30, 2026?
E close higher: SPY gain 0.73% and QQQ gain 1.63% compared with June 29 closing. Market breadth narrow pass: 51.8% of liquid names rise, while 4 of 10 S&P sector funds close green.
Which sector lead market for June 30, 2026?
Technology: XLK gain 2.69%. Industrials follow with 1.34%, while real estate come last with -2%. Difference between the best and worst na 4.69 points.
Which stocks move pass for June 30, 2026?
Among names wey trade $10 million or more, JEM gain pass with +256.76%, while SOC lose pass with 55.89%. No split record dey for either one. So, na real price moves be this, no be corporate-action artifacts.
How stock market do for Q2 2026?
From April 1 opening to June 30 closing, across 62 sessions: QQQ +26.53%, IWM 20.21%, SPY 14.13%, DIA 12.08%. Quarter na growth-led one, and growth-led day na how e end.
Why volume dey trade plenty for the last half hour?
The final half hour carry 4.63 billion shares, compared with 2.05 billion for the open. Closing auction set each stock official closing price through one crossing. Index funds trade for that auction to match the closing price. Quarter-end rebalancing also concentrate the flow.
Data notes and method
- The baskets. Sector board na the ten SPDR sector funds wey panel name, and na the same basket every session, so dispersion number fit compare across days. Mover boards dey require $10 million turnover and previous close above $1. Dem exclude the reused-symbol listing wey dey above, and dem carry split-record column.
- The caveats. Dollar volume na per-minute proxy (close × volume for each bar). June 30 filing index almost empty; month-end gap note explain why. News counts come from one vendor feed only: if article no dey here, e no prove say nobody publish am anywhere.
- The volume panel's closing half hour counts the closing auction prints. One-minute bars no include auction prints, so half-hour panel add every trade wey carry closing-print sale condition, timestamped 4:00 to 4:15 p.m. ET for consolidated tape, to the final bucket.
- The method. Na one session (1, verified from observed bars); timestamps dey stored for UTC and queries convert dem to New York time; "close" na the last regular minute bar, no be auction print. Dem re-parse option expiries from OCC ticker because table own column spoil; dem measure moneyness against SPY last regular bar. Panels run once, when author dey prepare am, through gated read-only path. Warehouse as of July 13, 2026.
Every panel na stored query result, chart, table and SQL inside one object. Paste any of dem into Strasmore terminal. Next session: July 1.