Cos’è l’High-Low Index e come si calcola
L’High-Low Index è la media a 10 giorni del Record High Percent: formula, esempio con numeri arrotondati e rischio di un campione ridotto.
L’High-Low Index è un indicatore di ampiezza del mercato costruito su due conteggi: è la media mobile semplice a 10 giorni del Record High Percent, mentre il Record High Percent è dato dai nuovi massimi a 52 settimane divisi per la somma dei nuovi massimi e dei nuovi minimi a 52 settimane, moltiplicata per 100. Un valore superiore a 50 indica che più titoli stanno segnando nuovi massimi rispetto ai nuovi minimi; un valore inferiore a 50 indica il contrario. La formula è così breve. Di seguito vengono mostrati i calcoli, arrotondati, e il problema della numerosità del campione, che può far poggiare un valore dall’apparenza decisiva su un numero esiguo di titoli.
Come si calcola il High-Low Index?
Due passaggi, entrambi eseguibili in una sola riga.
- Record High Percent, per una singola seduta: conta i titoli del tuo universo che hanno chiuso su un nuovo massimo a 52 settimane e quelli che hanno chiuso su un nuovo minimo a 52 settimane; dividi i massimi per la somma dei due valori e moltiplica per 100.
- High-Low Index: calcola la media delle ultime 10 letture giornaliere del Record High Percent.
Gli esempi con numeri tondi rendono il calcolo più concreto. Il mercato registra 90 nuovi massimi e 30 nuovi minimi. La somma di massimi e minimi è 120, e 90 diviso 120 fa 0,75; il Record High Percent della seduta è quindi 75. Ora prendiamo 10 sedute con queste letture: 75, 70, 65, 60, 55, 50, 45, 40, 35 e 30. La somma è 525 e 525 diviso 10 fa 52,5. L’High-Low Index segna 52,5 in una giornata in cui il Record High Percent della seduta è stato 75.
Questa differenza è il compromesso introdotto dalla media mobile. Dieci giorni di memoria attenuano le oscillazioni di una serie che può passare da 100 a 0 in una sola notte, ma rendono l’indicatore più lento. L’indice mostra come si è evoluta l’ampiezza del mercato nell’arco di due settimane. Non mostra mai che cosa è accaduto nel pomeriggio.
Che cosa conta come nuovo massimo delle ultime 52 settimane?
Un’azione raggiunge un nuovo massimo delle ultime 52 settimane quando il suo prezzo supera tutti i prezzi registrati nelle 52 settimane precedenti. I fornitori di dati adottano criteri diversi: alcuni confrontano i massimi e i minimi intraday, altri considerano solo i prezzi di chiusura. I due metodi producono conteggi diversi per la stessa seduta. In questa pagina il criterio è sempre il prezzo di chiusura. Nuovi massimi e minimi delle ultime 52 settimane illustra direttamente l’elenco.
Il pannello seguente conta entrambi gli estremi in ogni seduta per un paniere fisso di 40 large-cap statunitensi, dal primo aprile al 31 luglio 2026. Un paniere di queste dimensioni mantiene i conteggi abbastanza contenuti da poter essere verificati manualmente. È proprio questo che rende evidente più avanti il difetto della formula.
L'esatto SQL dietro ogni numero
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_dateNelle 77 sedute, i due conteggi raramente aumentano insieme. In Jul 29, l’ultima seduta dell’intervallo, 3 dei 40 titoli ha chiuso su un massimo delle ultime 52 settimane e 0 ha chiuso su un minimo delle ultime 52 settimane. In Apr 1, la prima seduta, il rapporto era di 1 massimi contro 1 minimi. Tutti gli altri titoli del paniere si trovavano all’interno del proprio intervallo e non sono mai entrati nel calcolo.
Qual è un buon valore dell’High-Low Index?
La linea a 50 è il punto di equilibrio, con massimi e minimi bilanciati. Il livello convenzionale che segnala una situazione forte è 70: nell’intera media mobile a 10 giorni, i nuovi massimi hanno superato i nuovi minimi con un rapporto superiore a two-to-one. Il livello convenzionale che segnala una situazione debole è 30, il suo opposto. Tra 30 e 70, l’indice indica che gli estremi del mercato sono misti. È l’intervallo in cui si trova per la maggior parte del tempo.
Il pannello seguente mette a confronto il Record High Percent giornaliero grezzo con la relativa media mobile a 10 giorni per lo stesso paniere. Il ritardo è visibile nel grafico e non viene descritto.
L'esatto SQL dietro ogni numero
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_dateL’intervallo rappresentato inizia con un Record High Percent pari a 100 il Apr 15, mentre l’indice è a 52.5. Si conclude a 100 il Jul 29, con l’indice a 64. Leggi ciascun valore rispetto ai livelli 70 e 30 e considera la distanza tra le due linee come il prezzo dello smoothing: in un determinato giorno, la media include ancora nove sedute precedenti. Le prime nove sedute della finestra sono escluse dal pannello, perché una media a 10 giorni richiede 10 giorni.
Il denominatore ignora gran parte del mercato
Questa è la limitazione da tenere presente. Il denominatore del Record High Percent è dato dai nuovi massimi più i nuovi minimi, e da nient’altro. Un titolo fermo nella parte centrale del proprio intervallo a 52 settimane non rientra né nel numeratore né nel denominatore. L’indice non distingue una seduta in cui 900 dei 3.000 titoli raggiungono un estremo da una in cui lo fanno 9 titoli, e rappresenta entrambi i casi con lo stesso sicuro numero a due cifre.
Immaginiamo un listino con 6.000 titoli durante una seduta di agosto caratterizzata da scambi ridotti: 40 titoli segnano nuovi massimi e 20 segnano nuovi minimi. Il Record High Percent è 40 diviso 60, cioè 66,7, un valore che sembra indicare un rialzo ampio. Il calcolo si basa sull’1% dei titoli quotati. Gli altri 5.940 titoli non hanno espresso alcun voto.
Il paniere di 40 titoli rende questo aspetto misurabile. Ogni seduta della finestra viene assegnata a una fascia in base al numero di titoli che hanno raggiunto un estremo qualsiasi.
L'esatto SQL dietro ogni numero
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_denominatorNelle 39 sedute della fascia 1 to 3 names, il dato complessivo si basava su una media di 2 titoli su 40. In queste sedute il Record High Percent ha registrato una mediana pari a 100 e si è collocato a una distanza mediana di 50 punti dalla linea del 50. Le 10 or more names sedute, 1 delle quali con una media di 10 titoli, hanno registrato una mediana pari a 70 e si sono collocate a 20 punti dal valore centrale.
L’aritmetica limita anche i valori che una seduta con pochi titoli può esprimere. Con tre titoli su un estremo, gli unici valori possibili sono 0, 33,3, 66,7 e 100. Con due titoli, sono possibili solo 0, 50 e 100. Un valore di 66,7 costruito su due nuovi massimi e un nuovo minimo contiene una cifra decimale che il campione non può sostenere. La regola per evitare questo problema è semplice: leggere i conteggi grezzi dei nuovi massimi e dei nuovi minimi accanto all’indice, senza considerare mai l’indice da solo.
Ampiezza di mercato: indice High-Low e advance/decline
Entrambe le misure valutano quanti titoli partecipano al movimento. Lo fanno però su orizzonti diversi. L’ampiezza advance/decline conta ogni titolo che ha chiuso al rialzo o al ribasso rispetto a ieri. Il denominatore è l’intero universo e la misura descrive una sola seduta. L’indice High-Low conta invece solo i titoli su un estremo delle ultime 52 settimane. Il denominatore è ridotto e la misura indica dove si collocano i prezzi rispetto a un intero anno di storia. Un mercato può salire ampiamente nella seduta, mentre pochissimi titoli si trovano vicino a un nuovo massimo delle ultime 52 settimane.
Il pannello seguente rende più omogenee entrambe le misure sulle stesse 10 sedute e sullo stesso paniere, riportandole sulla stessa scala.
L'esatto SQL dietro ogni numero
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 coppia apre l’intervallo rappresentato a 52.5 per l’indice High-Low e a 52.8 per la quota di titoli in rialzo a 10 giorni su Apr 15, e lo chiude a 64 e 52.5 su Jul 29, nell’arco di 68 sedute rappresentate. La quota di titoli in rialzo si muove in una banda ristretta. In una seduta ordinaria, circa metà del paniere chiude al rialzo; la media su dieci sedute mantiene quindi la linea vicino al centro della scala. L’indice High-Low non ha invece un riferimento analogo. Quando nessun titolo del paniere registra un nuovo minimo delle ultime 52 settimane per dieci sedute consecutive, ogni lettura giornaliera è pari a 100 e anche la media resta a 100.
L’ampiezza di mercato si interpreta meglio affiancandola a misure della partecipazione. Il volume relativo indica se oggi un titolo è scambiato con un’intensità insolitamente elevata rispetto alla propria norma. I titoli con i maggiori movimenti della settimana mostra quali titoli hanno effettivamente registrato gli spostamenti più ampi, mentre i titoli con volumi insoliti questa settimana indica dove si sono concentrati gli scambi.
Domande frequenti sull’High-Low Index
Che cosa significa una lettura dell’High-Low Index superiore a 70?
Significa che, considerando la media delle ultime dieci sedute, i nuovi massimi a 52 settimane hanno superato i nuovi minimi a 52 settimane con un rapporto superiore a two-to-one. È il livello convenzionalmente associato a un mercato molto forte. Non indica quanti titoli abbiano effettivamente raggiunto un estremo. Questo è il dato da verificare insieme all’indice.
Qual è la differenza tra Record High Percent e High-Low Index?
Record High Percent è il dato della singola seduta: nuovi massimi divisi per la somma di nuovi massimi e nuovi minimi, moltiplicata per 100. L’High-Low Index è la media mobile semplice a 10 giorni di quel dato. Il primo descrive la seduta odierna. Il secondo descrive le ultime due settimane.
L’High-Low Index può essere pari a 0 o 100?
Sì. Se nessun titolo dell’universo raggiunge un nuovo minimo a 52 settimane per dieci sedute consecutive, ogni lettura giornaliera è pari a 100 e lo è anche la media. Quando nessun titolo raggiunge un nuovo massimo o un nuovo minimo, la frazione ha denominatore pari a zero e per quella seduta non esiste una lettura definita.
L’High-Low Index è uguale all’ampiezza advance/decline?
No. L’ampiezza advance/decline divide per l’intero universo e descrive la direzione di una singola seduta. L’High-Low Index divide per il gruppo ristretto di titoli che si trovano agli estremi delle ultime 52 settimane e descrive la posizione rispetto ai prezzi dell’ultimo anno.
Quanti titoli rientrano normalmente nel denominatore dell’High-Low Index?
Nel paniere di 40 titoli analizzato qui da aprile a luglio 2026, le sedute nella fascia 1 to 3 names hanno registrato in media 2 titoli nel denominatore. I conteggi sull’intero listino sono più elevati in termini assoluti, ma restano una quota ridotta di tutte le quotazioni. Per questo i conteggi grezzi devono comparire sullo schermo accanto all’indice.
Ogni conteggio riportato in questa pagina proviene da una query archiviata e versionata sui prezzi di chiusura. Apri un pannello per leggere il codice SQL sottostante oppure ricostruisci la stessa serie di ampiezza su un paniere personalizzato nel terminale Strasmore.