Strasmore Research
학습 Matt Connor작성자 Matt Connor

앵커드 VWAP 공식과 활용법 알아보기

앵커드 VWAP의 누적 평균 계산 방식과 공식을 설명합니다. Python 예제로 앵커 위치를 바꿀 때 결과가 어떻게 달라지는지도 알아봅니다.

앵커드 VWAP는 거래량가중평균가격으로, 사용자가 선택한 하나의 바에서 누적 합계를 시작한 뒤 이를 초기화하지 않는다. 세션 VWAP는 매일 개장할 때마다 다시 시작하므로, 해당 거래일에 평균적으로 주식이 얼마에 거래됐는지만 보여준다. 반면 앵커드 VWAP는 선택한 시작 시점 이후 주식이 평균적으로 얼마에 거래됐는지를 보여준다.

앵커드 VWAP란 무엇인가?

두 방식의 산술 계산은 동일하다. 시작 시점 이후 각 바의 가격에 해당 바의 거래량을 곱하고 이를 누적한다. 거래량도 별도로 누적한다. 첫 번째 누적값을 두 번째 누적값으로 나눈다. 수식으로 나타내면 n번째 바의 앵커드 VWAP는 앵커 바부터 n번째 바까지 가격과 거래량을 곱한 값의 합을 같은 구간의 거래량 합으로 나눈 값이다.

바의 가격에는 일반적으로 고가, 저가, 종가의 평균인 대표가격을 사용한다. 데이터 피드가 바 자체의 VWAP를 제공할 때는 해당 값을 사용하기도 한다.

두 누적값에서는 어떤 값도 제거되지 않는다. 50일 이동평균은 새로운 관측값을 추가할 때마다 가장 오래된 관측값을 제외한다. 그래서 이동평균선이 방향을 바꿀 수 있다. 앵커드 VWAP는 계속 더하기만 하므로 과거 정보가 영구적으로 남는다. 세션 VWAP는 매일 개장할 때 두 누적값을 모두 0으로 되돌리는 동일한 계산이다. 따라서 세션 VWAP는 앵커가 개장 시점에 고정된 앵커드 VWAP라고 볼 수 있다.

VWAP와 앵커드 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까지 일별 시계열은 시장 흐름에 따라 움직인 반면, 앵커드 시계열은 완만하게 휘어진다. 첫날에는 한 세션이 전체 이력과 같으므로 앵커드 선은 255.02에서 시작한다. 기간이 끝날 때는 286.86에 도달하며, 최종 세션 VWAP는 288.09였다. 선의 형태가 핵심이다. 앵커드 선은 처음에는 일별 선을 가까이 따라간다. 이후 이를 뒷받침하는 거래량이 누적되면서 점차 평평해진다.

사람들은 어디에 앵커를 설정하는가?

자주 쓰이는 앵커는 실적 발표일, 갭이 발생한 첫 번째 바, 52주 저점, 신규 상장 종목의 첫 거래 가격이다. 이들에 붙는 논리는 동일하다. 해당 시점 이후 거래에 참여한 모든 투자자가 평균적으로 앵커드 VWAP에 거래했다는 것이다. 따라서 가격이 선 위에 있으면 평균 참여자가 평가이익 상태라는 뜻으로 해석할 수 있다.

다만 일반적으로 빠지는 부분이 있다. 앵커는 판단에 따라 정하는 값이며, 결과도 앵커를 따라 달라진다. 아래 패널은 같은 종목을 최근 12개월 각각의 시작점에 앵커로 설정한 뒤, 해당 월부터 하나의 고정된 종료일까지 평균 매입가격을 계산한다.

조회동일 종목·동일 최근 가격, 12개의 서로 다른 앵커(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%이다. 같은 종목과 같은 마지막 가격을 놓고도, 앵커 이후 보유자가 수익 상태인지에 대해 12가지 판단이 나온다. 산술 계산 자체가 앵커를 정해주지는 않는다. 사후적으로 앵커를 선택하면 차트가 전달하려는 결론에 맞을 때까지 날짜를 바꿀 수 있다. 따라서 읽는 모든 앵커드 VWAP 차트의 캡션에는 앵커 날짜가 표시되어야 한다.

Python에서 앵커드 VWAP를 어떻게 계산하는가?

두 시계열은 바를 한 번 순회하는 과정에서 계산할 수 있다. 아래 스크립트는 패키지와 네트워크를 사용하지 않는 표준 라이브러리 Python 3 코드다. 30개 바를 읽어 세션 시계열과 앵커드 시계열을 나란히 출력한다. 이후 가격이 앵커드 선을 다시 통과한 첫 번째 바를 표시한다. 바는 설명을 위해 임의로 만든 값이다. 같은 반복문에 실제 바를 넣어도 산술 계산은 달라지지 않는다.

"""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_pvsession_vol은 날짜가 바뀔 때마다 0으로 초기화된다. anchor_pvanchor_vol은 초기화되지 않는다. 그 이후의 작업은 결과를 출력하는 것뿐이다.

앵커드 선은 왜 움직임이 둔해지는가

앵커드 VWAP는 시간이 지날수록 움직이기 어려워진다. 이는 기계적인 이유 때문이다. 새 바는 앵커 이후 전체 거래량에서 해당 바의 거래량이 차지하는 비율만큼 평균에 반영된다. 둘째 날에는 한 세션의 거래량이 전체의 절반을 차지할 수 있다. 200개 세션이 지나면 같은 세션의 비중은 1% 미만으로 떨어진다. 아래 패널은 Apple 바를 10개 세션 단위로 나눠 이 비중을 측정한 결과다.

조회최신 세션이 앵커 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

첫 10개 세션에서는 유입되는 바가 선의 평균 30.09%를 차지한다. 앵커 바 자체는 전체 비중을 차지한다. 130 세션에 이르면 가장 최근 바의 비중은 2.14%까지 낮아진다. 이 차트를 읽을 때 두 가지를 알 수 있다. 오래된 앵커는 거의 움직이지 않는 평평한 선을 만든다. 현재 발생하는 거래에도 거의 반응하지 않는다. 반면 새로운 앵커는 가격을 따라 급격히 움직이며 가격선을 자주 교차한다. 어느 쪽이 더 정확한 것은 아니다. 서로 다른 기간만큼 오래된 동일한 공식이다. 정상 수준과 비교해 거래량이 얼마나 유입되는지를 직접 확인하려면 평균 일일 거래량상대 거래량을 확인하면 된다.

앵커드 VWAP는 무엇을 보여준다고 보는가?

일반적인 해석은 포지셔닝을 파악하는 지표라는 것이다. 특정 이벤트에 앵커를 설정하면 선은 그 이후 거래에 참여한 투자자의 평균 매입가격이 된다. 따라서 가격이 선 위에 있으면 다수의 보유자가 평가이익 상태라는 뜻으로 해석한다. 선 아래에 있으면 그 반대다. 아래 패널은 5개 대표 종목 각각에 대해 최근 12개월 중 기록된 일일 종가 최저점에 앵커를 설정했다. 이후 해당 기간의 마지막 종가가 계산된 평균 매입가격에서 얼마나 떨어져 있는지 측정했다.

조회각 종목의 지난 12개월 최저 종가에 앵커
모든 수치 뒤에 숨겨진 정확한 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

5개 종목은 각각의 앵커 날짜를 기준으로 SPY10.4%에서 MSFT1.3%까지 분포한다. 이 차이는 실제로 발생한 결과를 보여준다. 다만 해석의 한계를 분명히 해야 한다. 앵커드 VWAP는 이미 거래된 가격과 거래량으로 계산한 기술통계량이다. 미래를 예측하는 지표가 아니다. 학술 연구에서 검증된 우위를 가진 매매 규칙도 아니다. 가격과 거래량 이력에 없는 정보를 담고 있지도 않다. 결과를 만든 앵커 역시 사람이 선택했다. 특정 날짜 이후 시장 흐름을 요약하는 지표로 읽으면 타당하다. 확정적인 판단으로 읽는다면 결론을 좌우하는 것은 앵커다.

자주 묻는 질문

VWAP와 앵커드 VWAP의 차이는 무엇인가?

세션 VWAP는 매일 시장이 개장할 때마다 누적값을 초기화한다. 따라서 현재 거래일만 설명한다. 앵커드 VWAP는 사용자가 선택한 바에서 누적을 시작하고 초기화하지 않는다. 따라서 해당 바 이후 모든 세션에서의 평균 매입가격을 설명한다.

트레이더는 VWAP를 어디에 앵커로 설정하는가?

일반적인 선택지는 실적 발표일, 갭이 발생한 첫 번째 바, 스윙 고점 또는 스윙 저점, 신규 상장 종목의 첫 거래일이다. 어떤 바든 앵커가 될 수 있다. 독자가 선을 해석하려면 앵커 날짜를 알아야 한다.

앵커드 VWAP는 밤사이 초기화되는가?

아니다. 초기화되지 않는 것이 앵커드 VWAP의 정의상 핵심이다. 가격과 거래량을 곱한 값의 누적합과 거래량 누적합은 장 마감 후에도 유지된다. 이후 다음 세션이 시작되면, 세션 간격이 얼마나 길었는지와 관계없이 계산을 이어간다.

앵커드 VWAP는 무엇인가를 예측하는가?

앵커드 VWAP는 예측이 아니라 기술통계량이다. 앵커 이후 실제로 지불된 가격을 요약한다. 앵커를 바꾸면 선이 움직이고 겉으로 보이는 결론도 반대가 될 수 있다. 따라서 이를 바탕으로 한 주장의 타당성은 앵커 날짜를 선택한 근거만큼만 강하다.

앵커드 VWAP를 일봉으로 계산할 수 있는가?

가능하다. 이 페이지의 패널은 일봉을 사용하며, 각 세션 VWAP를 바의 가격으로 사용한다. 장중 차트에서는 분봉을 사용한다. 어느 시간 단위에서도 공식은 동일하다. 달라지는 것은 증분의 크기뿐이다.


위의 모든 패널에는 이를 산출한 SQL이 함께 제공된다. 따라서 패널을 열고 앵커 날짜를 직접 바꿔볼 수 있다. 관심 있는 날짜를 기준으로 같은 누적 계산을 실행하려면 Strasmore terminal에 자연어로 요청하면 된다.