High-Low Index: cos’è e come si calcola
Scopri la formula dell’High-Low Index, la media a 10 giorni del Record High Percent, con esempi arrotondati e il rischio di un campione ridotto.
L’High-Low Index è una misura dell’ampiezza di mercato costruita su due conteggi: è la media mobile semplice a 10 giorni del Record High Percent, e il Record High Percent è dato dai nuovi massimi a 52 settimane divisi per la somma di nuovi massimi e nuovi minimi a 52 settimane, moltiplicata per 100. Un valore superiore a 50 indica che sono più numerosi i titoli che stanno registrando nuovi massimi rispetto a quelli che registrano nuovi minimi; sotto 50 vale il contrario. La formula è così breve. Di seguito sono riportati i calcoli con numeri arrotondati e il problema della numerosità del campione, che permette a un valore dall’aspetto decisivo di poggiare su pochi titoli.
Come si calcola l’High-Low Index?
Due passaggi, entrambi contenuti in una riga.
- Record High Percent per una singola seduta: conta i titoli del tuo universo che hanno chiuso su un nuovo massimo a 52 settimane, conta 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 degli ultimi 10 valori giornalieri del Record High Percent.
I numeri arrotondati rendono il calcolo concreto. Il mercato registra 90 nuovi massimi e 30 nuovi minimi. Massimi più minimi fanno 120, e 90 diviso 120 fa 0,75; il Record High Percent della seduta è quindi 75. Ora considera dieci sedute con questi valori: 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 è quindi pari a 52,5 in una giornata in cui il Record High Percent della seduta è stato 75.
Questa differenza è il costo della media mobile. Dieci giorni di memoria attenuano una serie che può passare da 100 a 0 da un giorno all’altro, ma introducono un ritardo. L’indice indica come si è comportata l’ampiezza nell’arco di due settimane. Non indica mai che cosa è successo nel pomeriggio.
Che cosa conta come nuovo massimo a 52 settimane?
Un titolo segna un nuovo massimo a 52 settimane quando il suo prezzo supera ogni prezzo registrato nelle 52 settimane precedenti. I fornitori di dati adottano criteri diversi: alcuni confrontano i massimi e i minimi intraday, altri considerano soltanto i prezzi di chiusura, e i due metodi producono conteggi diversi per la stessa seduta. In questa pagina si utilizzano ovunque i prezzi di chiusura. Nuovi massimi e minimi a 52 settimane illustra direttamente l’elenco.
Il pannello seguente conta entrambi gli estremi per ogni seduta, su un paniere fisso di 40 titoli USA a larga capitalizzazione, dal primo aprile al 31 luglio 2026. Un paniere di queste dimensioni mantiene i conteggi abbastanza ridotti da poter essere verificati a mano. È questo che rende visibile più avanti il problema 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 della finestra, 3 dei 40 titoli ha chiuso su un massimo a 52 settimane e 0 ha chiuso su un minimo a 52 settimane. In Apr 1, la prima seduta, il confronto era di 1 massimi contro 1 minimi. Tutti gli altri titoli del paniere si trovavano all’interno del proprio intervallo e non sono entrati nel calcolo.
Qual è un buon valore dell’High-Low Index?
La soglia di 50 è il punto di equilibrio, con massimi e minimi bilanciati. Il livello convenzionalmente forte è 70: nella media mobile a 10 giorni, i nuovi massimi hanno superato i nuovi minimi con un rapporto superiore a two-to-one. Il livello convenzionalmente debole è 30, l’immagine speculare. Tra 30 e 70 l’indice indica che gli estremi del mercato sono misti, condizione nella quale si trova per la maggior parte del tempo.
Il pannello seguente rappresenta il Record High Percent giornaliero rispetto alla sua media mobile a 10 giorni, sullo stesso paniere. Il ritardo è visibile nel grafico, senza bisogno di descriverlo.
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. Confronta ciascun valore con le soglie 70 e 30 e considera la distanza tra le due linee come il costo della stabilizzazione: in ogni giornata la media incorpora 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 la maggior parte del mercato
Questa è la limitazione da tenere presente. Il denominatore del Record High Percent è dato dalla somma di nuovi massimi e nuovi minimi, senza 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 titoli su 3.000 raggiungono un estremo da una in cui lo fanno 9 titoli, e assegna a entrambe lo stesso numero a due cifre dall’apparenza sicura.
Immagina un mercato con 6.000 titoli in una seduta fiacca di agosto: 40 titoli segnano nuovi massimi e 20 nuovi minimi. Il Record High Percent è 40 diviso 60, cioè 66,7, un valore che sembra indicare un rialzo ampio. Ma il calcolo si basa sull’1% dei titoli quotati. Gli altri 5.940 non hanno espresso alcun voto.
Il paniere di 40 titoli porta sul grafico una versione quantificabile dello stesso problema. Ogni seduta della finestra viene assegnata a una classe in base al numero di titoli che hanno registrato 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 classe 1 to 3 names, l’intero valore si basava su una media di 2 titoli su 40. In quelle sedute il Record High Percent mediano era 100 e la distanza mediana dalla soglia di 50 era di 50 punti. Le 10 or more names sedute della classe 1, 10 delle quali con una media di 10 titoli, presentavano un valore mediano di 70 e una distanza di 20 punti dal centro.
L’aritmetica limita anche i valori che una seduta con pochi titoli può stampare. Con tre titoli su un estremo, gli unici valori possibili sono 0, 33,3, 66,7 e 100. Con due titoli, soltanto 0, 50 e 100. Un valore di 66,7 costruito su due massimi e un minimo contiene una virgola che il campione non può sostenere. La regola pratica per correggere il problema è semplice: leggi i conteggi grezzi di massimi e minimi accanto all’indice, senza guardare l’indice da solo.
Ampiezza di mercato: High-Low Index contro advance/decline
Entrambe le misure chiedono quanti titoli stanno partecipando al movimento. Lo fanno su orizzonti diversi. L’ampiezza advance/decline conta ogni titolo che ha chiuso in rialzo o in ribasso rispetto al giorno precedente. Il suo denominatore è l’intero universo e la misura descrive una sola giornata. L’High-Low Index conta soltanto i titoli che si trovano su un estremo a 52 settimane. Il suo denominatore è ridotto e la misura descrive la posizione dei prezzi rispetto a un anno intero di storia. Il mercato può salire ampiamente nella giornata mentre pochissimi titoli si avvicinano a un nuovo massimo a 52 settimane.
Il pannello seguente calcola la media mobile di entrambe le misure sulle stesse 10 sedute e sullo stesso paniere, così da riportarle 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’High-Low Index e a 52.8 per la quota dei titoli in rialzo a 10 giorni il Apr 15, e lo chiude a 64 e 52.5 il Jul 29, su 68 sedute rappresentate. La quota dei titoli in rialzo si muove in un intervallo ristretto. In una seduta ordinaria circa metà del paniere chiude in rialzo, e la media di dieci valori mantiene la linea vicino al centro della scala. L’High-Low Index non ha un punto di ancoraggio analogo. Se nessun titolo del paniere registra un nuovo minimo a 52 settimane per dieci sedute consecutive, ogni valore giornaliero è 100 e anche la media è 100.
L’ampiezza di mercato si interpreta meglio affiancandola a misure di partecipazione. Volume relativo indica se oggi un titolo sta scambiando volumi insolitamente elevati rispetto alla propria norma. I titoli con i maggiori movimenti della settimana mostra quali titoli si sono effettivamente mossi, mentre titoli con volumi insoliti questa settimana mostra dove si sono concentrati gli scambi.
Domande frequenti sull’High-Low Index
Che cosa significa un valore dell’High-Low Index superiore a 70?
Significa che, nella 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 forte. Non dice nulla sul numero di titoli che hanno raggiunto un estremo, che deve essere verificato separatamente.
Qual è la differenza tra Record High Percent e High-Low Index?
Il Record High Percent è il valore di una 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 valore. Il primo descrive la giornata corrente. Il secondo descrive le ultime due settimane.
L’High-Low Index può essere 0 o 100?
Sì. Se nessun titolo dell’universo registra un nuovo minimo a 52 settimane per dieci sedute consecutive, ogni valore giornaliero è 100 e lo è anche la media. Se nessun titolo registra né un massimo né un minimo, la frazione ha denominatore zero e per quella seduta non esiste un valore definito.
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 giornata. L’High-Low Index divide per il piccolo gruppo di titoli che si trova su estremi a 52 settimane e descrive la posizione rispetto ai prezzi di un anno.
Quanti titoli rientrano normalmente nel denominatore dell’High-Low Index?
Nel paniere di 40 titoli misurato qui da aprile a luglio 2026, le sedute nella classe 1 to 3 names avevano in media 2 titoli nel denominatore. I conteggi sull’intero mercato sono maggiori in termini assoluti, ma restano una quota ridotta di tutti i titoli quotati. Per questo i conteggi grezzi devono comparire sullo schermo accanto all’indice.
Ogni conteggio di 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 scelto da te nel terminale Strasmore.