Indice High-Low : définition et calcul du breadth
L’indice High-Low est la moyenne sur 10 jours du Record High Percent. Formule, exemple chiffré et biais de taille d’échantillon sur un marché calme.
L’indice High-Low est un indicateur de breadth construit à partir de deux décomptes : il correspond à la moyenne mobile simple sur 10 jours du Record High Percent, lui-même égal au nombre de nouveaux plus-hauts sur 52 semaines divisé par la somme des nouveaux plus-hauts et des nouveaux plus-bas sur 52 semaines, multiplié par 100. Une valeur supérieure à 50 signifie que davantage d’actions inscrivent de nouveaux plus-hauts que de nouveaux plus-bas. En dessous de 50, c’est l’inverse. La formule est aussi courte. La suite détaille le calcul avec des chiffres arrondis, ainsi que le biais lié à la taille de l’échantillon, qui permet à une valeur apparemment décisive de reposer sur une poignée d’actions.
Comment calcule-t-on l’indice High-Low ?
Deux étapes, chacune tenant sur une ligne.
- Record High Percent, pour une séance donnée : comptez les actions de votre univers qui ont clôturé sur un nouveau plus-haut à 52 semaines, puis celles qui ont clôturé sur un nouveau plus-bas à 52 semaines. Divisez le nombre de plus-hauts par la somme des deux, puis multipliez par 100.
- L’indice High-Low : calculez la moyenne des dix dernières valeurs quotidiennes de Record High Percent.
Les chiffres arrondis rendent le calcul concret. Une séance compte 90 nouveaux plus-hauts et 30 nouveaux plus-bas. La somme est de 120, et 90 divisé par 120 donne 0,75. Le Record High Percent de la séance est donc de 75. Prenons maintenant dix valeurs : 75, 70, 65, 60, 55, 50, 45, 40, 35 et 30. Leur somme est de 525, et 525 divisé par 10 donne 52,5. L’indice High-Low s’établit à 52,5 lors d’une séance où le Record High Percent est lui-même de 75.
Cet écart est le coût du lissage. Dix jours de mémoire atténuent les variations d’une série qui peut passer de 100 à 0 en une nuit, au prix d’un signal plus tardif. L’indice indique le niveau de la breadth sur deux semaines. Il ne dit jamais ce qui s’est passé cet après-midi.
Qu’est-ce qui constitue un nouveau plus-haut à 52 semaines ?
Une action inscrit un nouveau plus-haut à 52 semaines lorsque son cours dépasse tous les cours enregistrés au cours des 52 semaines précédentes. Les fournisseurs de données ne retiennent pas tous la même base : certains comparent les plus-hauts et plus-bas intraday, tandis que d’autres comparent uniquement les cours de clôture. Les deux méthodes produisent des décomptes différents pour une même séance. Les cours de clôture servent de base partout sur cette page. Nouveaux plus-hauts et plus-bas à 52 semaines détaille la liste elle-même.
Le panneau ci-dessous décompte les deux extrêmes à chaque séance pour un panier fixe de 40 grandes capitalisations américaines, du 1er avril au 31 juillet 2026. Un panier de cette taille maintient les décomptes à un niveau vérifiable manuellement. C’est ce qui rend ensuite le biais de la formule visible.
Le SQL exact derrière chaque chiffre
WITH daily_close AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS session_date,
argMax(close, window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('AAPL','MSFT','NVDA','AMZN','GOOGL','AVGO','JPM','JNJ','XOM','PG',
'KO','PEP','WMT','HD','CVX','MRK','PFE','ABBV','CSCO','ORCL',
'CRM','ADBE','MCD','NKE','VZ','T','DIS','BA','CAT','GE',
'IBM','MMM','UNH','LLY','COST','TGT','SBUX','GS','MS','LIN')
AND window_start >= toDateTime('2025-03-01 00:00:00')
AND window_start < toDateTime('2026-08-01 05:00:00')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY ticker, session_date
),
extremes AS (
SELECT cur.ticker AS ticker,
cur.session_date AS session_date,
cur.close_px AS close_px,
max(hist.close_px) AS high_52w,
min(hist.close_px) AS low_52w
FROM daily_close AS cur
INNER JOIN daily_close AS hist ON cur.ticker = hist.ticker
WHERE cur.session_date >= toDate('2026-04-01')
AND hist.session_date <= cur.session_date
AND hist.session_date > cur.session_date - 364
GROUP BY cur.ticker, cur.session_date, cur.close_px
),
daily AS (
SELECT session_date,
countIf(close_px >= high_52w) AS new_highs,
countIf(close_px <= low_52w) AS new_lows,
countIf(close_px >= high_52w) + countIf(close_px <= low_52w) AS names_at_extreme
FROM extremes
GROUP BY session_date
HAVING names_at_extreme > 0
)
SELECT session_date AS date,
formatDateTimeInJodaSyntax(session_date, 'MMM d') AS session_label,
new_highs,
new_lows
FROM daily
ORDER BY session_dateSur 77 séances, les deux décomptes augmentent rarement ensemble. Le Jul 29, dernière séance de la période, 3 des 40 titres ont clôturé sur un plus-haut à 52 semaines et 0 sur un plus-bas à 52 semaines. Le Apr 1, première séance, la répartition était de 1 plus-hauts contre 1 plus-bas. Tous les autres titres du panier se situaient à l’intérieur de leur propre fourchette et n’entraient pas dans le calcul.
Qu’est-ce qu’une bonne valeur de l’indice High-Low ?
Le seuil de 50 constitue le pivot, lorsque les plus-hauts et les plus-bas sont équilibrés. Le seuil conventionnel d’un marché fort est 70. Il signifie que les nouveaux plus-hauts ont dépassé les nouveaux plus-bas selon un ratio supérieur à deux pour un sur l’ensemble de la moyenne mobile de 10 jours. Le seuil conventionnel d’un marché faible est 30, son symétrique. Entre 30 et 70, l’indice indique que les extrêmes du marché sont partagés. C’est dans cette zone qu’il se situe la plupart du temps.
Le panneau ci-dessous représente le Record High Percent quotidien brut par rapport à sa propre moyenne mobile sur 10 jours pour le même panier. Le décalage apparaît directement sur le graphique.
Le SQL exact derrière chaque chiffre
WITH daily_close AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS session_date,
argMax(close, window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('AAPL','MSFT','NVDA','AMZN','GOOGL','AVGO','JPM','JNJ','XOM','PG',
'KO','PEP','WMT','HD','CVX','MRK','PFE','ABBV','CSCO','ORCL',
'CRM','ADBE','MCD','NKE','VZ','T','DIS','BA','CAT','GE',
'IBM','MMM','UNH','LLY','COST','TGT','SBUX','GS','MS','LIN')
AND window_start >= toDateTime('2025-03-01 00:00:00')
AND window_start < toDateTime('2026-08-01 05:00:00')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY ticker, session_date
),
extremes AS (
SELECT cur.ticker AS ticker,
cur.session_date AS session_date,
cur.close_px AS close_px,
max(hist.close_px) AS high_52w,
min(hist.close_px) AS low_52w
FROM daily_close AS cur
INNER JOIN daily_close AS hist ON cur.ticker = hist.ticker
WHERE cur.session_date >= toDate('2026-04-01')
AND hist.session_date <= cur.session_date
AND hist.session_date > cur.session_date - 364
GROUP BY cur.ticker, cur.session_date, cur.close_px
),
daily AS (
SELECT session_date,
countIf(close_px >= high_52w) AS new_highs,
countIf(close_px >= high_52w) + countIf(close_px <= low_52w) AS names_at_extreme
FROM extremes
GROUP BY session_date
HAVING names_at_extreme > 0
),
rhp AS (
SELECT session_date,
round(100 * new_highs / names_at_extreme, 1) AS record_high_pct
FROM daily
),
smoothed AS (
SELECT session_date,
record_high_pct,
round(avg(record_high_pct) OVER (ORDER BY session_date
ROWS BETWEEN 9 PRECEDING AND CURRENT ROW), 1) AS high_low_index_pct,
count() OVER (ORDER BY session_date
ROWS BETWEEN 9 PRECEDING AND CURRENT ROW) AS sessions_in_window
FROM rhp
)
SELECT session_date AS date,
formatDateTimeInJodaSyntax(session_date, 'MMM d') AS session_label,
record_high_pct,
high_low_index_pct
FROM smoothed
WHERE sessions_in_window = 10
ORDER BY session_dateLa période représentée commence avec un Record High Percent de 100 le Apr 15, et un indice à 52.5. Elle se termine à 100 le Jul 29, avec un indice à 64. Comparez chaque valeur aux seuils de 70 et 30. Considérez l’écart entre les deux lignes comme le coût du lissage : chaque jour, la moyenne intègre encore neuf séances plus anciennes. Les neuf premières séances de la période sont exclues du panneau, car une moyenne sur 10 jours nécessite 10 séances.
Le dénominateur ignore la majeure partie du marché
Voici la limite à retenir. Le dénominateur du Record High Percent correspond aux nouveaux plus-hauts plus les nouveaux plus-bas, et à rien d’autre. Une action située au milieu de sa fourchette sur 52 semaines n’entre ni dans le numérateur ni dans le dénominateur. L’indice ne peut pas distinguer une séance durant laquelle 900 titres sur 3 000 atteignent un extrême d’une séance durant laquelle 9 titres seulement le font. Il affiche les deux situations avec le même nombre à deux chiffres, en apparence précis.
Prenons une Bourse de 6 000 titres lors d’une séance calme d’août : 40 actions inscrivent un nouveau plus-haut et 20 un nouveau plus-bas. Le Record High Percent est égal à 40 divisé par 60, soit 66,7. Cette valeur suggère une hausse généralisée. Pourtant, le calcul repose sur 1 % des titres cotés. Les 5 940 autres n’ont pas participé au calcul.
Le panier de 40 titres permet de visualiser cette limite avec des nombres faciles à décompter. Chaque séance de la période est classée selon le nombre de titres ayant inscrit un extrême, quel qu’il soit.
Le SQL exact derrière chaque chiffre
WITH daily_close AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS session_date,
argMax(close, window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('AAPL','MSFT','NVDA','AMZN','GOOGL','AVGO','JPM','JNJ','XOM','PG',
'KO','PEP','WMT','HD','CVX','MRK','PFE','ABBV','CSCO','ORCL',
'CRM','ADBE','MCD','NKE','VZ','T','DIS','BA','CAT','GE',
'IBM','MMM','UNH','LLY','COST','TGT','SBUX','GS','MS','LIN')
AND window_start >= toDateTime('2025-03-01 00:00:00')
AND window_start < toDateTime('2026-08-01 05:00:00')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY ticker, session_date
),
extremes AS (
SELECT cur.ticker AS ticker,
cur.session_date AS session_date,
cur.close_px AS close_px,
max(hist.close_px) AS high_52w,
min(hist.close_px) AS low_52w
FROM daily_close AS cur
INNER JOIN daily_close AS hist ON cur.ticker = hist.ticker
WHERE cur.session_date >= toDate('2026-04-01')
AND hist.session_date <= cur.session_date
AND hist.session_date > cur.session_date - 364
GROUP BY cur.ticker, cur.session_date, cur.close_px
),
daily AS (
SELECT session_date,
countIf(close_px >= high_52w) AS new_highs,
countIf(close_px >= high_52w) + countIf(close_px <= low_52w) AS names_at_extreme
FROM extremes
GROUP BY session_date
HAVING names_at_extreme > 0
)
SELECT multiIf(names_at_extreme <= 3, '1 to 3 names',
names_at_extreme <= 9, '4 to 9 names',
'10 or more names') AS sample_size_bucket,
count() AS readings,
round(avg(names_at_extreme), 1) AS avg_names_in_denominator,
round(quantileDeterministic(0.5)(100 * new_highs / names_at_extreme,
cityHash64(session_date)), 1) AS median_record_high_pct,
round(quantileDeterministic(0.5)(abs(100 * new_highs / names_at_extreme - 50),
cityHash64(session_date)), 1) AS median_distance_from_50
FROM daily
GROUP BY sample_size_bucket
ORDER BY avg_names_in_denominatorSur les 39 séances du compartiment 1 to 3 names, la valeur affichée reposait entièrement sur une moyenne de 2 titres sur 40. Ces séances affichaient un Record High Percent médian de 100 et se situaient à une distance médiane de 50 points du seuil de 50. Les 10 or more names séances, dont 1 avec une moyenne de 10 titres, affichaient une valeur médiane de 70 et se situaient à 20 points du milieu.
Le calcul limite aussi les valeurs qu’une séance peu participative peut afficher. Avec trois titres à un extrême, les seules valeurs possibles sont 0, 33,3, 66,7 et 100. Avec deux titres, seules 0, 50 et 100 sont possibles. Une valeur de 66,7 fondée sur deux plus-hauts et un plus-bas comporte une décimale que la taille de son échantillon ne permet pas de justifier. La règle pratique est simple : lisez les décomptes bruts des plus-hauts et des plus-bas à côté de l’indice. Ne consultez jamais l’indice seul.
Breadth de marché : indice High-Low contre advance/decline
Les deux indicateurs mesurent la participation des actions. Ils le font sur des horizons différents. La breadth advance/decline compte chaque titre qui a terminé la séance en hausse ou en baisse par rapport à la veille. Son dénominateur est l’ensemble de l’univers, et elle décrit une seule journée. L’indice High-Low compte uniquement les titres situés sur un extrême à 52 semaines. Son dénominateur est réduit, et il décrit la position des cours par rapport à une année d’historique. Le marché peut progresser largement sur la séance alors que très peu de titres se trouvent près d’un plus-haut à 52 semaines.
Le panneau ci-dessous lisse les deux indicateurs sur les mêmes 10 séances et sur le même panier. Ils sont ainsi placés sur une échelle commune.
Le SQL exact derrière chaque chiffre
WITH daily_close AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS session_date,
argMax(close, window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('AAPL','MSFT','NVDA','AMZN','GOOGL','AVGO','JPM','JNJ','XOM','PG',
'KO','PEP','WMT','HD','CVX','MRK','PFE','ABBV','CSCO','ORCL',
'CRM','ADBE','MCD','NKE','VZ','T','DIS','BA','CAT','GE',
'IBM','MMM','UNH','LLY','COST','TGT','SBUX','GS','MS','LIN')
AND window_start >= toDateTime('2025-03-01 00:00:00')
AND window_start < toDateTime('2026-08-01 05:00:00')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY ticker, session_date
),
extremes AS (
SELECT cur.ticker AS ticker,
cur.session_date AS session_date,
cur.close_px AS close_px,
max(hist.close_px) AS high_52w,
min(hist.close_px) AS low_52w
FROM daily_close AS cur
INNER JOIN daily_close AS hist ON cur.ticker = hist.ticker
WHERE cur.session_date >= toDate('2026-04-01')
AND hist.session_date <= cur.session_date
AND hist.session_date > cur.session_date - 364
GROUP BY cur.ticker, cur.session_date, cur.close_px
),
daily AS (
SELECT session_date,
countIf(close_px >= high_52w) AS new_highs,
countIf(close_px >= high_52w) + countIf(close_px <= low_52w) AS names_at_extreme
FROM extremes
GROUP BY session_date
HAVING names_at_extreme > 0
),
prior AS (
SELECT ticker,
session_date,
close_px,
lagInFrame(close_px, 1) OVER (PARTITION BY ticker ORDER BY session_date
ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_close
FROM daily_close
),
breadth AS (
SELECT session_date,
round(100 * countIf(close_px > prev_close) / count(), 1) AS advancing_pct
FROM prior
WHERE session_date >= toDate('2026-04-01')
AND prev_close > 0
GROUP BY session_date
HAVING count() >= 20
),
combined AS (
SELECT d.session_date AS session_date,
round(100 * d.new_highs / d.names_at_extreme, 1) AS record_high_pct,
b.advancing_pct AS advancing_pct
FROM daily AS d
INNER JOIN breadth AS b ON d.session_date = b.session_date
),
smoothed AS (
SELECT session_date,
round(avg(record_high_pct) OVER (ORDER BY session_date
ROWS BETWEEN 9 PRECEDING AND CURRENT ROW), 1) AS high_low_index_pct,
round(avg(advancing_pct) OVER (ORDER BY session_date
ROWS BETWEEN 9 PRECEDING AND CURRENT ROW), 1) AS advancing_pct_10d,
count() OVER (ORDER BY session_date
ROWS BETWEEN 9 PRECEDING AND CURRENT ROW) AS sessions_in_window
FROM combined
)
SELECT session_date AS date,
formatDateTimeInJodaSyntax(session_date, 'MMM d') AS session_label,
high_low_index_pct,
advancing_pct_10d
FROM smoothed
WHERE sessions_in_window = 10
ORDER BY session_dateLa période représentée commence à 52.5 pour l’indice High-Low et à 52.8 pour la part des titres en hausse sur 10 jours, le Apr 15. Elle se termine à 64 et 52.5 le Jul 29, sur 68 séances représentées. La part des titres en hausse évolue dans une fourchette étroite. Lors d’une séance ordinaire, environ la moitié du panier clôture en hausse. La moyenne de dix séances maintient donc la ligne près du milieu de l’échelle. L’indice High-Low ne dispose d’aucun point d’ancrage comparable. Si aucun titre du panier n’inscrit de nouveau plus-bas à 52 semaines pendant dix séances consécutives, chaque valeur quotidienne est de 100, et la moyenne l’est également.
La breadth est plus utile lorsqu’elle est analysée avec des indicateurs de participation. Volume relatif indique si un titre se négocie aujourd’hui avec une activité inhabituellement élevée par rapport à sa propre norme. Les plus fortes variations de la semaine montre quels titres ont réellement évolué, tandis que les actions à volume inhabituel cette semaine indique où les échanges se sont concentrés.
FAQ sur l’indice High-Low
Que signifie une valeur de l’indice High-Low supérieure à 70 ?
Cela signifie que les nouveaux plus-hauts à 52 semaines ont dépassé les nouveaux plus-bas à 52 semaines selon un ratio supérieur à deux pour un sur la moyenne des dix dernières séances. Il s’agit du seuil conventionnel signalant un marché fort. Cette valeur ne dit rien du nombre total de titres ayant atteint un extrême. C’est ce décompte qu’il faut consulter à côté de l’indice.
Quelle est la différence entre le Record High Percent et l’indice High-Low ?
Le Record High Percent est la valeur d’une seule séance : le nombre de nouveaux plus-hauts divisé par le nombre de nouveaux plus-hauts plus les nouveaux plus-bas, multiplié par 100. L’indice High-Low est la moyenne mobile simple sur 10 jours de cette valeur. L’un décrit la séance du jour. L’autre décrit les deux dernières semaines.
L’indice High-Low peut-il être égal à 0 ou à 100 ?
Oui. Si aucune action de l’univers n’inscrit de nouveau plus-bas à 52 semaines pendant dix séances consécutives, chaque valeur quotidienne est de 100 et la moyenne l’est également. Lorsqu’aucune action n’inscrit de plus-haut ni de plus-bas, la fraction a un dénominateur nul et aucune valeur définie n’est disponible pour cette séance.
L’indice High-Low est-il identique à la breadth advance/decline ?
Non. La breadth advance/decline divise par l’ensemble de l’univers et décrit la direction du marché sur une seule journée. L’indice High-Low divise par le petit groupe d’actions situées sur des extrêmes à 52 semaines et décrit leur position par rapport à une année de cours.
Combien d’actions figurent généralement dans le dénominateur de l’indice High-Low ?
Pour le panier de 40 titres mesuré ici d’avril à juillet 2026, les séances du compartiment 1 to 3 names comptaient en moyenne 2 titres dans le dénominateur. Les décomptes à l’échelle d’une Bourse sont plus élevés en valeur absolue, tout en représentant une faible fraction de l’ensemble des titres cotés. C’est pourquoi les décomptes bruts doivent apparaître à côté de l’indice.
Chaque décompte de cette page provient d’une requête stockée et versionnée, fondée sur les cours de clôture. Ouvrez n’importe quel panneau pour consulter le SQL correspondant, ou reconstruisez cette même série de breadth sur votre propre panier dans le terminal Strasmore.