Strasmore Research
Обучение Matt ConnorАвтор: Matt Connor

Что такое индекс High-Low и как он работает

Индекс High-Low представляет собой десятидневное среднее значение процента новых максимумов. Узнайте формулу расчета на простых числах и риски использования малых выборок.

Индекс High-Low — это показатель рыночной широты, основанный на двух значениях: 10-дневном простом скользящем среднем процента новых максимумов (Record High Percent). Процент новых максимумов — это количество новых 52-недельных максимумов, деленное на сумму новых 52-недельных максимумов и новых 52-недельных минимумов, умноженное на 100. Значение выше 50 означает, что количество акций, обновивших максимумы, превышает количество акций, обновивших минимумы; значение ниже 50 указывает на обратное. Формула предельно проста. Ниже приведен расчет в округленных числах и описание изъяна выборки, из-за которого убедительно выглядящий показатель может опираться лишь на горстку акций.

Как рассчитывается индекс High-Low?

Два шага, каждый из которых умещается в одну строку.

  1. Процент новых максимумов (Record High Percent) для одной сессии: подсчитайте количество акций в вашей выборке, закрывшихся на новом 52-недельном максимуме, и количество акций, закрывшихся на новом 52-недельном минимуме. Разделите число максимумов на сумму этих двух значений, затем умножьте на 100.
  2. Индекс High-Low: усредните последние 10 ежедневных значений процента новых максимумов.

Округленные числа делают расчет наглядным. На ленте зафиксировано 90 новых максимумов и 30 новых минимумов. Сумма максимумов и минимумов равна 120; 90, деленное на 120, дает 0,75, значит, процент новых максимумов за эту сессию равен 75. Теперь возьмем десять сессий: 75, 70, 65, 60, 55, 50, 45, 40, 35 и 30. Их сумма составляет 525, а 525, деленное на 10, дает 52,5. Индекс High-Low равен 52,5 в день, когда процент новых максимумов составил 75.

Этот разрыв — результат работы скользящего среднего. Десятидневная «память» сглаживает ряд, который может за ночь измениться от 100 до 0, ценой запоздалой реакции. Индекс показывает, какой была широта рынка в течение двух недель. Он не отвечает на вопрос, что произошло сегодня днем.

Что считается новым 52-недельным максимумом?

Акция достигает нового 52-недельного максимума, когда ее цена превышает любую цену, зафиксированную за предыдущие 52 недели. Поставщики данных расходятся в методологии: одни сравнивают внутридневные максимумы и минимумы, другие — только цены закрытия, что дает разные результаты для одной и той же сессии. На этой странице везде используются цены закрытия. Новые 52-недельные максимумы и минимумы содержит сам список.

В приведенной ниже панели подсчитаны оба экстремума для фиксированной корзины из 40 крупных американских компаний за период с 1 апреля по 31 июля 2026 года. Такой размер корзины позволяет легко проверить расчеты вручную, что позже сделает очевидным изъян в формуле.

ЗапросНовые 52-недельные максимумы и минимумы за сессию: 40 крупных компаний США, апрель–июль 2026 г.
Точный SQL-код для каждого числа
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_date
Run this yourself

За 77 сессий эти два показателя редко растут одновременно. Jul 29, в последнюю сессию периода, 3 из 40 бумаг закрылись на 52-недельном максимуме, а 0 — на 52-недельном минимуме. Apr 1, в первую сессию, соотношение составило 1 максимумов к 1 минимумам. Все остальные бумаги в корзине остались внутри своего диапазона и не попали в расчет.

Какое значение индекса High-Low считается хорошим?

Отметка 50 является точкой равновесия между максимумами и минимумами. Общепринятым индикатором силы является уровень 70, где новые максимумы превышают новые минимумы более чем в два раза в среднем за 10 дней. Общепринятый индикатор слабости — зеркальная отметка 30. В диапазоне от 30 до 70 индекс указывает на смешанные рыночные экстремумы, где он и находится большую часть времени.

На графике ниже представлен необработанный ежедневный процент новых максимумов в сравнении с его 10-дневным средним для той же корзины. Лаг (задержка) виден на графике, а не описан словами.

ЗапросПроцент рекордных максимумов (RHP) и его 10-дневное скользящее среднее (индекс High-Low), корзина из 40 акций
Точный SQL-код для каждого числа
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_date
Run this yourself

Отображаемый диапазон начинается с процента новых максимумов 100 на Apr 15, при значении индекса 52.5. Он заканчивается на 100 на Jul 29, индекс 64. Сравнивайте каждое значение с отметками 70 и 30, а расстояние между двумя линиями воспринимайте как цену сглаживания: в любой день среднее значение все еще учитывает девять предыдущих сессий. Первые девять сессий периода исключены из панели, так как для 10-дневного среднего нужно 10 дней.

Знаменатель игнорирует большую часть рынка

Вот ограничение, которое важно учитывать. Знаменатель процента новых максимумов — это новые максимумы плюс новые минимумы, и ничего больше. Акция, находящаяся в середине своего 52-недельного диапазона, не попадает ни в числитель, ни в знаменатель. Индекс не может отличить сессию, где 900 из 3000 бумаг достигли экстремума, от той, где это сделали 9 бумаг, и в обоих случаях выдает уверенное двузначное число.

Представьте биржу с 6000 бумаг в спокойную августовскую сессию: 40 акций обновили максимумы, 20 — минимумы. Процент новых максимумов равен 40, деленным на 60, то есть 66,7, что выглядит как широкий рост. Это значение вычислено на основе 1% листингов. Остальные 5940 бумаг не участвовали в голосовании.

Корзина из 40 бумаг наглядно демонстрирует это. Каждая сессия в периоде распределена по корзинам в зависимости от того, сколько бумаг достигли какого-либо экстремума.

ЗапросВлияние сокращения знаменателя: распределение сессий по количеству акций на 52-недельных экстремумах
Точный SQL-код для каждого числа
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_denominator
Run this yourself

В 39 сессиях в корзине 1 to 3 names весь показатель основывался в среднем на 2 бумагах из 40. Медианный процент новых максимумов в этих сессиях составил 100, а отклонение от отметки 50 — 50 пунктов. В 10 or more names сессиях, 1 из которых пришлись на среднее значение 10 бумаг, медианное значение составило 70, а отклонение от центра — 20 пунктов.

Арифметика ограничивает возможности «тонкой» сессии. Если экстремума достигли три бумаги, возможные значения — только 0, 33,3, 66,7 и 100. Если две бумаги — только 0, 50 и 100. Значение 66,7, полученное на основе двух максимумов и одного минимума, содержит десятичную дробь, которую выборка не может обосновать. Правильная привычка: всегда смотрите на необработанные данные о количестве максимумов и минимумов рядом с индексом, а не только на сам индекс.

Рыночная широта: индекс High-Low против линии «рост/падение»

Оба показателя оценивают участие акций. Они делают это на разных временных горизонтах. Широта по линии «рост/падение» (advance/decline) учитывает каждую бумагу, которая закрылась выше или ниже вчерашнего дня. Ее знаменатель — вся совокупность акций, и она описывает один день. Индекс High-Low учитывает только бумаги на 52-недельном экстремуме. Его знаменатель мал, и он описывает положение цен относительно годовой истории. Лента может быть широко растущей в течение дня, в то время как лишь немногие бумаги находятся вблизи 52-недельного максимума.

На панели ниже оба показателя сглажены за те же 10 сессий по той же корзине, что позволяет привести их к одной шкале.

ЗапросДва показателя рыночного охвата для одной корзины: 10-дневный индекс High-Low против 10-дневной доли растущих акций
Точный SQL-код для каждого числа
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_date
Run this yourself

Пара начинает отображаемый диапазон с 52.5 для индекса High-Low и 52.8 для 10-дневной доли растущих акций на Apr 15, и заканчивает на 64 и 52.5 на Jul 29, за 68 сессий. Доля растущих акций находится в узком диапазоне. Примерно половина корзины закрывается ростом в обычную сессию, и усреднение десяти таких дней оставляет линию около середины шкалы. У индекса High-Low нет такого якоря. Когда ни одна бумага в корзине не обновляет 52-недельный минимум в течение десяти сессий подряд, каждое ежедневное значение равно 100, и среднее значение также равно 100.

Широту рынка лучше оценивать вместе с показателями участия. Относительный объем показывает, торгуется ли бумага сегодня необычно активно по сравнению с собственной нормой. Крупнейшие ценовые движения недели показывает, какие бумаги действительно совершили значительное движение, а акции с необычным объемом на этой неделе — где сосредоточились торги.

Часто задаваемые вопросы об индексе High-Low

Что означает значение индекса High-Low выше 70?

Это означает, что новые 52-недельные максимумы превысили новые 52-недельные минимумы более чем в два раза в среднем за последние десять сессий. Это общепринятый индикатор сильного рынка. Он ничего не говорит о том, сколько именно акций достигли экстремума, поэтому это число нужно проверять параллельно.

В чем разница между процентом новых максимумов и индексом High-Low?

Процент новых максимумов — это показатель за одну сессию: новые максимумы, деленные на сумму новых максимумов и новых минимумов, умноженные на 100. Индекс High-Low — это 10-дневное простое скользящее среднее этого показателя. Один описывает сегодняшний день. Другой описывает последние две недели.

Может ли индекс High-Low быть равен 0 или 100?

Да. Если ни одна акция в выборке не обновляет 52-недельный минимум в течение десяти сессий подряд, каждое ежедневное значение равно 100, как и среднее. Когда ни одна акция не обновляет ни максимум, ни минимум, знаменатель дроби равен нулю, и для этой сессии значение индекса не определено.

Является ли индекс High-Low тем же самым, что и широта по линии «рост/падение»?

Нет. Широта «рост/падение» использует в знаменателе всю совокупность акций и описывает направление одного дня. Индекс High-Low использует в знаменателе небольшую группу акций на 52-недельных экстремумах и описывает положение относительно цен за год.

Сколько акций обычно входит в знаменатель индекса High-Low?

В корзине из 40 бумаг, измеренной здесь с апреля по июль 2026 года, сессии в корзине 1 to 3 names имели в среднем 2 бумаг в знаменателе. В масштабах всей биржи абсолютные значения выше, но они все равно остаются лишь малой частью всех листингов, поэтому необработанные данные должны быть на экране рядом с индексом.


Каждый подсчет на этой странице является сохраненным версионированным запросом по ценам закрытия. Откройте любую панель, чтобы прочитать SQL-код, лежащий в ее основе, или создайте ту же серию широты рынка на собственной корзине в терминале Strasmore.

#market breadth#52-week highs#indicators#record high percent