market recap week july 20 2026
SPY rank for week after July options expiry, sector dispersion, weekly breadth, and where dollars flow. Concrete numbers from stored queries.
The week wey start for July 20, 2026 na di first full week after July monthly options expire, and e run 5 sessions wey no get closure inside am. SPY change from close to close for dat week na -0.59%, and when we measure open-to-close against di trailing year of weeks, e rank 43 out of 53. Every number wey dey below na from stored query, and every window dey pinned to specific dates, so if you run di SQL again, you go get di same figures.
Di week for di board
Weekly changes dey run from Friday July 17 regular close go reach Friday July 24 own. Di last column carry di week before am, so di two dey side by side. Rows dey alphabetical.
The exact SQL behind every number
SELECT ticker,
round(argMaxIf(toFloat64(close), window_start, window_start >= '2026-07-17 13:30:00' AND window_start < '2026-07-17 20:00:00'), 2) AS prior_week_close,
round(argMaxIf(toFloat64(close), window_start, window_start >= '2026-07-24 13:30:00' AND window_start < '2026-07-24 20:00:00'), 2) AS week_close,
round((argMaxIf(toFloat64(close), window_start, window_start >= '2026-07-24 13:30:00' AND window_start < '2026-07-24 20:00:00')
/ argMaxIf(toFloat64(close), window_start, window_start >= '2026-07-17 13:30:00' AND window_start < '2026-07-17 20:00:00') - 1) * 100, 2) AS week_change_pct,
round((argMaxIf(toFloat64(close), window_start, window_start >= '2026-07-17 13:30:00' AND window_start < '2026-07-17 20:00:00')
/ argMaxIf(toFloat64(close), window_start, window_start >= '2026-07-10 13:30:00' AND window_start < '2026-07-10 20:00:00') - 1) * 100, 2) AS prior_week_change_pct
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'QQQ', 'DIA', 'IWM')
AND ((window_start >= '2026-07-10 13:30:00' AND window_start < '2026-07-10 20:00:00')
OR (window_start >= '2026-07-17 13:30:00' AND window_start < '2026-07-17 20:00:00')
OR (window_start >= '2026-07-24 13:30:00' AND window_start < '2026-07-24 20:00:00'))
GROUP BY ticker
ORDER BY tickerFor di week: DIA move -0.38%, IWM -0.98%, QQQ -1.59%, and SPY -0.59% go $738.85 close. Di readings for di week before, for di same alphabetical order, na -0.95%, -0.63%, -4.17%, and -1.55%. How far di four indexes dey apart na di first tin wey scoreboard dey measure, and e no always small.
Di week against di year wey don pass
One week number no mean anything if you no see di whole picture. Dis panel dey recalculate every week wey don pass with di same method, from open to close for di regular session, and e rank dis one inside dem.
The exact SQL behind every number
SELECT round(anyIf(ret, wk = toDate('2026-07-20')), 2) AS week_open_to_close_pct,
arrayCount(x -> x > anyIf(ret, wk = toDate('2026-07-20')), groupArrayIf(ret, wk != toDate('2026-07-20'))) + 1 AS rank_best,
count() AS weeks_compared,
toString(min(wk)) AS first_week,
anyIf(sessions_measured, wk = toDate('2026-07-20')) AS sessions_this_week
FROM (
SELECT toStartOfWeek(toDate(toTimeZone(window_start, 'America/New_York')), 1) AS wk,
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions_measured,
(argMax(toFloat64(close), window_start) / argMin(toFloat64(open), window_start) - 1) * 100 AS ret
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2025-07-21 00:00:00')
AND window_start < toDateTime('2026-07-25 00:00:00')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY wk
HAVING sessions_measured >= 3
)If you measure am like dat, SPY return -1.1% and e rank 43 out of 53 weeks wey don pass since 2025-07-21. Make you note di difference for definition: dis figure start from di week first regular-session open, di scoreboard wey dey up dey start from di week wey don pass close. Both dey mark everywhere dem appear.
Five sessions, one arc
The exact SQL behind every number
SELECT toString(d) AS date,
round(c, 2) AS spy_close,
round((c / prev_c - 1) * 100, 2) AS change_pct,
round(shares_m, 1) AS spy_shares_m
FROM (
SELECT d, c, shares_m,
lagInFrame(c) OVER (ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_c
FROM (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMax(toFloat64(close), window_start) AS c,
toFloat64(sum(volume)) / 1e6 AS shares_m
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND ((window_start >= '2026-07-17 13:30:00' AND window_start < '2026-07-17 20:00:00')
OR (window_start >= '2026-07-20 13:30:00' AND window_start < '2026-07-24 20:00:00'))
AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199
GROUP BY d
)
)
WHERE d >= '2026-07-20'
ORDER BY dateSession by session, di change for SPY na -0.15% Monday, 0.84% Tuesday, -0.12% Wednesday, -1.22% Thursday, and 0.08% Friday, e finish at $738.85 on 40.1 million shares. Monday figure dey measured against di July 17 close, wey be di session wey come before di period.
Breadth, session by session
Index level na one number. Breadth dey count how many stocks follow am move, and na dat number wey go tell you whether green week dey wide or narrow.
The exact SQL behind every number
SELECT toString(d) AS date, advancers, decliners, unchanged, measured_names
FROM (
SELECT d,
countIf(c > prev_c) AS advancers,
countIf(c < prev_c) AS decliners,
countIf(c = prev_c) AS unchanged,
count() AS measured_names
FROM (
SELECT d, c, dv,
lagInFrame(c) OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_c
FROM (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMax(toFloat64(close), window_start) AS c,
sum(toFloat64(close) * toFloat64(volume)) AS dv
FROM global_markets.delayed_stocks_minute_aggs
WHERE ((window_start >= '2026-07-17 13:30:00' AND window_start < '2026-07-17 20:00:00')
OR (window_start >= '2026-07-20 13:30:00' AND window_start < '2026-07-24 20:00:00'))
AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199
GROUP BY ticker, d
)
)
WHERE d >= '2026-07-20' AND prev_c > 0 AND dv >= 5000000
GROUP BY d
)
ORDER BY dateFor Monday, 1268 out of 3945 wey dem measure rise, 2632 fall. By Friday, di split read 2273 up against 1635 down, out of 3950. Names wey no get close for both side of session dem no count dem, na why di measured number dey shift small from day to day.
Di same question wey dem ask once, across di whole week:
The exact SQL behind every number
SELECT
countIf(cw > cp AND liquid) AS advancers,
countIf(cw < cp AND liquid) AS decliners,
countIf(cw = cp AND liquid) AS unchanged,
countIf(liquid) AS measured_names,
countIf(NOT liquid) AS dropped_by_liquidity_filter,
round(100.0 * countIf(cw > cp AND liquid) / countIf(liquid), 1) AS advancer_pct
FROM (
SELECT ticker, cp, cw, dv >= 5000000 AS liquid
FROM (
SELECT ticker,
argMaxIf(toFloat64(close), window_start, window_start < '2026-07-18 00:00:00') AS cp,
argMaxIf(toFloat64(close), window_start, window_start >= '2026-07-24 13:30:00') AS cw,
sumIf(toFloat64(close) * toFloat64(volume), window_start >= '2026-07-20 13:30:00') AS dv
FROM global_markets.delayed_stocks_minute_aggs
WHERE ((window_start >= '2026-07-17 13:30:00' AND window_start < '2026-07-17 20:00:00')
OR (window_start >= '2026-07-20 13:30:00' AND window_start < '2026-07-25 00:00:00'))
AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199
GROUP BY ticker
HAVING cp > 0 AND cw > 0
)
)Across 6100 names wey pass di five-million-dollar regular-hours turnover bar, 2437 close above dia July 17 close, 3630 close below, wey make advancer share be 40%. Di liquidity filter set aside 5099 names wey trade under dat bar during di week. Dem count dem here, no be say dem just throw dem away.
Di sector scoreboard
Di eleven SPDR sector ETFs, from July 17 close go reach July 24 close, wey dem rank from best to worst.
The exact SQL behind every number
SELECT sector, week_pct, round(max(week_pct) OVER () - week_pct, 2) AS points_behind_best
FROM (
SELECT multiIf(ticker = 'XLK', 'Technology', ticker = 'XLC', 'Communications', ticker = 'XLE', 'Energy',
ticker = 'XLF', 'Financials', ticker = 'XLI', 'Industrials', ticker = 'XLB', 'Materials',
ticker = 'XLP', 'Staples', ticker = 'XLRE', 'Real Estate', ticker = 'XLU', 'Utilities',
ticker = 'XLV', 'Health Care', 'Consumer Discretionary') AS sector,
round((cw / cp - 1) * 100, 2) AS week_pct
FROM (
SELECT ticker,
argMaxIf(toFloat64(close), window_start, window_start < '2026-07-18 00:00:00') AS cp,
argMaxIf(toFloat64(close), window_start, window_start >= '2026-07-24 13:30:00') AS cw
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('XLB', 'XLC', 'XLE', 'XLF', 'XLI', 'XLK', 'XLP', 'XLRE', 'XLU', 'XLV', 'XLY')
AND ((window_start >= '2026-07-17 13:30:00' AND window_start < '2026-07-17 20:00:00')
OR (window_start >= '2026-07-24 13:30:00' AND window_start < '2026-07-24 20:00:00'))
GROUP BY ticker
HAVING cp > 0 AND cw > 0
)
)
ORDER BY week_pct DESCEnergy dey for di top of di board at 3.33%. Consumer Discretionary dey for di bottom at -5.2%, 8.53 percentage points behind am. Dat gap na di week's sector dispersion, and e get value to read am alone: a week wey all eleven land inside one point of each oda na very different market from one wey di spread run enter double digits.
Where the dollars dey go
The exact SQL behind every number
SELECT ticker, week_dollar_bn, round(100 * week_dollar_bn / max(week_dollar_bn) OVER (), 1) AS pct_of_leader
FROM (
SELECT ticker,
round(sum(toFloat64(close) * toFloat64(volume)) / 1e9, 1) AS week_dollar_bn
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= '2026-07-20 13:30:00' AND window_start < '2026-07-24 20:00:00'
AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199
AND ticker NOT IN ('SPCX')
GROUP BY ticker
ORDER BY week_dollar_bn DESC
LIMIT 8
)
ORDER BY week_dollar_bn DESCMU print 158.1 billion dollars of regular-hours turnover for di five sessions, pass SPY wey get 133.9 billion and QQQ wey get 101.5 billion. Eighth for di board, AAPL, trade 34.5% of di leader dollars. Turnover record where di market spend im week dey argue, and e no gree with di price. Di per-name version of dis measure na relative volume.
Di week wey get di biggest movers
Splits dey change di print but no dey change di value: reverse split dey make fake four-digit gain, forward split dey make fake collapse wey get di same size. Di week carry 25 reverse splits and 11 forward splits, and both boards below no include any name wey dem split between July 17 close and July 24 close, di exact time wey dem measure di change. Both boards also need five million dollars of regular-hours turnover.
The exact SQL behind every number
SELECT ticker, board, week_pct, week_dollar_m, sessions_traded,
round(100 * week_dollar_m / max(week_dollar_m) OVER (), 1) AS pct_of_dollar_max
FROM (
SELECT 'gainers' AS board, ticker, round((cw / cp - 1) * 100, 1) AS week_pct,
round(dv / 1e6, 1) AS week_dollar_m, sessions_traded
FROM (
SELECT ticker,
argMaxIf(toFloat64(close), window_start, window_start < '2026-07-18 00:00:00') AS cp,
argMaxIf(toFloat64(close), window_start, window_start >= '2026-07-24 13:30:00') AS cw,
sumIf(toFloat64(close) * toFloat64(volume), window_start >= '2026-07-20 13:30:00') AS dv,
uniqExactIf(toDate(toTimeZone(window_start, 'America/New_York')), window_start >= '2026-07-20 13:30:00') AS sessions_traded
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker NOT IN ('SPCX')
AND ticker NOT IN (SELECT ticker FROM global_markets.stocks_splits WHERE execution_date > '2026-07-17' AND execution_date <= '2026-07-24')
AND ((window_start >= '2026-07-17 13:30:00' AND window_start < '2026-07-17 20:00:00')
OR (window_start >= '2026-07-20 13:30:00' AND window_start < '2026-07-25 00:00:00'))
AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199
GROUP BY ticker
HAVING cp > 0 AND cw > 0 AND dv >= 5000000
)
ORDER BY week_pct DESC
LIMIT 10
UNION ALL
SELECT 'decliners' AS board, ticker, round((cw / cp - 1) * 100, 1) AS week_pct,
round(dv / 1e6, 1) AS week_dollar_m, sessions_traded
FROM (
SELECT ticker,
argMaxIf(toFloat64(close), window_start, window_start < '2026-07-18 00:00:00') AS cp,
argMaxIf(toFloat64(close), window_start, window_start >= '2026-07-24 13:30:00') AS cw,
sumIf(toFloat64(close) * toFloat64(volume), window_start >= '2026-07-20 13:30:00') AS dv,
uniqExactIf(toDate(toTimeZone(window_start, 'America/New_York')), window_start >= '2026-07-20 13:30:00') AS sessions_traded
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker NOT IN ('SPCX')
AND ticker NOT IN (SELECT ticker FROM global_markets.stocks_splits WHERE execution_date > '2026-07-17' AND execution_date <= '2026-07-24')
AND ((window_start >= '2026-07-17 13:30:00' AND window_start < '2026-07-17 20:00:00')
OR (window_start >= '2026-07-20 13:30:00' AND window_start < '2026-07-25 00:00:00'))
AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199
GROUP BY ticker
HAVING cp > 0 AND cw > 0 AND dv >= 5000000
)
ORDER BY week_pct ASC
LIMIT 10
)
ORDER BY board DESC, abs(week_pct) DESCTo make any of di two boards, di move must be real. Di mildest gainer wey show rise 92.3%, and di mildest decliner print -47.8%. For di extremes, STAK move 383.7% on 251.6 million dollars wey trade, and LBGJ move -98.8% on 47.7 million. Dat decline dey close to di whole quoted value of di name, so di board get im own receipt: LBGJ print regular-hours bars on 5 of di five sessions, and no split execute against am between di two closes wey di board measure.
Di quoted spread, session by session
Price na di main tory. Di cost to finish di trade na di quoted spread, wey dem measure here for SPY one session at a time, straight from di raw NBBO tape, no be from any summary.
The exact SQL behind every number
SELECT toString(toDate(sip_timestamp)) AS date,
round(quantileExactIf(0.5)(
10000 * (toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2),
bid_price > 0 AND ask_price > 0 AND ask_price >= bid_price), 2) AS median_spread_bps,
round(count() / 1e6, 2) AS quote_updates_m,
countIf(bid_price <= 0 OR ask_price <= 0) AS one_sided_quote_count,
countIf(bid_price > ask_price AND bid_price > 0 AND ask_price > 0) AS crossed_quote_count
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'SPY'
AND sip_timestamp >= '2026-07-20 13:30:00'
AND sip_timestamp < '2026-07-24 20:00:00'
AND (toHour(sip_timestamp) * 60 + toMinute(sip_timestamp)) BETWEEN 810 AND 1199
GROUP BY toDate(sip_timestamp)
HAVING countIf(bid_price > 0 AND ask_price > 0 AND ask_price >= bid_price) > 0
ORDER BY toDate(sip_timestamp)SPY's median quoted spread bin measure 0.27 basis points of mid for Monday and 0.27 for Friday, on 3.89 million and 4.4 million NBBO updates. Di last two columns na di disclosure, no be di finding: 0 one-sided quotes and 1084 crossed quotes dem count out of Monday's median instead of dem drop am quiet. A crossed quote, wey bid dey above ask, na normal artifact of a consolidated feed wey dem stitch from many venues for nanosecond resolution.
Di options week afta monthly expiration
July monthly expiration fall for di Friday before dis week open, so every contract wey dey trade for dis five sessions na survivor of am. Expiration timing set di rhythm wey di same-day crowd dey trade to.
The exact SQL behind every number
SELECT toString(toDate(sip_timestamp)) AS date,
round(toFloat64(sum(size)) / 1e6, 1) AS contracts_m,
round(100.0 * sumIf(size, substring(ticker, length(ticker) - 14, 6) = formatDateTime(toDate(sip_timestamp), '%y%m%d')) / sum(size), 1) AS pct_0dte,
round(100.0 * sumIf(size, substring(ticker, length(ticker) - 8, 1) = 'C') / sum(size), 1) AS pct_call,
round(100.0 * sumIf(size, substring(ticker, length(ticker) - 14, 6) = '260724') / sum(size), 1) AS pct_expiring_jul24
FROM global_markets.options_trades
WHERE sip_timestamp >= '2026-07-20 00:00:00' AND sip_timestamp < '2026-07-25 00:00:00'
GROUP BY toDate(sip_timestamp)
ORDER BY toDate(sip_timestamp)Contract volume run 64 million for Monday and 71.1 million for Friday. Di same-day share, wey mean contracts wey go expire for di session wey dem trade am, read 40.2% Monday against 49% Friday, di week wey expiration happen. Calls take 53.5% of Friday contract volume. And di pull of dat Friday show from di opening session: 15.1% of Monday volume already dey for contracts wey date to expire for am.
Rates across di week
The exact SQL behind every number
SELECT toString(date) AS date,
round(toFloat64(yield_2_year), 2) AS yield_2y_pct,
round(toFloat64(yield_10_year), 2) AS yield_10y_pct,
round(toFloat64(yield_30_year), 2) AS yield_30y_pct,
round((toFloat64(yield_10_year) - toFloat64(yield_2_year)) * 100) AS spread_2s10s_bp,
round((toFloat64(yield_10_year) - (SELECT toFloat64(any(yield_10_year)) FROM global_markets.treasury_yields WHERE date = '2026-07-17')) * 100) AS chg_10y_from_prior_close_bp
FROM global_markets.treasury_yields
WHERE date >= '2026-07-17' AND date <= '2026-07-24'
ORDER BY dateFrom di July 17 print, di ten-year move 16 basis points go reach 4.71% for di last print wey dey for file, wit di two-year dey 4.37% and di thirty-year dey 5.17%. Di two-to-ten-year spread finish di series at 34 basis points. Treasury file dey run about one session behind di tape, so dis panel get 5 prints, each one get date for di table.
Di shorts: di daily files
FINNA dey publish daily short-sale volume file. Short volume na gross daily flow, no be position, and dis files sometimes arrive wey dem cut am short, so coverage dey measure before any ratio dey quote from dem.
The exact SQL behind every number
SELECT date, tickers_on_file, short_shares_bn,
round(100.0 * tickers_on_file / max(tickers_on_file) OVER (), 1) AS pct_of_fullest_file
FROM (
SELECT toString(date) AS date,
uniqExact(ticker) AS tickers_on_file,
round(sum(short_shares) / 1e9, 2) AS short_shares_bn
FROM (
SELECT date, ticker, max(short_volume) AS short_shares
FROM global_markets.stocks_short_volume
WHERE date >= '2026-07-20' AND date <= '2026-07-24'
GROUP BY date, ticker
)
GROUP BY date
)
ORDER BY date5 daily files dey for di week. Di first hold 15098 tickers and 4.71 billion short-marked shares; di last hold 15062 tickers, or 99.7% of di fullest file's ticker count. Any per-name short-volume claim wey dem draw from file wey dey sit well under im neighbors, e go remain unverifiable until dat file dem refile am.
Di calendar behind di week
The exact SQL behind every number
SELECT toString(filing_date) AS date,
count() AS filings,
countIf(form_type = '4') AS form4,
countIf(form_type = '8-K') AS form8k,
countIf(form_type = '424B2') AS f424b2
FROM global_markets.stocks_sec_edgar_index
WHERE filing_date >= '2026-07-20' AND filing_date <= '2026-07-24'
GROUP BY filing_date
ORDER BY dateDi first session wey dey for file carry 3012 filings, 632 of dem na insider Form 4 reports and 166 of dem na 8-Ks. Di last session carry 3814, with 644 Form 4s and 223 8-Ks. 5 of di week sessions get EDGAR daily index wey dey for file; dat index land on im own schedule, wey sometimes dey follow di tape late.
The exact SQL behind every number
SELECT
(SELECT count() FROM global_markets.stocks_sec_edgar_index WHERE filing_date >= '2026-07-20' AND filing_date <= '2026-07-24') AS filings_week,
(SELECT uniqExact(filing_date) FROM global_markets.stocks_sec_edgar_index WHERE filing_date >= '2026-07-20' AND filing_date <= '2026-07-24') AS filing_days_on_file,
(SELECT count() FROM global_markets.stocks_dividends WHERE ex_dividend_date >= '2026-07-20' AND ex_dividend_date <= '2026-07-24') AS ex_dividends_week,
(SELECT countIf(ticker IN ('AAPL', 'MSFT', 'JPM', 'KO', 'JNJ', 'XOM', 'CVX', 'PG', 'WMT', 'HD')) FROM global_markets.stocks_dividends WHERE ex_dividend_date >= '2026-07-20' AND ex_dividend_date <= '2026-07-24') AS household_ex_dividends_week,
(SELECT countIf(toFloat64(split_from) > toFloat64(split_to)) FROM global_markets.stocks_splits WHERE execution_date >= '2026-07-20' AND execution_date <= '2026-07-24') AS reverse_splits_week,
(SELECT countIf(toFloat64(split_to) > toFloat64(split_from)) FROM global_markets.stocks_splits WHERE execution_date >= '2026-07-20' AND execution_date <= '2026-07-24') AS forward_splits_week,
(SELECT count() FROM global_markets.stocks_ipos WHERE listing_date >= '2026-07-20' AND listing_date <= '2026-07-24') AS listings_week,
(SELECT count() FROM global_markets.stocks_news WHERE published_utc >= '2026-07-20 04:00:00' AND published_utc < '2026-07-25 04:00:00') AS news_week,
(SELECT uniqExact(JSONExtractString(publisher, 'name')) FROM global_markets.stocks_news WHERE published_utc >= '2026-07-20 04:00:00' AND published_utc < '2026-07-25 04:00:00') AS news_publishers_weekDi rest of di week paperwork: 17106 SEC filings across 5 days wey dem index, 592 ex-dividend records, 1 of dem come from di ten household names wey dis panel dey check, 25 reverse and 11 forward splits, 4 new listings, and 1704 articles from 2 publishers. Dat last pair dey measure one feed attention, not di whole world media.
Di sessions, wey don check am
The exact SQL behind every number
WITH spy AS (
SELECT d, c, lagInFrame(c) OVER (ORDER BY d ASC ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS p
FROM (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
argMax(toFloat64(close), window_start) AS c
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND ((window_start >= '2026-07-17 13:30:00' AND window_start < '2026-07-17 20:00:00')
OR (window_start >= '2026-07-20 13:30:00' AND window_start < '2026-07-24 20:00:00'))
AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 1199
GROUP BY d
)
)
SELECT
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions_in_week,
toString(min(toDate(toTimeZone(window_start, 'America/New_York')))) AS first_session,
toString(max(toDate(toTimeZone(window_start, 'America/New_York')))) AS last_session,
count() AS regular_bars_in_week,
(SELECT count() FROM global_markets.stocks_market_holidays WHERE date >= '2026-07-20' AND date <= '2026-07-24') AS holiday_rows_in_week,
(SELECT countIf(c > p) FROM spy WHERE d >= '2026-07-20') AS up_sessions,
(SELECT countIf(c < p) FROM spy WHERE d >= '2026-07-20') AS down_sessions,
(SELECT toString(min(date)) FROM global_markets.stocks_market_holidays WHERE date > '2026-07-24' AND date <= '2026-12-31' AND status = 'closed') AS next_closure_date,
(SELECT argMin(name, date) FROM global_markets.stocks_market_holidays WHERE date > '2026-07-24' AND date <= '2026-12-31' AND status = 'closed') AS next_closure_name
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= '2026-07-20 13:30:00' AND window_start < '2026-07-24 20:00:00'
AND (toHour(window_start) * 60 + toMinute(window_start)) BETWEEN 810 AND 11995 sessions, from 2026-07-20 go reach 2026-07-24, with 0 holiday rows for any part of di window. SPY don print 1950 regular-session minute bars across dem. 2 sessions close above di before close, and 3 close below am. Di next scheduled closure na Labor Day for 2026-09-07.
For di week wey dey come
For di week wey dey come, read from our own tables:
The exact SQL behind every number
SELECT
(SELECT count() FROM global_markets.stocks_market_holidays WHERE date >= '2026-07-27' AND date <= '2026-07-31' AND status != 'open') AS closures_next_week,
(SELECT count() FROM global_markets.stocks_dividends WHERE ex_dividend_date >= '2026-07-27' AND ex_dividend_date <= '2026-07-31') AS ex_dividends_next_week,
(SELECT countIf(ticker IN ('AAPL', 'MSFT', 'JPM', 'KO', 'JNJ', 'XOM', 'CVX', 'PG', 'WMT', 'HD')) FROM global_markets.stocks_dividends WHERE ex_dividend_date >= '2026-07-27' AND ex_dividend_date <= '2026-07-31') AS household_ex_div_next_week,
(SELECT count() FROM global_markets.stocks_splits WHERE execution_date >= '2026-07-27' AND execution_date <= '2026-07-31') AS splits_next_week,
(SELECT round(100.0 * sumIf(size, substring(ticker, length(ticker) - 14, 6) = '260731') / sum(size), 1) FROM global_markets.options_trades WHERE sip_timestamp >= '2026-07-24 00:00:00' AND sip_timestamp < '2026-07-25 00:00:00') AS jul31_expiry_pct_of_friday_volume,
(SELECT toString(max(settlement_date)) FROM global_markets.stocks_short_interest WHERE settlement_date <= '2026-07-24') AS latest_short_interest_settlementDi holiday table show 0 closures for di week wey dey come. 368 ex-dividend records fall inside am, 0 from di household set, plus 15 scheduled splits. For Friday options volume, 14.2% already dey inside contracts wey go expire di next Friday. Di most recent short-interest settlement date wey we get na 2026-07-15, one file wey dey publish wit delay wey long enough to get im own explainer.
FAQ
How di stock market do for di week of July 20, 2026?
SPY change -0.59% close over close from July 17 go July 24, with QQQ at -1.59%, DIA at -0.38%, and IWM at -0.98%. Among di liquid names, 2437 rise and 3630 fall.
Which sector lead di week of July 20, 2026?
Energy, at 3.33%. Di weakest among di eleven SPDR sector ETFs na Consumer Discretionary at -5.2%, 8.53 percentage points behind.
How many trading sessions dey for di week of July 20, 2026?
5, wey run from 2026-07-20 go 2026-07-24, with 0 holiday rows inside di window. Di next scheduled closure na Labor Day.
Which ticker trade di most dollars for di week of July 20, 2026?
MU, at 158.1 billion dollars of regular-hours turnover, ahead of SPY at 133.9 billion.
Data notes
All timestamps wey dey store na UTC; regular hours na 13:30-20:00 UTC per session, and week boundaries dey run from July 17 regular close go reach July 24. Every close-over-close panel wey dey here dey read di last regular-hours minute bar for each side of di comparison, so extended-hours print no fit set weekly close. Di trailing-year rank dey use open-to-close weekly returns, so e no go match di close-over-close scoreboard; both definitions dem mark where dem appear. Weekly breadth and di mover boards dey apply five-million-dollar regular-hours turnover filter, and breadth dey publish di count of names wey dat filter set aside. Mover boards no dey include any name wey dem split execute after July 17 close go through July 24, di exact interval wey di change dey measure over, wey catch split wey dem stamp for di intervening weekend as well as one wey dem stamp for session; dem no dey exclude leveraged and inverse ETFs, wey fit dominate board for directional week. Di bottom of di decliner board fit sit close to total loss of quoted value for di week, and dat board dey publish how many of di five sessions each name print for. Di SPY spread panel dey count one-sided and crossed quotes instead of dropping dem quiet, and di median dey take over di remaining valid quotes. Treasury file dey run about session behind di tape and di EDGAR daily index dey land for im own schedule, so di rates and filings panels dey report how many days dem actually hold. No implied-volatility index dey appear here: dem no license those series into dis warehouse, so volatility dem read off di tape through ranges, same-day options share, and quote behavior.
Methodology
- Market data source: consolidated tape.
delayed_stocks_minute_aggsfor prices and volumes,cache_stocks_quotesfor the NBBO panel,options_tradesfor the options week. - Close: di last regular-session minute bar of di session, never wey dem assume say na 16:00 print and never extended-hours print.
- Sessions: dem verify from di holiday table plus observed bars, never wey dem assume from di calendar.
- Time zone handling: WHERE clauses dey use raw UTC literals, and
toTimeZoneonly appear inside SELECT lists for ET labels. - Decimals: price, size, and volume columns dem cast to Float64 before any division or product.
- Deterministic aggregates: exact quantiles for everything, and every ordering or sign claim inside di prose dem encode as a sanity bound.
- Warehouse as-of date: July 26, 2026.
Cross-links: di previous edition of dis weekly series, wetin bid-ask spread be, wen options expire, short interest versus short volume, and di two-to-ten-year spread.
Every query wey dey above dey run unchanged on di Strasmore terminal if you wan re-point a window at a different week.