Strasmore Research
Market Recap 2026-07-02

Market Recap: July 1, 2026 — The Day in Numbers

The second half opened with one of the month's quietest index days atop a violent tape: the memory complex broke, META diverged, the dividend wave crested.

Wednesday, July 1, 2026 — the first session of the second half — put one of the month's quietest index days on top of one of its most violent tapes. SPY closed -0.08%, yet QQQ printed -1.44%, 3464 liquid names dropped against 2922 advancers, and the memory-and-storage complex that carried the second quarter broke hard. The half that ended the night before is measured in the H1 recap; the prior session is the June 30 recap. Every number below is read from a stored query — expand any panel for the exact SQL.

The scoreboard

Every change compares July 1's last regular-session minute bar with Tuesday June 30's.

QuerySPY / QQQ / DIA / IWM — July 1 vs the June 30 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-30 13:30:00' AND window_start < '2026-06-30 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-07-01 13:30:00' AND window_start < '2026-07-01 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

The split is the story: DIA at 0.02% and SPY at -0.08% held roughly flat against QQQ's -1.44% and IWM's -0.37% — a growth-index selloff the broad market barely registered at the close level.

One of the quietest index days of the trailing month — the receipt

QuerySPY's open-to-close move ranked against the trailing month of sessions (rank 1 = biggest absolute move)
The exact SQL behind every number
SELECT round(anyIf(oc_pct, d = toDate('2026-07-01')), 2) AS day_move_pct,
       arrayCount(x -> x > abs(anyIf(oc_pct, d = toDate('2026-07-01'))), groupArrayIf(abs(oc_pct), d != toDate('2026-07-01'))) + 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-02 00:00:00')
      AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199
    GROUP BY d
)

Measured open-to-close within the session — a different lens from the close-over-close scoreboard, stated here — SPY moved 0.09%: rank 20 of 22 trailing sessions by absolute size — only two trailing sessions moved less. That stillness is itself the observation — underneath it, the single-name tape was anything but still.

Breadth: more fell than rose

QueryAdvancers vs decliners among tickers with at least $1M traded on July 1
The exact SQL behind every number
WITH per_ticker AS (
    SELECT
        ticker,
        toFloat64(argMaxIf(close, window_start, window_start < '2026-07-01 00:00:00')) AS prior_close,
        toFloat64(argMaxIf(close, window_start, window_start >= '2026-07-01 00:00:00')) AS day_close,
        sumIf(toFloat64(close) * toFloat64(volume), window_start >= '2026-07-01 00:00:00') AS day_dollar_volume
    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')
       OR (window_start >= '2026-07-01 13:30:00' AND window_start < '2026-07-01 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
FROM per_ticker
WHERE prior_close > 0 AND day_close > 0

2922 advancers, 3464 decliners, 82 unchanged — 45.2% of the liquid tape rose, the day's selling reaching well past the growth index. The filter drops 5098 of 11566 dual-session tickers under $1 million traded, counted here rather than hidden.

The day's highlight: the memory complex broke

Four names that led the quarter fell together — co-movement and magnitude reported; the data does not say why.

QueryThe memory and storage names: change vs Tuesday's close, range timing, and dollar volume
The exact SQL behind every number
WITH per_name AS (
    SELECT
        ticker,
        toFloat64(argMaxIf(close, window_start, window_start < '2026-07-01 00:00:00')) AS prior_close,
        toFloat64(argMaxIf(close, window_start, window_start >= '2026-07-01 00:00:00')) AS day_close,
        maxIf(toFloat64(high), window_start >= '2026-07-01 00:00:00') AS day_high,
        minIf(toFloat64(low), window_start >= '2026-07-01 00:00:00') AS day_low,
        argMinIf(window_start, toFloat64(low), window_start >= '2026-07-01 00:00:00') AS low_bar,
        argMaxIf(window_start, toFloat64(high), window_start >= '2026-07-01 00:00:00') AS high_bar,
        round(sumIf(toFloat64(close) * toFloat64(volume), window_start >= '2026-07-01 00:00:00') / 1e9, 2) AS day_dollar_bn
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker IN ('MU', 'SNDK', 'STX', 'WDC')
      AND ((window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00')
        OR (window_start >= '2026-07-01 13:30:00' AND window_start < '2026-07-01 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

MU printed -10.23% on $42.94 billion of turnover — more than SPY itself traded all day — its high at 09:48 ET, its low at 15:59, the session's final minute. SanDisk closed -10.45%, Western Digital -6.3%, Seagate -5.11%. All four printed morning highs; MU and SanDisk bled to late-day lows (15:59 and 14:49 ET) while Seagate and Western Digital bottomed in the morning (09:35, 10:46) — the fade was two names' story, not the group's. The quarter these names had just finished — MU up triple digits, the group leading the whole tape's turnover — is receipted in the MU deep-dive and the Q2 recap; this page reports the single day.

The other side of the tape diverged just as hard:

QueryMegacap divergence: change vs Tuesday's close, range timing, and dollar volume
The exact SQL behind every number
WITH per_name AS (
    SELECT
        ticker,
        toFloat64(argMaxIf(close, window_start, window_start < '2026-07-01 00:00:00')) AS prior_close,
        toFloat64(argMaxIf(close, window_start, window_start >= '2026-07-01 00:00:00')) AS day_close,
        maxIf(toFloat64(high), window_start >= '2026-07-01 00:00:00') AS day_high,
        minIf(toFloat64(low), window_start >= '2026-07-01 00:00:00') AS day_low,
        argMinIf(window_start, toFloat64(low), window_start >= '2026-07-01 00:00:00') AS low_bar,
        argMaxIf(window_start, toFloat64(high), window_start >= '2026-07-01 00:00:00') AS high_bar,
        round(sumIf(toFloat64(close) * toFloat64(volume), window_start >= '2026-07-01 00:00:00') / 1e9, 2) AS day_dollar_bn
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker IN ('AMD', 'META', 'MRVL', 'NVDA')
      AND ((window_start >= '2026-06-30 13:30:00' AND window_start < '2026-06-30 20:00:00')
        OR (window_start >= '2026-07-01 13:30:00' AND window_start < '2026-07-01 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

META rose 8.88% against a falling Nasdaq — its low printed at 09:30 ET, the open, its high at 11:05 — while AMD printed -6.87%, Marvell -8.68%, and NVDA -1.09% — holding up while its memory-making neighbors slid. NVDA's June is dissected here.

Where the money traded

QueryVolume leaders two ways: top 6 by dollars traded, top 4 by shares traded (one reused-symbol listing 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-07-01 13:30:00' AND window_start < '2026-07-01 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-07-01 13:30:00' AND window_start < '2026-07-01 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

MU's $42.94 billion led the entire tape — $27.76 billion for SPY in second — a falling stock out-trading the index fund by half again. META's $22.72 billion put the megacap panel's one green name fourth on the board. The share board is the usual funhouse mirror: SOXS, the 3x-inverse semiconductor ETF, led at 553.1 million shares, and a low-priced name rounds out the board at 189.8 million shares worth $319 million all day. Basis: July 1 regular hours; one reused-symbol June listing is excluded pending entity verification — its receipts.

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-07-01 13:30:00' AND window_start < '2026-07-01 20:00:00'
GROUP BY et_time
ORDER BY et_time

2.22 billion shares in the opening half hour, a 0.82 billion trough at 14:00, and 2.46 billion into the close — the classic smile.

The options tape

QueryOne row for the whole options day: volume, same-day expiry, the 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-07-01 00:00:00' AND sip_timestamp < '2026-07-02 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-07-01 13:30:00' AND window_start < '2026-07-01 20:00:00'
    ) AS spy_regular_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) = '260701') / 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,
    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_regular_close, 2) AS top_strike_minus_spy_close
FROM global_markets.options_trades
WHERE sip_timestamp >= '2026-07-01 00:00:00' AND sip_timestamp < '2026-07-02 00:00:00'

Options traded 68.46 million contracts across 11.22 million prints — calls 58.6% of volume, same-day expiries 33.5%. The busiest single contract was the same-day SPY $748 call — 878947 contracts at an average $0.707 premium, SPY's close landing 2.31 dollars below the strike: out of the money, as Tuesday's was. No contract with a Friday, July 3 expiration code printed all day (0 prints) — the market is closed that Friday — while the Thursday weekly carried 14.43 million contracts.

Rates: drifting up, front end down

Yields are daily closes; changes are against Tuesday, June 30.

QueryThe Treasury curve, July 1 close vs June 30 (populated maturities only)
The exact SQL behind every number
SELECT
    t.1 AS curve_point,
    round(t.2, 2) AS jul1_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-07-01') AS d,
         (SELECT * FROM global_markets.treasury_yields WHERE date = '2026-06-30') AS p
)

The 10-year added 4 bp to 4.48% and the 30-year 6 bp, while the 1-month bill moved -3 bp — belly and long end up, the very front end down. The 2s10s spread closed at 0.31 percentage points.

The calendar behind the day

QueryJuly 1's corporate calendar and information flow, in one row
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-07-01'
    ) 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-07-01'
            )
            WHERE t != 'SPCX'
            GROUP BY t
        )
    ) AS top_news
SELECT
    (SELECT count() FROM global_markets.stocks_dividends WHERE ex_dividend_date = '2026-07-01') AS ex_dividend_records,
    (SELECT count() FROM global_markets.stocks_splits WHERE execution_date = '2026-07-01') AS splits_executed,
    (SELECT count() FROM global_markets.stocks_ipos WHERE listing_date = '2026-07-01') AS ipos_listed,
    (SELECT uniqExact(accession_number) FROM global_markets.stocks_sec_edgar_index WHERE filing_date = '2026-07-01') AS sec_filings,
    (SELECT uniqExactIf(accession_number, form_type = '4') FROM global_markets.stocks_sec_edgar_index WHERE filing_date = '2026-07-01') AS insider_form4_filings,
    (SELECT uniqExactIf(accession_number, form_type = '8-K') FROM global_markets.stocks_sec_edgar_index WHERE filing_date = '2026-07-01') AS filings_8k,
    (SELECT arrayStringConcat(groupArray(concat(ticker, ' — ', issuer_name)), '; ') FROM (
        SELECT ticker, issuer_name FROM global_markets.stocks_ipos WHERE listing_date = '2026-07-01' 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

The quarter turn crested exactly here: 746 dividend records went ex-dividend on July 1 — the wave the June recap watched building — alongside 10 splits and 3 listings (BSP — Bending Spoons S.p.A.; ITG — ITG Inc.; LIME — Neutron Holdings Inc.) — the debuts Monday's recap flagged in advance. The filing feed also came back to life: 4282 filings — 1072 Form 4s, 248 8-Ks — after June 30's near-empty index day (the month-end gap note has that story). Our news feed carried 201 articles from 3 publishers; the most-covered name was MSFT at 16 articles.

The session, verified

QuerySession check: SPY's 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-07-01 13:30:00' AND window_start < '2026-07-01 20:00:00') AS regular_session_bars,
    uniqExactIf(toDate(toTimeZone(window_start, 'America/New_York')), window_start >= '2026-07-01 13:30:00' AND window_start < '2026-07-01 20:00:00') AS day_sessions
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY' AND window_start >= '2026-07-01 00:00:00' AND window_start < '2026-07-02 00:00:00'

SPY's bars run 04:00 to 19:59 New York time with exactly 390 regular-window bars — a complete regular session, verified from the tape (the exchange-calendar dataset only carries upcoming closures, so past-day session checks are tape-based).

Data notes

  • Dollar volume is a per-minute proxy — close × volume summed per minute bar.
  • The index ETFs' highs and lows were cross-checked against adjacent bars at authoring time — an editorial procedure, receipted only when it surfaces an anomaly; none did on this session.
  • One reused-symbol June listing is excluded from the volume leaderboards pending entity verification; its own post carries the receipts.
  • The news feed's ticker tags include occasional malformed symbols; counts are per-tag as stored, and the feed spans only 3 publishers — a narrow source base, stated where used.

Methodology

  • The period is a single trading session ({v:session_count} session, verified from observed bars). Timestamps are stored in UTC and converted to New York time inside the queries. "Close" means the last regular-session minute bar; day changes compare July 1 with June 30. The session was verified from the observed bar span — never assumed.
  • Decimal columns are cast to 64-bit floats before ratio arithmetic; option expiries are re-parsed from the OCC ticker (the table's own expiry column is broken). All panels are read once, at authoring time, through the gated read-only path. Warehouse state as of July 5, 2026.

Every panel is a stored query result — chart, table, and SQL are one object. Paste any of them into the Strasmore terminal and make them your own. Previous session: June 30. Next: July 2. The week: the four-session holiday week.