Strasmore Research
Навчання Matt ConnorВід Matt Connor

Що таке High-Low Index та ринкова ширина

High-Low Index є десятиденним середнім показником Record High Percent. Ознайомтеся з розрахунком на круглих числах та особливостями аналізу вибірки під час низької активності.

High-Low Index — це показник ринкової ширини, що базується на двох значеннях: 10-денному простому ковзному середньому відсотка нових максимумів (Record High Percent). Своєю чергою, Record High Percent — це кількість нових 52-тижневих максимумів, поділена на суму нових 52-тижневих максимумів і нових 52-тижневих мінімумів, помножена на 100. Значення вище 50 означає, що більше акцій оновлюють максимуми, ніж мінімуми, а значення нижче 50 — навпаки. Формула досить лаконічна. Нижче наведено арифметику на круглих числах та опис недоліку вибірки, через який показник може виглядати переконливо, базуючись лише на кількох акціях.

Як розрахувати High-Low Index?

Два кроки, кожен з яких вміщується в один рядок.

  1. Record High Percent для однієї сесії: підрахуйте кількість акцій у вашому всесвіті, що закрилися на новому 52-тижневому максимумі, підрахуйте ті, що закрилися на новому 52-тижневому мінімумі, поділіть кількість максимумів на суму цих двох значень, а потім помножте на 100.
  2. High-Low Index: обчисліть середнє значення за останні 10 щоденних показників Record High Percent.

Круглі числа роблять це наочним. На стрічці зафіксовано 90 нових максимумів і 30 нових мінімумів. Сума максимумів і мінімумів становить 120, а 90, поділене на 120, дорівнює 0,75, отже Record High Percent для цієї сесії становить 75. Тепер візьмемо десять сесій: 75, 70, 65, 60, 55, 50, 45, 40, 35 і 30. Їхня сума дорівнює 525, а 525, поділене на 10, становить 52,5. High-Low Index дорівнює 52,5 у день, коли власний Record High Percent становив 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 Index вважається хорошим?

Позначка 50 є точкою розвороту, де максимуми та мінімуми перебувають у рівновазі. Загальноприйнятим маркером сили є 70, де нові максимуми перевищують нові мінімуми більш ніж удвічі в середньому за 10 днів. Загальноприйнятий маркер слабкості — 30, його дзеркальне відображення. Між 30 і 70 індекс вказує на те, що ринкові екстремуми змішані, і саме в цьому діапазоні він перебуває більшу частину часу.

На панелі нижче відображено необроблений щоденний Record High Percent порівняно з його 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

Побудований діапазон починається з Record High Percent на рівні 100 Apr 15, при цьому індекс становить 52.5. Він завершується на рівні 100 Jul 29, індекс 64. Порівнюйте кожне значення з маркерами 70 і 30, а відстань між двома лініями сприймайте як ціну згладжування: у будь-який день середнє значення все ще враховує дев’ять попередніх сесій. Перші дев’ять сесій вікна виключені з панелі, оскільки для 10-денного середнього потрібно 10 днів.

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

Ось обмеження, яке варто запам’ятати. Знаменник Record High Percent — це лише сума нових максимумів і нових мінімумів. Акція, що перебуває посередині свого 52-тижневого діапазону, не потрапляє ні в чисельник, ні в знаменник. Індекс не може розрізнити сесію, де 900 з 3000 назв досягли екстремуму, від тієї, де це зробили 9 назв, і в обох випадках видає однакове впевнене двозначне число.

Уявіть біржу з 6000 назв під час млявої серпневої сесії: 40 акцій оновлюють максимуми, 20 — мінімуми. Record High Percent дорівнює 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. Ці сесії мали медіанний Record High Percent 100 і перебували на медіанній відстані 50 пунктів від лінії 50. 10 or more names сесій, 1 з яких мали в середньому 10 назв, мали медіану 70 і перебували на відстані 20 пунктів від середини.

Арифметика обмежує те, що може показати «тонка» сесія. Якщо лише три назви досягли екстремуму, можливі лише значення 0, 33,3, 66,7 і 100. Якщо дві назви — лише 0, 50 і 100. Значення 66,7, побудоване на двох максимумах і одному мінімумі, містить десяткову частину, яку вибірка не може підтвердити. Правило, що виправляє це, просте: дивіться на необроблені дані максимумів і мінімумів поруч з індексом, а не лише на сам індекс.

Ринкова ширина: High-Low Index проти показника «зростання/падіння»

Обидва показники оцінюють рівень участі акцій. Вони роблять це на різних часових горизонтах. Ширина «зростання/падіння» (advance/decline) підраховує кожну назву, яка закрилася вище або нижче вчорашнього рівня. Її знаменник — це весь всесвіт, і вона описує один день. High-Low Index підраховує лише назви на 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 Index і 52.8 для 10-денної частки акцій, що зростають, Apr 15, і завершує на 64 та 52.5 Jul 29, охоплюючи 68 побудованих сесій. Частка акцій, що зростають, живе у вузькому діапазоні. Приблизно половина кошика закривається вище під час звичайної сесії, і усереднення десяти таких днів залишає лінію поблизу середини шкали. High-Low Index не має такого якоря. Коли жодна назва в кошику не оновлює 52-тижневий мінімум протягом десяти сесій поспіль, кожне щоденне значення дорівнює 100, і середнє значення також дорівнює 100.

Ширина ринку краще читається з показниками участі поруч. Відносний обсяг показує, чи торгується акція сьогодні незвично активно порівняно зі своєю нормою. Найбільші рухи акцій за тиждень показує, які назви дійсно змінили ціну, а акції з незвичним обсягом цього тижня показує, куди спрямувалися торги.

FAQ щодо High-Low Index

Що означає значення High-Low Index вище 70?

Це означає, що нові 52-тижневі максимуми перевищили нові 52-тижневі мінімуми більш ніж удвічі в середньому за останні десять сесій. Це загальноприйнятий маркер сильного ринку. Він нічого не говорить про те, скільки акцій взагалі досягли екстремуму, тому це число варто перевіряти паралельно.

У чому різниця між Record High Percent та High-Low Index?

Record High Percent — це показник однієї сесії: нові максимуми, поділені на суму нових максимумів і нових мінімумів, помножені на 100. High-Low Index — це 10-денне просте ковзне середнє цього показника. Один описує сьогоднішній день. Інший описує останні два тижні.

Чи може High-Low Index дорівнювати 0 або 100?

Так. Якщо жодна акція у всесвіті не оновлює 52-тижневий мінімум протягом десяти сесій поспіль, кожне щоденне значення дорівнює 100, як і середнє. Коли жодна акція не оновлює ні максимум, ні мінімум, дріб має нульовий знаменник, і для цієї сесії значення не визначене.

Чи є High-Low Index тим самим, що й ширина «зростання/падіння»?

Ні. Ширина «зростання/падіння» ділиться на весь всесвіт і описує один день напрямку. High-Low Index ділиться на малу групу акцій, що перебувають на 52-тижневих екстремумах, і описує позицію відносно річної історії цін.

Скільки акцій зазвичай у знаменнику High-Low Index?

У кошику з 40 назв, виміряному тут з квітня по липень 2026 року, сесії в кошику 1 to 3 names мали в середньому 2 назв у знаменнику. Загальноринкові підрахунки більші в абсолютних цифрах, але залишаються тонким зрізом усіх лістингів, тому необроблені дані мають бути на екрані поруч із індексом.


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

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