Le premier semestre 2026 a été composé de deux marchés distincts : un premier trimestre où chaque ETF d'indice majeur a chuté ou stagné, et un second trimestre qui a largement compensé ces pertes. Le SPY a terminé le semestre en hausse de 8.8% ; le QQQ était en hausse de 18.7% ; et le 21.3% de l'IWM a été le meilleur premier semestre enregistré par cet ETF small-cap selon nos données — le détail est présenté ci-dessous, recalculé par rapport à chaque année précédente via une requête unique. Le marché des taux a suivi sa propre dynamique : le spread 2s10s s'est aplati, passant de 72 points de base à 30 sur le semestre, sans jamais s'inverser. Cette page constitue le bilan complet du semestre — le score, le classement historique, l'évolution mensuelle, la courbe des taux par échéance, les onze secteurs, l'évolution mensuelle du marché des options et les titres individuels notables du semestre. Chaque chiffre provient d'une requête stockée ; vous pouvez développer n'importe quel panneau pour consulter la requête SQL.
Le bilan du semestre
Le SQL exact derrière chaque chiffre
SELECT ticker,
round((argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-06-30') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)
/ argMinIf(toFloat64(open), window_start, toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-01-01') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS h1_return_pct,
round((argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-03-31') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)
/ argMinIf(toFloat64(open), window_start, toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-01-01') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS q1_return_pct,
round((argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-06-30') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)
/ argMinIf(toFloat64(open), window_start, toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-04-01') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS q2_return_pct,
round(argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-06-30') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959), 2) AS h1_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'QQQ', 'DIA', 'IWM')
AND window_start >= toDateTime('2026-01-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')
GROUP BY ticker
ORDER BY tickerLa répartition sur deux trimestres définit la structure du semestre : SPY -5.2% puis 14.1% ; QQQ -6.9% puis 26.5%. L'IWM a été le leader discret du semestre à 21.3% — les small caps ont surperformé tous les indices large-cap sur les six mois. Le détail trimestriel est disponible dans le récapitulatif du Q2. Note sur l'arithmétique des semestres : le rendement de 8.8% du SPY sur six mois est bien inférieur à celui du seul Q2, car le semestre enchaîne un drawdown et une reprise — la capitalisation de -5.2% et 14.1% correspond aux données du tableau, et tout titre annonçant un « rendement semestriel » intègre implicitement ce cycle complet.
La performance de la première moitié face à toutes les autres
Une 8.8% est-elle inhabituelle ? Les panneaux ci-dessous recalculent le MÊME rendement de la première moitié — de l'ouverture à la clôture en horaires réguliers, de janvier à juin — pour chaque année de l'historique en minutes. Le calcul est identique pour chaque année, effectué via une requête par paire d'ETF. Ces résultats sont ensuite classés par rapport au reste de l'historique. La date la plus ancienne de la série en minutes est vérifiée dans la méthodologie ci-dessous ; la première première moitié complète disponible est celle indiquée par les données.
Le SQL exact derrière chaque chiffre
SELECT toYear(toTimeZone(window_start, 'America/New_York')) AS y,
ticker,
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions,
round((argMax(toFloat64(close), window_start) / argMin(toFloat64(open), window_start) - 1) * 100, 1) AS h1_return_pct
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'QQQ')
AND window_start >= toDateTime('2003-01-01 00:00:00')
AND window_start < toDateTime('2026-07-01 00:00:00')
AND toMonth(toTimeZone(window_start, 'America/New_York')) <= 6
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY y, ticker
HAVING sessions >= 100
ORDER BY y ASC, ticker ASCLe SQL exact derrière chaque chiffre
SELECT ticker,
round(anyIf(ret, y = 2026), 1) AS h1_2026_pct,
arrayCount(x -> x > anyIf(ret, y = 2026), groupArrayIf(ret, y != 2026)) + 1 AS rank_best,
count() AS halves_compared,
min(y) AS first_year,
anyIf(sessions, y = 2026) AS sessions_2026
FROM (
SELECT toYear(toTimeZone(window_start, 'America/New_York')) AS y,
ticker,
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions,
(argMax(toFloat64(close), window_start) / argMin(toFloat64(open), window_start) - 1) * 100 AS ret
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'QQQ')
AND window_start >= toDateTime('2003-01-01 00:00:00')
AND window_start < toDateTime('2026-07-01 00:00:00')
AND toMonth(toTimeZone(window_start, 'America/New_York')) <= 6
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY y, ticker
HAVING sessions >= 100
)
GROUP BY ticker
ORDER BY ticker ASCLe 8.8% de SPY se classe dans le 6 des 23 premières moitiés depuis 2004 (le rang 1 est le meilleur) — il fait partie du tiers supérieur, mais n'est pas un record. Le 18.7% de QQQ se classe dans le 3 des 16 premières moitiés comparables — la série QQQ est plus courte — le fonds a été échangé sous un autre ticker pendant plusieurs années — et toute année comptant moins de cent sessions de première moitié pour un ticker est exclue par une garde de sécurité sur le nombre de sessions visible dans le tableau.
Le SQL exact derrière chaque chiffre
SELECT toYear(toTimeZone(window_start, 'America/New_York')) AS y,
ticker,
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions,
round((argMax(toFloat64(close), window_start) / argMin(toFloat64(open), window_start) - 1) * 100, 1) AS h1_return_pct
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('DIA', 'IWM')
AND window_start >= toDateTime('2003-01-01 00:00:00')
AND window_start < toDateTime('2026-07-01 00:00:00')
AND toMonth(toTimeZone(window_start, 'America/New_York')) <= 6
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY y, ticker
HAVING sessions >= 100
ORDER BY y ASC, ticker ASCLe SQL exact derrière chaque chiffre
SELECT ticker,
round(anyIf(ret, y = 2026), 1) AS h1_2026_pct,
arrayCount(x -> x > anyIf(ret, y = 2026), groupArrayIf(ret, y != 2026)) + 1 AS rank_best,
count() AS halves_compared,
min(y) AS first_year,
anyIf(sessions, y = 2026) AS sessions_2026
FROM (
SELECT toYear(toTimeZone(window_start, 'America/New_York')) AS y,
ticker,
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions,
(argMax(toFloat64(close), window_start) / argMin(toFloat64(open), window_start) - 1) * 100 AS ret
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('DIA', 'IWM')
AND window_start >= toDateTime('2003-01-01 00:00:00')
AND window_start < toDateTime('2026-07-01 00:00:00')
AND toMonth(toTimeZone(window_start, 'America/New_York')) <= 6
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY y, ticker
HAVING sessions >= 100
)
GROUP BY ticker
ORDER BY ticker ASCLa ligne des petites capitalisations est l'élément principal : IWM se classe dans le 1 des 23 premières moitiés depuis 2004 — c'est la meilleure performance enregistrée pour le fonds, devant toutes les moitiés de reprise du tableau. Le 8.4% de DIA se classe dans le 4 des 23. La base, expliquée simplement : rendement de l'ouverture à la clôture en horaires réguliers pour chaque première moitié de l'année civile, calcul identique pour chaque année, et limite supérieure fixée à la fin de cette période afin que l'échantillon de comparaison ne s'élargisse pas lors de l'intégration des années suivantes.
Mois par mois
Le SQL exact derrière chaque chiffre
SELECT toString(toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York')))) AS period_start, ticker,
round((argMaxIf(toFloat64(close), window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) / argMinIf(toFloat64(open), window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS month_return_pct,
round(argMaxIf(toFloat64(close), window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959), 2) AS month_close
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'QQQ')
AND window_start >= toDateTime('2026-01-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')
GROUP BY period_start, ticker
ORDER BY period_start, tickerLa tendance suit un mouvement en escalier : une légère hausse, puis des baisses, une forte remontée, une nouvelle hausse, et enfin une légère baisse. Avril a marqué le pivot du semestre (SPY 9.9%, QQQ 14.8% — le meilleur mois de l'année pour le QQQ), et le mois de juin s'est clôturé calmement à -1.2% pour le SPY. Le récapitulatif de juin, incluant la répartition de la breadth derrière ce chiffre stable, est disponible ici. Analyse du tableau mois par mois : l'année a débuté presque à l'équilibre (SPY 0.9% en janvier), a reculé en février (-0.5%) et en mars (-4.2%), puis avril a inversé la tendance en un seul mois, mai l'a accentuée (4.9%), et juin a ralenti la progression. Trois mois sur six étaient négatifs — un équilibre parfait pour un semestre qui finit solidement positif. C'est la structure habituelle des semestres sur actions, un point important à garder en tête lorsqu'un seul mois semble dicter une tendance.
Taux : l'ensemble de la courbe, par échéance
La courbe des taux du Treasury a connu une torsion plutôt qu'un déplacement. Le segment ultra-court — les maturités les plus sensibles à la politique monétaire — a peu bougé ; le taux à deux ans a progressé de deux tiers de point de pourcentage ; le taux à trente ans a été quasiment immobile. Le panel présente l'ensemble de la courbe, comparant le début et la fin du semestre.
Le SQL exact derrière chaque chiffre
SELECT maturity, start_pct, end_pct, round((end_pct - start_pct) * 100, 0) AS change_bp FROM (
SELECT '1-month' AS maturity, (SELECT round(argMin(yield_1_month, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_1_month)) AS start_pct, (SELECT round(argMax(yield_1_month, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_1_month)) AS end_pct, 1 AS o
UNION ALL SELECT '3-month', (SELECT round(argMin(yield_3_month, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_3_month)), (SELECT round(argMax(yield_3_month, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_3_month)), 2
UNION ALL SELECT '1-year', (SELECT round(argMin(yield_1_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_1_year)), (SELECT round(argMax(yield_1_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_1_year)), 3
UNION ALL SELECT '2-year', (SELECT round(argMin(yield_2_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_2_year)), (SELECT round(argMax(yield_2_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_2_year)), 4
UNION ALL SELECT '5-year', (SELECT round(argMin(yield_5_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_5_year)), (SELECT round(argMax(yield_5_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_5_year)), 5
UNION ALL SELECT '10-year', (SELECT round(argMin(yield_10_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_10_year)), (SELECT round(argMax(yield_10_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_10_year)), 6
UNION ALL SELECT '30-year', (SELECT round(argMin(yield_30_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_30_year)), (SELECT round(argMax(yield_30_year, date), 2) FROM global_markets.treasury_yields WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30') AND isNotNull(yield_30_year)), 7
) ORDER BY oEn lisant la colonne des variations de haut en bas, la torsion est évidente : le taux à un mois a évolué de -2 points de base en six mois, tandis que le taux à deux ans a augmenté de 67 et le taux à trente ans de seulement 5. Un déplacement parallèle fait bouger toutes les maturités de concert ; ce semestre a déplacé le milieu de la courbe et immobilisé les deux extrémités — les taux courts sont restés ancrés près de la politique monétaire, les taux longs ont peu été reprécisés.
Impact sur la pente
Le SQL exact derrière chaque chiffre
SELECT
round((argMin(yield_10_year - yield_2_year, date)) * 100, 0) AS start_bp,
round((argMax(yield_10_year - yield_2_year, date)) * 100, 0) AS end_bp,
round(min((yield_10_year - yield_2_year)) * 100, 0) AS min_bp,
count() AS prints
FROM global_markets.treasury_yields
WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30')
AND isNotNull(yield_10_year) AND isNotNull(yield_2_year)L'accélération de la partie courte par rapport à la partie longue définit l'aplatissement : le spread 2s10s est passé de 72 à 30 points de base sur l'ensemble des publications de 124. Son niveau le plus bas sur le semestre était de 27, la courbe s'étant aplatie sans jamais s'inverser. Déterminer si un aplatissement de la courbe est prédictif de l'évolution future relève de la prévision, et ce tableau ne propose pas de prévisions.
Le SQL exact derrière chaque chiffre
SELECT toString(date) AS d, round((yield_10_year - yield_2_year) * 100, 0) AS spread_2s10s_bp
FROM global_markets.treasury_yields
WHERE date >= toDate('2026-01-01') AND date <= toDate('2026-06-30')
AND isNotNull(yield_10_year) AND isNotNull(yield_2_year)
ORDER BY dateLa série quotidienne montre que l'aplatissement n'a pas été un événement isolé mais un processus graduel — les publications de 124 ont diminué tout au long du semestre, le spread passant de 72 points de base en début d'année à 30 en fin de période.
Secteurs : la dispersion cachée par l'indice
Quelles parties du marché ont réellement généré les gains du semestre ? Les onze ETF sectoriels SPDR, répartis entre le premier et le second semestre, en une seule requête.
Le SQL exact derrière chaque chiffre
SELECT ticker,
round((argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-06-30') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)
/ argMinIf(toFloat64(open), window_start, toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-01-01') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS h1_return_pct,
round((argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-03-31') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)
/ argMinIf(toFloat64(open), window_start, toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-01-01') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS q1_return_pct,
round((argMaxIf(toFloat64(close), window_start, toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-06-30') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)
/ argMinIf(toFloat64(open), window_start, toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2026-04-01') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS q2_return_pct,
round(sumIf(toFloat64(close) * toFloat64(volume), (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) / 1e9, 1) AS h1_dollar_bn
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('XLB', 'XLC', 'XLE', 'XLF', 'XLI', 'XLK', 'XLP', 'XLRE', 'XLU', 'XLV', 'XLY')
AND window_start >= toDateTime('2026-01-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')
GROUP BY ticker
ORDER BY tickerLa dispersion est l'élément clé : le secteur technologique (XLK) a terminé le semestre en hausse de 30.8% — avec un 42% deuxième trimestre — tandis que les services de communication (XLC) ont terminé à -9.3%, soit un spread d'environ quarante points de pourcentage entre le meilleur et le pire secteur sur six mois. Détenir « le marché » revenait à détenir ces deux extrêmes. L'énergie (XLE) illustre les risques liés aux cycles longs : XLE affiche un 18.8% sain — construit sur un 36.9% premier trimestre suivi d'un -11% deuxième. C'était le secteur large le plus performant lors du trimestre de baisse des indices, et l'un des plus faibles lors du trimestre de reprise. Les services financiers (XLF) ont suivi une trajectoire inverse : -9.9% au premier trimestre, puis 7.7% au deuxième. Un chiffre unique pour le premier semestre lisse ces mouvements de va-et-vient ; la répartition par trimestre offre une vision fidèle.
Le coût de transaction par secteur
Les tableaux de rendement sont omniprésents, contrairement aux flux de cotations. Ce panel mesure le spread bid-ask médian de chaque ETF sectoriel sur une session complète — 123 sessions sur le semestre, la session du 29 juin étant celle mesurée ici — à partir de chaque mise à jour du NBBO de la journée.
Le SQL exact derrière chaque chiffre
SELECT ticker,
round(quantileDeterministicIf(0.5)((toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2) * 10000, toUInt64(toUnixTimestamp64Micro(sip_timestamp)), bid_price > 0 AND ask_price >= bid_price), 2) AS med_spread_bps,
round(count() / 1e6, 2) AS quote_updates_m,
countIf(NOT (bid_price > 0 AND ask_price > 0 AND ask_price >= bid_price)) AS invalid_dropped
FROM global_markets.cache_stocks_quotes
WHERE ticker IN ('XLB', 'XLC', 'XLE', 'XLF', 'XLI', 'XLK', 'XLP', 'XLRE', 'XLU', 'XLV', 'XLY')
AND sip_timestamp >= toDateTime64('2026-06-29 13:30:00', 9) AND sip_timestamp < toDateTime64('2026-06-29 20:00:00', 9)
GROUP BY ticker
ORDER BY med_spread_bpsChacune des onze cotations présente un spread de quelques points de base ou moins — le plus faible étant de 0.62 bps (XLV) et le plus élevé de 2.23 bps (XLRE) — ce qui définit concrètement la liquidité des ETF sectoriels : le coût pour prendre une position sur un secteur se mesure en centièmes de pour cent. Pour comparaison avec les actions individuelles, l'analyse approfondie du 29 juin montre que le spread d'un titre peu liquide est des centaines de fois supérieur à ces niveaux sur la même session.
La largeur du marché sur le semestre
La largeur du marché à l'échelle semestrielle présente deux niveaux de lecture. Le niveau macro : le SPY a enregistré 64 de séances en hausse contre 59 de séances en baisse sur les 123 du semestre — soit presque une chance sur deux, malgré un semestre nettement positif, ce qui caractérise une progression lente et constante sur le graphique quotidien. Le niveau micro — incluant chaque ticker — s'observe à l'échelle mensuelle : la répartition advancer/decliner de juin est disponible dans le récapitulatif de juin (plus de tickers ont baissé que de tickers ont progressé), et le décompte à la fin du trimestre est dans le récapitulatif du Q2. Un scan complet des advancers sur six mois dépasse le budget de requête généré par cette page ; cette limite est indiquée ici plutôt que d'être appliquée silencieusement.
Le SQL exact derrière chaque chiffre
SELECT countIf(day_ret > 0) AS up_sessions,
countIf(day_ret < 0) AS down_sessions,
countIf(day_ret = 0) AS flat_sessions,
count() AS sessions_total
FROM (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS d,
round((argMax(toFloat64(close), window_start) / argMin(toFloat64(open), window_start) - 1) * 100, 2) AS day_ret
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND window_start >= toDateTime('2026-01-01 00:00:00')
AND window_start < toDateTime('2026-07-01 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 d
)Le flux des options, mois par mois
Ce qu'un bilan semestriel peut montrer : l'évolution du flux des options. Chaque panneau ci-dessous correspond à un scan complet du flux pour un mois donné — le volume total de contrats et la part échangée lors de son propre jour d'expiration (0DTE). Le constat est le suivant : le volume est passé de 1316.1 millions de contrats en janvier à 1477.9 millions en juin — le mois le plus actif du semestre — et la part des contrats expirant le jour même est passée de 26.5% en janvier à 34.3% en juin, le mois le plus élevé du semestre. Un tiers du volume d'options de juin a été échangé sur des contrats expirant le jour même.
Le SQL exact derrière chaque chiffre
SELECT round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm,
round(100.0 * sumIf(toFloat64(volume), toDateOrNull(concat('20', substring(ticker, length(ticker) - 14, 6))) = toDate(toTimeZone(window_start, 'America/New_York'))) / sum(toFloat64(volume)), 1) AS zero_dte_pct,
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions
FROM global_markets.options_minute_aggs
WHERE window_start >= toDateTime('2026-01-01 00:00:00')
AND window_start < toDateTime('2026-02-01 00:00:00')Le SQL exact derrière chaque chiffre
SELECT round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm,
round(100.0 * sumIf(toFloat64(volume), toDateOrNull(concat('20', substring(ticker, length(ticker) - 14, 6))) = toDate(toTimeZone(window_start, 'America/New_York'))) / sum(toFloat64(volume)), 1) AS zero_dte_pct,
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions
FROM global_markets.options_minute_aggs
WHERE window_start >= toDateTime('2026-02-01 00:00:00')
AND window_start < toDateTime('2026-03-01 00:00:00')Le SQL exact derrière chaque chiffre
SELECT round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm,
round(100.0 * sumIf(toFloat64(volume), toDateOrNull(concat('20', substring(ticker, length(ticker) - 14, 6))) = toDate(toTimeZone(window_start, 'America/New_York'))) / sum(toFloat64(volume)), 1) AS zero_dte_pct,
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions
FROM global_markets.options_minute_aggs
WHERE window_start >= toDateTime('2026-03-01 00:00:00')
AND window_start < toDateTime('2026-04-01 00:00:00')Le SQL exact derrière chaque chiffre
SELECT round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm,
round(100.0 * sumIf(toFloat64(volume), toDateOrNull(concat('20', substring(ticker, length(ticker) - 14, 6))) = toDate(toTimeZone(window_start, 'America/New_York'))) / sum(toFloat64(volume)), 1) AS zero_dte_pct,
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions
FROM global_markets.options_minute_aggs
WHERE window_start >= toDateTime('2026-04-01 00:00:00')
AND window_start < toDateTime('2026-05-01 00:00:00')Le SQL exact derrière chaque chiffre
SELECT round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm,
round(100.0 * sumIf(toFloat64(volume), toDateOrNull(concat('20', substring(ticker, length(ticker) - 14, 6))) = toDate(toTimeZone(window_start, 'America/New_York'))) / sum(toFloat64(volume)), 1) AS zero_dte_pct,
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions
FROM global_markets.options_minute_aggs
WHERE window_start >= toDateTime('2026-05-01 00:00:00')
AND window_start < toDateTime('2026-06-01 00:00:00')Le SQL exact derrière chaque chiffre
SELECT round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm,
round(100.0 * sumIf(toFloat64(volume), toDateOrNull(concat('20', substring(ticker, length(ticker) - 14, 6))) = toDate(toTimeZone(window_start, 'America/New_York'))) / sum(toFloat64(volume)), 1) AS zero_dte_pct,
uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) AS sessions
FROM global_markets.options_minute_aggs
WHERE window_start >= toDateTime('2026-06-01 00:00:00')
AND window_start < toDateTime('2026-07-01 00:00:00')Le coût de transaction, échantillonné mensuellement
Le SQL exact derrière chaque chiffre
SELECT toDate(toTimeZone(sip_timestamp, 'America/New_York')) AS session,
round(quantileDeterministicIf(0.5)((toFloat64(ask_price) - toFloat64(bid_price)) / ((toFloat64(ask_price) + toFloat64(bid_price)) / 2) * 10000, toUInt64(toUnixTimestamp64Micro(sip_timestamp)), bid_price > 0 AND ask_price >= bid_price), 3) AS med_spread_bps,
round(count() / 1e6, 2) AS quote_updates_m,
countIf(NOT (bid_price > 0 AND ask_price > 0 AND ask_price >= bid_price)) AS invalid_dropped
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'SPY'
AND ((sip_timestamp >= toDateTime64('2026-01-14 14:30:00', 9) AND sip_timestamp < toDateTime64('2026-01-14 21:00:00', 9))
OR (sip_timestamp >= toDateTime64('2026-02-11 14:30:00', 9) AND sip_timestamp < toDateTime64('2026-02-11 21:00:00', 9))
OR (sip_timestamp >= toDateTime64('2026-03-11 13:30:00', 9) AND sip_timestamp < toDateTime64('2026-03-11 20:00:00', 9))
OR (sip_timestamp >= toDateTime64('2026-04-15 13:30:00', 9) AND sip_timestamp < toDateTime64('2026-04-15 20:00:00', 9))
OR (sip_timestamp >= toDateTime64('2026-05-13 13:30:00', 9) AND sip_timestamp < toDateTime64('2026-05-13 20:00:00', 9))
OR (sip_timestamp >= toDateTime64('2026-06-10 13:30:00', 9) AND sip_timestamp < toDateTime64('2026-06-10 20:00:00', 9)))
GROUP BY session
ORDER BY session ASCLe spread médian coté du SPY le deuxième mercredi de chaque mois : 0.145 bps pour l'échantillon de janvier, 0.144 pour celui de février, environ le double pour les échantillons du printemps, et 0.409 bps pour l'échantillon de juin — le plus élevé des six. Précision sur la base : il s'agit de sessions échantillonnées par étiquetage unique (le deuxième mercredi de chaque mois), et non de médianes mensuelles — un scan complet du tape sur six mois dépasserait le budget de requête de cette page. Les dates de l'échantillon figurent dans le tableau, et les cotations invalides y sont comptabilisées au lieu d'être ignorées.
Les noms notables du semestre
Notoriété mesurée et non éditoriale : l'ensemble ci-dessous représente le haut du classement par volume de transactions en dollars sur le trimestre. Ce classement est recalculé ici pour servir de justificatif à cette page ; chaque nom ayant fait l'objet d'une analyse approfondie renvoie vers celle-ci.
Le SQL exact derrière chaque chiffre
SELECT ticker,
round(sum(toFloat64(close) * toFloat64(volume)) / 1e9, 1) AS dollar_bn,
round(100 * sum(toFloat64(close) * toFloat64(volume)) / max(sum(toFloat64(close) * toFloat64(volume))) OVER (), 1) AS pct_of_leader
FROM global_markets.delayed_stocks_minute_aggs
WHERE window_start >= toDateTime('2026-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
AND ticker NOT IN ('SPCX')
GROUP BY ticker
ORDER BY dollar_bn DESC
LIMIT 8MU a affiché un volume de transactions supérieur à celui du SPY au cours du deuxième trimestre ($2047.5 milliards contre $2032 milliards) — le même constat que celui présenté dans le récapitulatif du Q2. Pour les six titres individuels de ce classement, le semestre :
Le SQL exact derrière chaque chiffre
SELECT ticker,
round((argMaxIf(toFloat64(close), window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)
/ argMinIf(toFloat64(open), window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS h1_return_pct,
round((argMaxIf(toFloat64(close), window_start, (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959)
/ argMinIf(toFloat64(open), window_start, window_start >= toDateTime('2026-04-01 00:00:00') AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) - 1) * 100, 1) AS q2_return_pct,
round(sumIf(toFloat64(close) * toFloat64(volume), (toHour(toTimeZone(window_start, 'America/New_York')) * 60 + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959) / 1e9, 1) AS h1_dollar_bn
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('MU', 'NVDA', 'TSLA', 'SNDK', 'AMD', 'INTC')
AND window_start >= toDateTime('2026-01-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')
GROUP BY ticker
ORDER BY tickerLe secteur de la mémoire et des semi-conducteurs domine le semestre : SNDK a réalisé un rendement de 830.1% en six mois, MU 290% — son analyse détaillée tick par tick est disponible ici — et INTC 269.3%. NVDA, le titre le plus échangé du groupe avec un turnover semestriel de $3287.9 milliards, a affiché un rendement de 5.2% — un chiffre à un seul digit alors que les titres de la mémoire ont multiplié leurs valeurs ; son analyse approfondie de juin détaille cette divergence session par session. TSLA est l'unique valeur déclinante du groupe à -8.2%. La méga-capitalisation de juin s'échange sous un symbole réutilisé et est exclue des scans de leaders en attente de vérification de l'entité — son premier mois fait l'objet d'un article détaillé par session. Base : le SET des leaders est sélectionné selon le volume de dollars en horaires réguliers du Q2 (le scan ci-dessus) ; les colonnes de rendement correspondent au semestre, de l'ouverture de la première séance en horaires réguliers à la clôture de la dernière séance en horaires réguliers.
La vague d'IPO du semestre, mois par mois
Le SQL exact derrière chaque chiffre
SELECT toString(toStartOfMonth(listing_date)) AS m, count() AS listings
FROM global_markets.stocks_ipos
WHERE listing_date >= toDate('2026-01-01') AND listing_date <= toDate('2026-06-30')
GROUP BY m
ORDER BY mLa vague de cotations a été concentrée en début de période et irrégulière : février a été le mois le plus actif du semestre avec 47 introductions en bourse, tandis que mars a été le plus calme avec 17 — la célèbre méga-introduction de juin est survenue lors d'un mois au volume par ailleurs ordinaire (35 introductions).
Le calendrier du semestre
Le SQL exact derrière chaque chiffre
SELECT
(SELECT count() FROM global_markets.stocks_dividends WHERE ex_dividend_date >= toDate('2026-01-01') AND ex_dividend_date <= toDate('2026-06-30')) AS ex_div_events,
(SELECT count() FROM global_markets.stocks_splits WHERE execution_date >= toDate('2026-01-01') AND execution_date <= toDate('2026-06-30')) AS splits,
(SELECT count() FROM global_markets.stocks_ipos WHERE listing_date >= toDate('2026-01-01') AND listing_date <= toDate('2026-06-30')) AS ipos,
(SELECT uniqExact(accession_number) FROM global_markets.stocks_sec_edgar_index WHERE filing_date >= toDate('2026-01-01') AND filing_date <= toDate('2026-06-30')) AS h1_filings,
(SELECT uniqExact(accession_number) FROM global_markets.stocks_sec_edgar_index WHERE filing_date = toDate('2026-03-31')) AS filings_mar31,
(SELECT uniqExact(accession_number) FROM global_markets.stocks_sec_edgar_index WHERE filing_date = toDate('2026-04-30')) AS filings_apr30,
(SELECT uniqExact(accession_number) FROM global_markets.stocks_sec_edgar_index WHERE filing_date = toDate('2026-06-30')) AS filings_jun30205 sociétés ont fait leur entrée en bourse au cours du semestre — une vague de listings dont la plus importante première en juin fait l'objet de son propre article détaillé par reçu — parallèlement à 830 splits et 28356 événements ex-dividend. Pour donner un ordre d'idée, cela représente plus d'une nouvelle cotation par séance de trading sur le semestre. Le total des documents déposés présente une triple anomalie : l'index de la SEC est presque vide à chaque fin de mois du semestre dont le dernier jour calendaire était un jour ouvré (55 dépôts indexés au 31 mars, 34 au 30 avril, et 31 au 30 juin, contre des milliers les jours adjacents), de sorte que les décomptes de dépôts semestriels sont sous-estimés tant que le flux n'est pas mis à jour — l'écart de fin de mois fait l'objet d'une note de diagnostic dédiée.
Le compte rendu de la séance
Le SQL exact derrière chaque chiffre
SELECT
(SELECT uniqExact(toDate(toTimeZone(window_start, 'America/New_York'))) FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY' AND window_start >= toDateTime('2026-01-01 00:00:00') AND window_start < toDateTime('2026-07-01 00:00:00')) AS h1_sessionsNotes sur les données
Notes complètes sur les données
- Le short interest s'arrête au règlement du 15 juin à la date de génération (l'impression de fin juin est en attente — détails complets dans le récapitulatif de juin ; ce post se régénère dès réception).
- Trois jours de dépôt d'index de fin de mois pour 2026 sont presque vides (31 mars, 30 avril, 30 juin — chaque fin de mois du semestre dont le dernier jour calendaire était un jour ouvré) ; les données sont divulguées avec les décomptes, comme expliqué dans la note sur l'écart de fin de mois. Les fins de mois de l'année précédente comportent des milliers de dépôts, il s'agit donc d'un écart de flux et non d'un jour férié de dépôt.
- Le classement à l'échelle de la moitié est limité : un scan de l'ensemble du marché sur six mois dépasse le budget de requête généré par cette page ; l'ensemble des noms notables est choisi selon le scan du leader à l'échelle trimestrielle affiché ci-dessous, et les rendements du semestre sont calculés pour ce groupe fixe — la base est précisée là où elle est utilisée. Les récapitulatifs du Q2 et de juin contiennent les tableaux complets des leaders à leurs échelles respectives.
- La largeur du marché total à l'échelle de la moitié est également limitée — la répartition par jour est affichée ; les décomptes par ticker sont disponibles aux échelles mensuelle et trimestrielle, via le lien dans la section de largeur de marché.
- La série historique du QQQ est plus courte que celle du SPY : le fonds a été négocié sous un autre symbole racine pendant plusieurs années ; la limite du nombre de sessions exclut visiblement ces années (le nombre de sessions par année figure dans le tableau).
- Les six panneaux d'options sont des scans mensuels de l'intégralité du tape et l'échantillon de tendance du spread utilise une session étiquetée par mois — les deux fonctionnent via le chemin de traitement par lots ; les bases d'échantillonnage sont précisées dans le texte.
- La microstructure est détaillée dans le détail approfondi du 29 juin.
Méthodologie
- La période s'étend du 1er janvier au 30 juin 2026 — 123 sessions, vérifiées à partir des bougies observées. Les rendements sont calculés de l'ouverture à la clôture de la séance régulière pour chaque fenêtre, selon les mêmes requêtes affichées.
- Les comparaisons historiques sont recalculées en temps réel sur l'historique complet en minutes lors de la génération — les valeurs stockées ne sont jamais utilisées. Vérification de la profondeur : la date de la première bougie en minutes de la vue différée utilisée ici correspond à celle de la table de base (septembre 2003), vérifiée lors de la rédaction ; ainsi, la première moitié complète disponible est celle de 2004. Chaque requête d'historique fixe sa limite supérieure à la fin de cette période (l'ensemble de comparaison ne peut pas s'étendre lors de l'intégration des années suivantes) et applique une garde minimale de sessions avec le nombre de sessions par an affiché.
- Les horodatages sont stockés en UTC avec des limites UTC brutes. Les blocs d'historique pluriannuels filtrent les heures régulières selon l'heure de l'Est (9:30–15:59, convertie par ligne — la seule convention compatible avec le passage à l'heure d'été sur plusieurs décennies) ; les blocs à fenêtre unique dans les plages uniquement en EDT utilisent la bande UTC brute équivalente. Les deux conventions sont précisées ici.
- La génération s'effectue via le chemin de lecture seule sécurisé ; la page publique n'interroge jamais les données en direct. État de l'entrepôt au 5 juillet 2026.
Il s'agit de la première édition du récapitulatif semestriel permanent ; l'édition annuelle suivra en janvier. Détail par trimestre : T2 2026. Les publications macroéconomiques servant de base au comparatif se trouvent dans le panorama macro.