Strasmore Research
Market recaps wey dey break am down Matt ConnorBy Matt Connor · Updated 2026-07-25

Market Recap June 30 2026 — di day for numbers

Di quarter last session for numbers: technology-led index gain on top mostly red tape, memory complex dey lead, and same-day options tape for close.

Tuesday, June 30, 2026 — na di last session for di quarter — na technology carry di market up for one day wey mostly red: QQQ gain 1.63% and SPY 0.73%, but na only 4 out of di 10 S&P sector funds close higher (3,349 liquid names up, 3,033 down). Di session before dis one: di June 29 recap. Every number wey dey below na from stored query — expand any panel for di SQL.

Di scoreboard

Every change dey compare June 30 last regular-session minute bar with Monday June 29 own.

QuerySPY / QQQ / DIA / IWM — June 30 versus June 29 close, regular hours
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.ticker

SPY open for $741.29 and e finish for $746.32, near im $748.02 high. QQQ im 1.63% against DIA im 0.12% na di shape of di day: growth run, blue chips no really move, IWM 0.49%.

Di quarter wey close today

June 30 close di last of 62 sessions for second quarter, and di way di day bend na di quarter for small.

QueryQ2 2026 start to finish: each index ETF from April 1 open to June 30 close, regular hours
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 ASC

From April 1 open reach June 30 close: QQQ +26.53%, IWM 20.21%, SPY 14.13%, DIA 12.08%. QQQ top di quarter and June 30 sef, but di middle of di board swap: SPY small pass IWM for di day, IWM lead SPY across di quarter. QQQ close higher for 38 of di 62 sessions (di Q2 recap run am panel by panel).

Di day dey unusual?

QuerySPY open-to-close move rank against di trailing month of sessions (rank 1 = biggest absolute move)
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
)

Open-to-close inside di session — different lens from di close-over-close scoreboard — SPY move 0.68%, e rank 7 out of 21 trailing sessions by absolute size. Di index calm; di tape underneath no calm.

Breadth: small positive side dey show

QueryAdvancers vs decliners among tickers wey trade at least $1M on June 30
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 > 0

3,349 stocks wey go up, 3,033 stocks wey go down, 88 stocks wey no move: 51.8% of the liquid market rise — e be like coin toss under 1.63% growth-index reading. The liquidity filter remove 5,055 of 11,525 tickers wey trade for both sessions (under $1 million traded), we count dem here, we no hide am.

Sector by sector: where the money really dey

If you count each name as one vote, e go hide where the money sit. The ten funds wey dey below, each one hold one slice of the S&P 500, and the gap between the best and worst dey show how rough the session be.

QueryDi ten S&P sector funds on June 30: change vs Monday close, and how far each one sit behind di leader
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 ASC

Technology (XLK) gain 2.69% and stand alone: industrials 1.34%, materials 0.36% and discretionary 0.15% na the only other ones wey green, and the board turn red from financials (-0.17%) go down to utilities (-1.48%), staples (-1.53%) and real estate wey dey last at -2%. Best minus worst: 4.69 percentage points, 4 out of 10 funds green. Index wey rise less than one percent, four-point gap underneath: na one sector carry the day.

Di biggest movers for today, across di whole market

Breadth dey count how many names rise; dis one show which ones move pass — top and bottom five by percentage change among names wey dey trade $10 million or more.

QueryTop 5 gainers and top 5 decliners among names with $10M+ traded on June 30 (one reused-symbol listing dey excluded)
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 ASC

None of di two boards look like di index. JEM lead at +256.76% on $141 million wey dem trade; SOC lose 55.89% on $306 million. ABVX rise 38.56% on $942 million, na im get di heaviest turnover for any board; NVCT fall 35.62% and UNCY fall 39.09%. Di split-record column dey keep di board honest — one 1-for-10 reverse split go show as +900% "gain" for one unadjusted tape — and every name here carry one 0: na real prints.

Three rows na one trade wey dem do twice: CRCA (-35.16%) and CRCG (-35.19%) fall while CRCD rise 35.47% — each one dey close to twice di -17.53% move of di crypto-adjacent name wey dey below: na leveraged single-stock wrappers.

Di highlight for today: semiconductors as quarter dey turn

Six names, one theme, but di outcomes dey very different — na only co-movement and magnitude we dey look; di data no talk why.

QueryDi semiconductor and storage names: change vs Monday close, range, and dollar volume
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 ticker

SanDisk jump 10.79%, AMD 7.7%, Intel 5.93%, TSMC 4.86% — while MU, wey be di biggest ticket for di tape with $37.41 billion turnover, close just 0.52% higher and Western Digital (-2.01%) no follow. Dis na di complex wey dey behind technology im 2.69% sector print (MU for June, tick by tick).

Di counter-current run through crypto-adjacent financials, against di green tape:

QueryCrypto-adjacent financials: change vs Monday close, range, and dollar volume
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 ticker

CRCL print -17.53%, im $62.52 low show face for 15:59 ET — di session final minute — with MSTR -6.2%, COIN -3.61% and HOOD -1.53% dey follow. We observe co-movement; we no assert cause.

Wetin di news feed carry

One recap wey no dey claim cause must tell pesin wetin dem really publish dat day.

QueryDi news feed on June 30: article count and di day last headline for each name for dis recap
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 ASC

Di name wey dem cover pass na NVDA wit 21 articles — e no even dey among di movers for dat day — di last piece for di session (16:28 ET, Investing.com) get title "These Stocks Could Benefit as the Robotaxi Race Heats Up". MU draw 7; SanDisk own one article (The Motley Fool) na di only headline for di whole day wey name one real move: "Why Sandisk Stock Is Skyrocketing Today".

Di gap na di finding: di day biggest decliner, im heaviest gainer and di crypto-adjacent name wey fall pass draw 0, 0 and 0 articles — zero each, inside one feed of 211 pieces. Coverage no be proxy for price action.

Where the money trade

QueryVolume leaders two ways: top 6 by dollars traded, top 4 by shares traded (one reused-symbol listing dey excluded pending entity verification)
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) DESC

By dollars, MU stand tall pass everitin, even index funds: $37.41 billion against SPY own $31.84 billion — na di second straight session wey e out-trade di flagship index fund (Monday recap get di first one). Di share board show anoda tori: SOXS, one 3x-leveraged inverse semiconductor ETF (515.5 million shares), plus two sub-dollar names wey dia value na rounding error for MU day — volume read two ways.

We hold one name comot from both boards on purpose: na June listing wey im ticker bin belong to anoda, unrelate company before, so vendor feeds dey tag two entities wit di same three letters (receipts dey here).

QueryShares traded per 30-minute bucket, regular hours (billions)
The exact SQL behind every number
SELECT
    formatDateTime(toStartOfInterval(toTimeZone(window_start, 'America/New_York'), INTERVAL 30 MINUTE), '%H:%i') AS et_time,
    round(sum(toFloat64(volume)) / 1e9, 2) AS shares_bn,
    round(100 * sum(toFloat64(volume)) / max(sum(toFloat64(volume))) OVER (), 1) AS pct_of_biggest_bucket
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'
GROUP BY et_time
ORDER BY et_time

2.05 billion shares for di opening half hour, one 0.78 billion trough for 13:30, and di day biggest bucket — 2.69 billion — into one quarter-end close, where di closing auction and im rebalancing flows dey print (di June 29 deep dive dey under di bars).

Di options tape

QueryOne row for di whole options day: volume, same-day expiry, SPY put/call skew by moneyness, di holiday-shifted week
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 trade 61.95 million contracts across 10.06 million prints; calls collect 57.3% of tape-wide volume, and 28% of am expire dat Tuesday. SPY lean di oda way: 12.04 million contracts at put/call ratio of 1.09 — more puts dan calls, on a day wey di fund rise.

If you sort SPY same-day expiries against im $746.32 close, di skew go clear: 3.33 million out-of-the-money puts (strikes below di close) and 2.28 million out-of-the-money calls, against 1.77 million in-the-money calls and 0.63 million in-the-money puts — downside strikes wey expire worthless na di busiest bucket for SPY 0DTE day. Nottin wit Friday, July 3 expiry code print at all (0 prints — di market dey closed dat Friday); di Thursday weekly carry 10.52 million.

QueryDi six busiest option contracts of June 30, by contracts traded
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 ASC

Di busiest contract anywhere na di same-day SPY $747 call — 821,361 contracts at average premium of $0.641, e finish $0.68 above SPY last regular bar, and e worthless. Di board behind am na di lesson: five of di six busiest contracts for tape na same-day SPY strikes wey dey one dollar apart around di close (SPY $748 call next), each dey trade for cents. Di exception, at 65.1% of di leader volume, na KWEB $29 call wey expire December 18, 2026, no be same-day contract: one six-month position among five afternoon lottery tickets.

Rates: di long end rise as di half close

QueryDi Treasury curve, June 30 close vs June 29 (populated maturities only)
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
)

Di long end back up for di half last day: di 10-year rise 6 bp go 4.44%, di 2-year 4 bp go 4.14%, and di 2s10s spread steepen 2 bp go 0.3 points. Long yields rise for session wey im weakest sector, real estate (-2%), and im third-weakest, utilities (-1.48%), na both be classic rate-sensitive: na co-occurrence wey worth notice, no be mechanism wey dis data fit prove (di H1 recap carry di half curve).

Di calendar wey dey behind di day

QueryJune 30 corporate calendar and information flow, for one row (di filing-index gap dey show)
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_session

704 dividend records bin comot for ex-dividend for di quarter last day — na quarter-end wave, as most US companies dey pay every quarter — plus 7 splits and 2 new listings (AACU — Ares Acquisition Corp III; OSPRU — Osprey Acquisition Corp. III). Di filing column na di main data-quality headline: SEC index hold 31 filings for June 30 — 0 insider Form 4s, 0 8-Ks — against 4439 di session before. Na month-end pattern for di feed, wey dem diagnose for di month-end gap note; any count wey include dis day no go complete until e backfill.

Di session, wey dem don verify

QuerySession check: SPY observed minute-bar span
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 go reach 19:59 New York time, and e get exactly 390 regular-window bars — na complete session, wey dem verify from di tape (di exchange-calendar dataset only get di closures wey dey come).

Wetin di session add up to

One 0.73% SPY print wey get 51.8% of names wey dey up, 4 of 10 sector funds wey dey green and 4.69 points between di best and worst no be broad rally — na one sector rally wey wear index cloth, im heaviest half-hour inside quarter-end auction. Index change na average, and dis one na technology carry am while most sectors fall: check di dispersion before you trust di arrow.

FAQ

How stock market take be for June 30, 2026?

E close higher: SPY gain 0.73% and QQQ 1.63% against June 29 close. Breadth no wide reach — 51.8% of liquid names rise, 4 out of 10 S&P sector funds green.

Which sector lead the market for June 30, 2026?

Technology: XLK gain 2.69%, against 1.34% for industrials wey follow and -2% for real estate wey dey last — 4.69 points between best and worst.

Which stocks move pass for June 30, 2026?

Among names wey trade $10 million or more, JEM gain the most (+256.76%) and SOC lose the most (55.89%). None of dem get split record: both na real price moves, no be corporate-action artifacts.

How stock market take be for Q2 2026?

From the April 1 open to the June 30 close, across 62 sessions: QQQ +26.53%, IWM 20.21%, SPY 14.13%, DIA 12.08% — na growth-led quarter, wey growth-led day end am.

Why volume dey heavy for the last half hour?

The final half hour carry 2.69 billion shares against 2.05 billion for open. The closing auction set each stock official closing price for one crossing, and index funds dey trade there to match am; quarter-end rebalancing dey concentrate the flow.

Data notes and method

  • Di baskets. Di sector board na di ten SPDR sector funds wey dem name for inside im panel — na di same basket for every session, so di dispersion number fit compare across days. Di mover boards need $10 million turnover and prior close wey pass $1, dem comot di reused-symbol listing wey dey up, and dem get split-record column.
  • Di caveats. Dollar volume na per-minute proxy (close × volume per bar). Di June 30 filing index near-empty (di month-end gap note dey diagnose am). News counts na one vendor feed: no article here no be proof say nothing dem publish for anywhere.
  • Di method. One session (1, verified from observed bars); timestamps dem store for UTC, dem convert am to New York time for inside di queries; "close" na di last regular minute bar, no be di auction print. Option expiries dem re-parse from di OCC ticker (di table own column don spoil); dem measure moneyness against SPY last regular bar. Panels run once, for authoring time, through di gated read-only path. Warehouse as of July 13, 2026.

Every panel na stored query result — chart, table and SQL for one object. Paste any of dem inside di Strasmore terminal. Next session: July 1.