Strasmore Research
学習 Matt Connor著者: Matt Connor

Anchored VWAPの計算式と使い方

Anchored VWAPは選択したバーから累計を始め、リセットしない出来高加重平均価格です。Pythonの式と、アンカー変更による値の違いを解説します。

Anchored VWAPは、出来高加重平均価格の累計を、選択した一つのバーから開始し、その後リセットしない指標です。セッションVWAPは各寄り付きで計算をやり直すため、その日に平均的な株式がいくらで取引されたかしか示しません。Anchored VWAPは異なる問いに答えます。選択した起点以降、平均的な株式がいくらで取引されたかを示します。

Anchored VWAPとは何ですか?

両者の計算方法は同じです。開始時点以降の各バーについて、バー価格にそのバーの出来高を掛け、累計します。別に出来高も累計します。前者を後者で割ります。式で表すと、n番目のバーにおけるAnchored VWAPは、アンカーバーからn番目のバーまでの価格と出来高の積の合計を、同じバー群の出来高合計で割った値です。

バー価格には通常、始値・高値・安値・終値のうち、高値、安値、終値の平均である代表価格を使います。フィードがバー自体のVWAPを配信している場合は、それを使うこともあります。

どちらの累計からも、過去の値が削除されることはありません。50日移動平均は、新しい観測値を取り込むたびに最も古い観測値を外すため、方向を変えられます。Anchored VWAPは加算するだけなので、過去の情報が残り続けます。セッションVWAPは、各寄り付きで両方の累計をゼロに戻す同じ計算です。つまり、寄り付きのベルをアンカーにしたAnchored VWAPです。

VWAPとAnchored VWAPの違いは何ですか?

下のパネルでは、Appleの日足バーを対象に、1四半期分の両方を計算しています。session_vwap列は各セッション内の出来高加重平均価格で、毎日新たに計算されます。anchored_vwap列は対象期間の最初のセッションから始まり、そこから累計します。

クエリ日次セッションVWAPと1日にアンカーした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系列はゆっくり曲がります。初日は一つのセッションが全履歴に当たるため、Anchoredラインは255.02で始まります。期間の末日には286.86となり、最終セッションVWAPの288.09と比較できます。ここで重要なのは形状です。Anchoredラインは最初のうちは日次ラインに近く動きますが、その裏付けとなる出来高が積み上がるにつれて平坦になります。

どこにアンカーを置きますか?

よく使われるアンカーは、決算発表、ギャップの最初のバー、52週安値、新規上場銘柄の最初の約定値です。これらに共通する考え方は同じです。その時点以降に取引した全員が、平均するとAnchored 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通りの判断が生じます。計算自体がアンカーを選んでくれるわけではありません。後からアンカーを選び、チャートが示したい内容を支持するまで動かすこともできます。そのため、Anchored VWAPチャートを読む際は、アンカー日を必ずキャプションに記載すべきです。

PythonでAnchored VWAPを計算する方法

両系列は、バーを一度走査するだけで計算できます。以下のスクリプトは、パッケージもネットワークも使わない標準ライブラリのPython 3です。30本のバーを読み込み、セッション系列とAnchored系列を並べて表示します。その後、価格がAnchoredラインを再び横切った最初のバーを報告します。バーは説明用に作成したものです。同じループを実際のバーに適用しても、計算方法は変わりません。

"""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は日付が変わるたびにゼロになります。anchor_pvanchor_volはゼロに戻りません。それ以外は表示処理です。

Anchoredラインの動きが止まる理由

Anchored 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%まで低下します。これらのチャートから読み取れる点は二つあります。古いアンカーは、現在の動きにほとんど反応しない平坦なラインを描きます。新しいアンカーは、価格の周囲で大きく動き、価格と頻繁に交差します。どちらがより正しいということではありません。経過時間が異なる同じ計算式です。通常に対してどれだけの出来高が流入しているかを直接確認するには、平均日次出来高相対出来高を使います。

Anchored 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銘柄は、10.4%におけるSPYから、1.3%におけるMSFTまで分布しています。各銘柄は、それぞれのアンカー日を基準に測定しています。この差が示すのは過去の値動きです。その限界も正確に理解する必要があります。Anchored VWAPは、すでに成立した価格と出来高から計算する記述統計であり、予測でも、学術研究で確立された優位性を持つルールでもありません。価格と出来高の履歴に含まれていない情報は持たず、結果を生んだアンカーも人が選んだものです。ある日以降の値動きの要約として読むなら妥当です。判断として読むなら、語っているのはアンカーです。

よくある質問

VWAPとAnchored VWAPの違いは何ですか?

セッションVWAPは市場の各寄り付きで累計をリセットするため、当日の状況だけを示します。Anchored VWAPは選択したバーから累計を始め、リセットしません。そのため、そのバー以降の全セッションにおける平均取得価格を示します。

トレーダーはVWAPをどこにアンカーしますか?

一般的な選択肢は、決算日、ギャップの最初のバー、スイング高値またはスイング安値、新規上場銘柄の初取引日です。どのバーでもアンカーにできます。ラインを解釈するには、アンカー日を把握する必要があります。

Anchored VWAPは夜間にリセットされますか?

いいえ。それが定義上の特徴です。価格と出来高の積の累計も、出来高の累計も、引けをまたいで維持されます。その後、次のセッションで再開します。次のセッションが何日後であっても同じです。

Anchored VWAPは何かを予測しますか?

これは予測ではなく、記述統計です。アンカー以降に実際に支払われた価格を要約します。アンカーを動かせばラインも動き、見かけ上の結論が逆転することがあります。したがって、これに基づく主張の妥当性は、アンカー日を選ぶ根拠に左右されます。

日足バーでAnchored VWAPを計算できますか?

はい。このページのパネルでは日足バーを使い、各セッションVWAPをバー価格としています。日中足チャートでは、代わりに分足バーを使います。どちらの時間軸でも計算式は同じで、増分の大きさだけが変わります。


上記の各パネルには、生成に使ったSQLが付属しています。そのため、パネルを開いてアンカー日を自分で変更できます。関心のある日付から同じ累計を実行するには、Strasmore terminalで平易な英語で依頼してください。