Strasmore Research
Learn am Matt ConnorBy Matt Connor · Updated 2026-08-08

Anchored VWAP Formula and Uses Explained

Anchored VWAP dey start im running average from any bar wey you choose. See the formula for plain Python and how changing the anchor dey change the answer.

Anchored VWAP na a volume weighted average price wey dey start im running totals from one bar wey you choose, and e no dey reset again. Session VWAP dey start over whenever market bell open, so e only dey answer wetin be the average price wey people don trade the share for today. Anchored version dey answer another question: wetin be the average price wey people don trade the share for since the time wey you choose as starting point.

Wetin be anchored VWAP?

Both versions dey use the same arithmetic. Take every bar since the start, multiply the price of each bar by that bar volume, then keep running total. Keep another running total for volume by itself. Divide the first total by the second one. If you write am out, anchored VWAP for bar n na the sum of price times volume from the anchor bar reach bar n, divided by the total volume across those same bars.

The price for one bar usually na its typical price, wey be the average of its high, low and close. E fit also be the VWAP of the bar itself if the feed publish one.

Nothing ever commot from either total. A 50-day moving average dey drop its oldest observation whenever e add new one, and na this dey allow am turn. Anchored VWAP only dey add, so its memory permanent. Session VWAP na the same calculation, but both totals dey return to zero at every market open. This make am an anchored VWAP wey im anchor na the opening bell.

Wetin be the difference between VWAP and anchored VWAP?

The panel below dey run both on Apple daily bars for one quarter. The session_vwap column na the volume weighted average price inside each single session, with fresh number every day. The anchored_vwap column start from the first session for the window and dey accumulate from there.

QueryDaily session VWAP against VWAP wey dem anchor for one date (AAPL)
The exact SQL behind every number
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

Across 62 sessions, from Apr 1 reach Jun 30, the daily series dey move with the tape while the anchored series dey bend slowly. The anchored line open at 255.02, because on day one one session na the whole history, and e reach 286.86 by the end of the window, compared with final session VWAP of 288.09. Na the shape be the main lesson. The anchored line dey follow the daily one closely at first, then e flatten as the volume behind am dey pile up.

Where people dey put the anchor?

Popular anchors na earnings release, the first bar of a gap, a 52-week low, or the opening print of a newly listed stock. The claim wey connect all of dem na the same. Everybody wey transact after that moment pay the anchored VWAP on average. So, when price dey above the line, e mean say the average participant dey sit on paper gain.

This na the part wey people normally no talk about. The anchor na judgment call, and the answer dey change with am. The panel below anchor the same stock at the beginning of each of the last twelve months. E then calculate the average price paid from that month reach one fixed end date.

QueryThe same stock and the same last price, twelve different anchors (AAPL)
The exact SQL behind every number
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

When you anchor at Jul 2025, the average price paid na 259.52. The last close for the window measure 11.5% against am. The figure dey positive when the close sit above the line. Anchoring at Jun 2026 give 294.07 and -1.6%. Na the same stock and the same last price, but twelve different verdicts on whether holders since the anchor dey above water. The arithmetic no choose the anchor for you. Person fit choose an anchor after the fact and move am until e support whatever message the chart suppose show. Na why the anchor date suppose dey inside the caption of every anchored VWAP chart wey you read.

How you fit calculate anchored VWAP for Python?

Both series dey come from one pass across the bars. The script below na standard library Python 3. E use no packages and no network. E read thirty bars and print the session series beside the anchored series. After that, e report the first bar where price cross back through the anchored line. The bars na examples wey dem create for demonstration. If you point the same loop at real bars, the arithmetic no change.

"""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")

The two pairs of counters na the whole idea. session_pv and session_vol dey return to zero whenever the date change. anchor_pv and anchor_vol no dey reset. Everything after that na printing.

Why anchored line dey stop moving

Anchored VWAP dey become harder to move as e dey age, and na mechanical reason cause am. Every new bar enter the average with weight equal to im own volume divided by all the volume since the anchor. On the second day, one session fit carry half of the total. Two hundred sessions later, that same session fit carry only fraction of one percent. The panel below measure that weight on Apple bars, in blocks of ten sessions.

QueryHow much the newest session fit move anchored VWAP (AAPL)
The exact SQL behind every number
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

During the first ten sessions, the new bar average 30.09% of the line. The anchor bar itself account for all of am. By session 130, the newest bar don fall to 2.14%. Two things follow when you read these charts. Old anchor draw almost flat line wey hardly respond to wetin dey happen now. Fresh anchor draw line wey dey move sharply around price and cross am often. None pass the other for correctness. Na the same formula at different ages. To directly see how much volume dey arrive compared with normal, average daily volume and relative volume dey measure am.

Wetin anchored VWAP claim to show?

The standard claim na positioning read. When event dey serve as the anchor, the line na the average price wey everybody wey transact since then pay. So price above the line describe majority holding wey dey on paper gain. Price below am describe the opposite. The panel below anchor five household names at the lowest daily close wey each of dem print for the past twelve months. E then measure the last close of the window against the average wey result.

QueryAnchored for each name own lowest close for the past twelve months
The exact SQL behind every number
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

The five names spread from SPY at 10.4% down to MSFT at 1.3%. Each one dey measure against im own anchor date. That spread describe wetin happen, but we need precise about the limits. Anchored VWAP na descriptive statistic wey dem calculate from prices and volumes wey don already print. E no be forecast, and e no be rule with established edge for published research. E no carry information wey price and volume history no already get. Also, person choose the anchor. If you read am as summary of the tape since one date, e honest. If you read am as verdict, na the anchor dey talk.

Frequently asked questions

Wetin be the difference between VWAP and anchored VWAP?

Session VWAP dey reset im running totals at every market open, so e only describe the current day. Anchored VWAP dey start im totals at one bar wey you choose and e no reset, so e describe the average price paid across every session since that bar.

Where traders dey anchor VWAP?

Common choices na earnings date, the first bar of a gap, swing high or swing low, and the first trading day for a new listing. Any bar fit serve as anchor. The anchor date na wetin reader need know to interpret the line.

Anchored VWAP dey reset overnight?

No. Na this be the defining property. The running sum of price times volume and the running sum of volume both carry across the close. Dem then continue on the next session, no matter how many sessions pass.

Anchored VWAP dey predict anything?

E na descriptive statistic, no be forecast. E summarize wetin people don already pay since the anchor. If you move the anchor, the line go move too, and the apparent conclusion fit reverse. So any claim wey build on am only strong as the case for that anchor date.

You fit calculate anchored VWAP on daily bars?

Yes. The panels for this page use daily bars, with each session VWAP serving as the bar price. Intraday charts use minute bars instead. The formula identical for both resolutions. Na only the size of the increments dey change.


Every panel above come with the SQL wey produce am, so you fit open one and move the anchor date by yourself. To run the same running totals from date wey matter to you, ask for am in plain English on the Strasmore terminal.