How to calculate anchored VWAP
Quick answer
To calculate anchored VWAP, pick an anchor bar, then for every bar from the anchor onward multiply the typical price, (high + low + close) / 3, by that bar's volume, and divide the running total of those products by the running total of volume. Unlike session VWAP it never resets. On daily bars the choice of anchor day moves the line more than the choice of price input, and prices and volume must be split-adjusted together or the weights are wrong.
Anchored VWAP is the volume-weighted average price from a bar you choose up to now. For each bar from the anchor onward, multiply its typical price by its volume, add those products up, and divide by the total volume over the same bars. The result is the average price paid by everyone who traded since the anchor, which is why traders anchor it to an event: an earnings gap, a low, a breakout.
The formula is the easy part, and every guide ranking for this question gives it. What they leave out is what moves the number in practice: which bar the line starts on, which price you weight, and whether your price and volume data were adjusted the same way. We worked all three on real SPY data below.
The formula
Anchored VWAP at bar n = sum of (typical price × volume) from the anchor to n, divided by the sum of volume from the anchor to n. Typical price is (high + low + close) / 3. That is the convention, and implementations that use the close alone will not match charts that use the typical price.
Session VWAP is the same sum restarted at every session open. Anchored VWAP never restarts, which has a consequence for how the line moves: each new bar's weight is its share of all the volume since the anchor, so the line gets stiffer as time passes. It is not a moving average and it does not forget.
def anchored_vwap(bars, anchor_date):
"""bars: list of dicts with date, high, low, close, volume, oldest first."""
pv = vol = 0.0
out = []
for b in bars:
if b["date"] < anchor_date:
continue
typical = (b["high"] + b["low"] + b["close"]) / 3
pv += typical * b["volume"]
vol += b["volume"]
out.append((b["date"], pv / vol))
return outA worked example: SPY from the 30 March 2026 low
We used daily SPY bars from Alpha Vantage covering 11 December 2025 to 6 May 2026. The lowest low in that window printed on 30 March 2026 at 629.28. That day's bar: high 640.37, low 629.28, close 631.97, volume 99,275,851 shares, so its typical price is 633.87.
Anchored on 30 March, the VWAP starts at 633.87 and by 6 May stands at 685.89, with SPY closing that day at 733.83. Over those 27 bars the anchor day still carries 6.1% of the total volume, and the latest day only 3.3%, which is the stiffness in numbers.
Typical price or close: about a dollar
Run the same calculation on closing prices and the 6 May value is 686.96 instead of 685.89. Across the whole window the two versions never differ by more than 1.90, and the largest gap is on the anchor day itself, where the close sat near the low. Small, but enough that two charts of the "same" anchored VWAP will disagree visibly at the level traders watch. State which price you used.
The anchor bar: more than three dollars
Anchor one bar later, on 31 March, and the 6 May value is 689.25. Moving the anchor by a single day shifted the line by 3.36, three times the effect of the price choice.
On daily bars this is not a detail. A daily bar has one typical price and one volume number for the whole session, so anchoring "at the low" on 30 March actually includes every share traded that day, most of them above 629.28. Anchoring the next day leaves that heavy session out entirely. If the event you care about happened intraday, anchor on intraday bars from the exact bar. If you only have daily data, decide whether the event day belongs in the average and write the anchor date on the chart.
Split and dividend adjustment: adjust price and volume together
This one breaks anchored VWAPs that span a corporate action, and it is invisible until you check. Take a hypothetical stock, purely to show the arithmetic: 10 days at 400 dollars on 1 million shares a day, then a 4-for-1 split, then 10 days at 105 on 4 million shares a day.
Adjusted properly, the pre-split bars become 100 dollars on 4 million shares, and the anchored VWAP across all 20 days is 102.50. Use split-adjusted prices with unadjusted volume and the pre-split days get a quarter of their real weight, giving 104.00. Use unadjusted prices for both and you get 164.00, a level nobody ever traded at after the split. Check in your data vendor's documentation whether volume is split-adjusted, not just prices.
Dividends cause a quieter version of the same problem. A dividend-adjusted price series shifts every bar before each ex-date downward, so an anchored VWAP built on it will sit below the one on an unadjusted chart, by more the further back the anchor sits. Neither is wrong, but they are different lines. Pick one and say so in the caption.
Charting it
Draw the line over the price bars, mark the anchor bar, and put the anchor date and the price basis in the label, for example "AVWAP from 30 Mar 2026, typical price". Two or three anchors on one chart, say from a low, an earnings gap and the start of the year, show where different groups of buyers sit on average, and the shared volume axis underneath shows how much each anchor's average rests on. The volume profile post is the companion view: it shows where volume traded by price level rather than averaging it into one line. An earnings date is a natural anchor, and the earnings expected move post covers what the options market priced going into one.
[QUADESTO-EMBED: SPY daily candles 11 Dec 2025 to 6 May 2026 with anchored VWAP lines from 30 Mar and 31 Mar 2026, typical-price basis, anchor bars marked, volume pane below]
Where Quadesto fits
Quadesto builds price charts like this from your own OHLCV data or from a connected market data source. Whichever tool draws the line, put the anchor date and the price basis in the caption so a reader can check it. You can start free.