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

Anchored VWAP: формула и применение

Anchored VWAP считает среднюю цену с выбранного бара и не сбрасывается. Разбираем формулу на Python и показываем, как перенос якоря меняет результат.

Anchored VWAP — это средневзвешенная по объёму цена, расчёт которой начинается с выбранного вами бара и после этого не сбрасывается. Session VWAP начинается заново при каждом открытии рынка и отвечает только на вопрос, по какой средней цене акция переходила из рук в руки сегодня. Anchored VWAP отвечает на другой вопрос: по какой средней цене акция переходила из рук в руки с выбранного вами момента.

Что такое anchored VWAP?

Обе версии используют одинаковую арифметику. Для каждого бара с начала расчёта умножают цену бара на его объём и ведут накопительный итог. Отдельно ведут накопительный итог объёма. Затем первый показатель делят на второй. Формула anchored VWAP для бара n выглядит так: сумма произведений цены на объём от анкерного бара до бара n, делённая на сумму объёмов за те же бары.

Ценой бара обычно считают типичную цену — среднее его максимума, минимума и цены закрытия. Если поток данных публикует VWAP бара, используют его.

Из этих итогов ничего не удаляется. 50-дневная скользящая средняя исключает самое старое наблюдение при добавлении каждого нового, поэтому может менять направление. Anchored VWAP только накапливает данные, поэтому сохраняет всю историю. Session VWAP использует тот же расчёт, но обнуляет оба итога при каждом открытии рынка. Это anchored VWAP с анкером в момент открытия.

В чём разница между VWAP и anchored VWAP?

На панели ниже обе метрики рассчитаны по дневным барам Apple за один квартал. В столбце session_vwap указана средневзвешенная по объёму цена внутри каждой отдельной сессии — каждый день это новое значение. Столбец anchored_vwap начинается с первой сессии выбранного периода и накапливает данные с этого момента.

ЗапросДневной VWAP с сессии и VWAP с привязкой к одной дате (AAPL)
Точный SQL-код для каждого числа
SELECT
    toString(date)                AS session_date,
    formatDateTime(date, '%b %e') AS bar_label,
    round(toFloat64(vwap), 2)     AS session_vwap,
    round(
        sum(toFloat64(vwap) * toFloat64(volume)) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
      / sum(toFloat64(volume))                   OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
    , 2)                          AS anchored_vwap
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'AAPL'
  AND date >= '2026-04-01'
  AND date <= '2026-06-30'
ORDER BY date
Run this yourself

За 62 сессий, с Apr 1 по Jun 30, дневной ряд движется вместе с рынком, а anchored VWAP меняет наклон медленно. В начале anchored VWAP равен 255.02: в первый день одна сессия составляет всю историю расчёта. К концу периода он достигает 286.86, тогда как итоговый session VWAP равен 288.09. Форма линий показывает главное. Сначала anchored VWAP близок к дневному значению, но затем выравнивается по мере накопления объёма.

Где обычно устанавливают анкер?

Популярные точки — публикация финансовой отчётности, первый бар гэпа, минимум за 52 недели или первый print после листинга акции. Во всех случаях используется одна и та же логика. Все, кто совершал сделки после этого момента, в среднем платили цену anchored VWAP. Поэтому цена выше линии означает, что средний участник имеет нереализованную прибыль.

Есть важный нюанс, о котором обычно не говорят. Выбор анкера субъективен, и результат зависит от него. На панели ниже один и тот же инструмент привязан к началу каждого из последних двенадцати месяцев. Затем рассчитывается средняя цена, уплаченная с этого месяца до одной фиксированной конечной даты.

ЗапросОдна акция и одна последняя цена, двенадцать разных точек привязки (AAPL)
Точный SQL-код для каждого числа
WITH
    monthly AS (
        SELECT
            toStartOfMonth(date)                     AS m,
            sum(toFloat64(vwap) * toFloat64(volume)) AS pv,
            sum(toFloat64(volume))                   AS vol
        FROM global_markets.stocks_daily_aggs
        WHERE ticker = 'AAPL'
          AND date >= '2025-07-01'
          AND date <= '2026-06-30'
        GROUP BY m
    ),
    anchored AS (
        SELECT
            m,
            sum(pv)  OVER (ORDER BY m ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
          / sum(vol) OVER (ORDER BY m ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS avwap
        FROM monthly
    ),
    final_close AS (
        SELECT toFloat64(argMax(close, date)) AS last_close
        FROM global_markets.stocks_daily_aggs
        WHERE ticker = 'AAPL'
          AND date >= '2026-06-01'
          AND date <= '2026-06-30'
    )
SELECT
    formatDateTime(a.m, '%b %Y')                 AS anchor_from,
    round(a.avwap, 2)                            AS anchored_vwap,
    round(100 * (f.last_close / a.avwap - 1), 2) AS close_vs_avwap_pct
FROM anchored AS a
CROSS JOIN final_close AS f
ORDER BY a.m
Run this yourself

При выборе даты Jul 2025 средняя уплаченная цена составляет 259.52. Последняя цена закрытия периода равна 11.5% относительно неё. Значение положительно, если цена закрытия была выше линии. При выборе даты Jun 2026 получаются значения 294.07 и -1.6%. Один и тот же инструмент и одна и та же последняя цена дают двенадцать разных выводов о том, находятся ли держатели с момента анкера в прибыли. Арифметика не выбирает анкер за вас. Анкер, выбранный задним числом, можно перемещать до тех пор, пока он не начнёт подтверждать нужную интерпретацию графика. Поэтому дата анкера должна быть указана в подписи к каждому графику anchored VWAP.

Как рассчитать anchored VWAP в Python?

Оба ряда рассчитываются за один проход по барам. Скрипт ниже написан на Python 3 с использованием только стандартной библиотеки. Пакеты и сетевое подключение не нужны. Скрипт читает тридцать баров, выводит session VWAP рядом с anchored VWAP, а затем сообщает первый бар, на котором цена снова пересекла anchored VWAP. Бары придуманы для демонстрации. Если подставить реальные бары, арифметика не изменится.

"""Session VWAP and anchored VWAP from the same running totals. Standard library only."""
import csv
import io

# Illustrative bars, not market data: three sessions of ten 30 minute bars.
BARS = """bar,price,volume
2026-03-02 09:30,100.40,240000
2026-03-02 10:00,100.90,180000
2026-03-02 10:30,101.30,150000
2026-03-02 11:00,101.10,130000
2026-03-02 11:30,100.60,120000
2026-03-02 12:00,100.20,110000
2026-03-02 12:30,99.80,120000
2026-03-02 13:00,99.50,140000
2026-03-02 13:30,99.70,170000
2026-03-02 14:00,99.40,260000
2026-03-03 09:30,99.10,300000
2026-03-03 10:00,98.70,210000
2026-03-03 10:30,98.90,160000
2026-03-03 11:00,98.40,150000
2026-03-03 11:30,98.10,140000
2026-03-03 12:00,98.30,120000
2026-03-03 12:30,98.80,130000
2026-03-03 13:00,99.20,150000
2026-03-03 13:30,99.60,190000
2026-03-03 14:00,99.90,280000
2026-03-04 09:30,100.20,320000
2026-03-04 10:00,100.60,230000
2026-03-04 10:30,100.90,170000
2026-03-04 11:00,101.40,160000
2026-03-04 11:30,101.20,140000
2026-03-04 12:00,101.60,130000
2026-03-04 12:30,102.10,140000
2026-03-04 13:00,102.40,160000
2026-03-04 13:30,102.20,200000
2026-03-04 14:00,102.60,290000
"""

ANCHOR = "2026-03-02 10:30"   # the bar the anchored series starts on

session_pv = session_vol = 0.0
anchor_pv = anchor_vol = 0.0
current_day = None
anchored = False
start_side = None
crossover = None

print(f"{'bar':<18}{'price':>8}{'session':>10}{'anchored':>10}")

for row in csv.DictReader(io.StringIO(BARS)):
    stamp = row["bar"]
    day, price, vol = stamp[:10], float(row["price"]), float(row["volume"])

    if day != current_day:                  # the session totals reset at every open
        session_pv = session_vol = 0.0
        current_day = day
    session_pv += price * vol
    session_vol += vol
    session_vwap = session_pv / session_vol

    anchored = anchored or stamp == ANCHOR
    if not anchored:
        print(f"{stamp:<18}{price:>8.2f}{session_vwap:>10.2f}{'.':>10}")
        continue

    anchor_pv += price * vol                # the anchored totals never reset
    anchor_vol += vol
    anchored_vwap = anchor_pv / anchor_vol
    print(f"{stamp:<18}{price:>8.2f}{session_vwap:>10.2f}{anchored_vwap:>10.2f}")

    gap = price - anchored_vwap
    if start_side is None and abs(gap) > 1e-9:
        start_side = gap > 0
    elif start_side is not None and crossover is None and (gap > 0) != start_side:
        crossover = stamp

print("first bar back through the anchored VWAP:", crossover or "no crossing here")

Вся логика сводится к двум парам счётчиков. session_pv и session_vol обнуляются при смене даты. anchor_pv и anchor_vol не обнуляются. Всё остальное в скрипте отвечает за вывод.

Почему anchored VWAP перестаёт двигаться

По мере старения anchored VWAP становится менее чувствительным к новым данным по механической причине. Каждый новый бар входит в среднее с весом, равным его объёму, делённому на весь объём с момента анкера. На второй день одна сессия может составлять половину общего объёма. Через двести сессий та же сессия будет иметь вес в доли процента. На панели ниже этот вес рассчитан для баров Apple по блокам из десяти сессий.

ЗапросНасколько новейшая сессия может изменить VWAP с привязкой (AAPL)
Точный SQL-код для каждого числа
WITH running AS (
    SELECT
        row_number() OVER (ORDER BY date) AS n,
        toFloat64(volume)
      / sum(toFloat64(volume)) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS weight
    FROM global_markets.stocks_daily_aggs
    WHERE ticker = 'AAPL'
      AND date >= '2026-01-02'
      AND date <= '2026-06-30'
)
SELECT
    intDiv(n - 1, 10) * 10 + 10 AS bars_since_anchor,
    round(100 * avg(weight), 2) AS newest_bar_weight_pct
FROM running
GROUP BY bars_since_anchor
ORDER BY bars_since_anchor
Run this yourself

В первые десять сессий новый бар в среднем влияет на 30.09% линии, причём анкерный бар сам по себе отвечает за всю величину. К сессии 130 вес нового бара снижается до 2.14%. При чтении таких графиков важно учитывать два вывода. Старый анкер формирует почти плоскую линию, которая слабо реагирует на текущие события. Свежий анкер формирует линию, которая резко меняется вместе с ценой и часто пересекает её. Ни один вариант не является более правильным. Это одна и та же формула на разных этапах накопления данных. Для прямой оценки текущего объёма относительно обычного уровня используются показатели среднего дневного объёма и относительного объёма.

Что показывает anchored VWAP?

Обычно anchored VWAP используют для оценки позиции участников. Если анкер установлен на определённом событии, линия показывает среднюю цену, по которой совершались сделки после него. Цена выше линии означает, что большинство участников имеют нереализованную прибыль. Цена ниже линии означает обратное. На панели ниже для пяти известных компаний анкер установлен на минимальной дневной цене закрытия за последние двенадцать месяцев. Затем последняя цена закрытия периода сравнивается с полученным средним значением.

ЗапросПривязка к минимальной цене закрытия каждой акции за последние двенадцать месяцев
Точный SQL-код для каждого числа
WITH
    bars AS (
        SELECT
            ticker,
            date,
            toFloat64(vwap)   AS px,
            toFloat64(volume) AS vol,
            toFloat64(close)  AS c
        FROM global_markets.stocks_daily_aggs
        WHERE ticker IN ('AAPL', 'MSFT', 'NVDA', 'KO', 'SPY')
          AND date >= '2025-07-01'
          AND date <= '2026-06-30'
    ),
    lows AS (
        SELECT
            ticker,
            argMin(date, c) AS low_date
        FROM bars
        GROUP BY ticker
    )
SELECT
    b.ticker                                AS symbol,
    formatDateTime(l.low_date, '%b %e, %Y') AS anchored_at,
    round(sumIf(b.px * b.vol, b.date >= l.low_date) / sumIf(b.vol, b.date >= l.low_date), 2) AS anchored_vwap,
    round(argMax(b.c, b.date), 2)           AS last_close,
    round(100 * (argMax(b.c, b.date)
        / (sumIf(b.px * b.vol, b.date >= l.low_date) / sumIf(b.vol, b.date >= l.low_date)) - 1), 1) AS close_vs_avwap_pct
FROM bars AS b
INNER JOIN lows AS l ON b.ticker = l.ticker
GROUP BY b.ticker, l.low_date
ORDER BY close_vs_avwap_pct DESC
Run this yourself

Пять компаний располагаются в диапазоне от SPY при 10.4% до MSFT при 1.3%. Для каждой используется собственная дата анкера. Этот диапазон отражает произошедшее, но важно точно понимать ограничения метода. Anchored VWAP — описательная статистика, рассчитанная по уже исполненным ценам и объёмам. Это не прогноз и не торговое правило с подтверждённым преимуществом в опубликованных исследованиях. Показатель не содержит информации, которой уже нет в истории цен и объёмов. Кроме того, анкер выбирает человек. Если рассматривать anchored VWAP как сводку движения рынка с определённой даты, это корректный инструмент. Если воспринимать его как окончательный вывод, основную роль играет выбор анкера.

Часто задаваемые вопросы

В чём разница между VWAP и anchored VWAP?

Session VWAP обнуляет накопительные итоги при каждом открытии рынка, поэтому описывает только текущий день. Anchored VWAP начинает расчёт с выбранного вами бара и не сбрасывается. Поэтому он показывает среднюю цену, по которой совершались сделки на всех сессиях после этого бара.

Где трейдеры устанавливают анкер VWAP?

Обычно выбирают дату публикации финансовой отчётности, первый бар гэпа, локальный максимум или минимум, а также первый торговый день после листинга. Анкером может быть любой бар. Чтобы интерпретировать линию, читателю нужно знать дату анкера.

Сбрасывается ли anchored VWAP на ночь?

Нет. Это его определяющее свойство. Накопительная сумма произведений цены на объём и накопительная сумма объёма сохраняются после закрытия рынка. На следующей сессии расчёт продолжается, независимо от того, сколько сессий прошло.

Делает ли anchored VWAP прогнозы?

Это описательная статистика, а не прогноз. Она суммирует цены, по которым уже совершались сделки с момента анкера. Изменение анкера меняет линию и может изменить вывод. Поэтому любое утверждение на её основе настолько надёжно, насколько обоснован выбор даты анкера.

Можно ли рассчитать anchored VWAP по дневным барам?

Да. На панелях этой страницы используются дневные бары, а session VWAP каждой сессии служит ценой бара. На внутридневных графиках вместо них используются минутные бары. Формула на любом таймфрейме одинаковая, меняется только размер приращений.


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