Guide walkthrough
Start reading here
This is the main article body, where the page shifts from summary cards into the actual workflow and decision-making notes.
On this page
What VWAP actually calculates
Volume-weighted average price is a running average of price, but each bar's contribution is weighted by how much volume traded on that bar instead of being counted equally. A bar with heavy volume pulls the average toward its price more than a quiet bar does. That weighting is the entire reason VWAP behaves differently from a simple moving average.
- Typical price per bar is usually (high + low + close) / 3.
- Each bar's typical price is multiplied by that bar's volume.
- VWAP is the running sum of those weighted values divided by the running sum of volume.
Why the reset matters more than the formula
The math behind VWAP is simple. The part that actually trips people up in Pine Script is resetting the running totals at the start of a new session. If the cumulative sums never reset, the script produces a multi-day average instead of a session VWAP, and it will look wrong without any obvious error.
- Detect a new session before accumulating that bar's contribution.
- Reset both the volume-times-price total and the volume total together.
- Decide deliberately whether the reset should be daily, weekly, or anchored to a custom event.
Build it manually first
The code block below tracks two running totals with var float variables so they persist across bars, resets them on a new day, and divides one by the other to plot VWAP. This is the version worth typing out by hand at least once, because it makes the session-weighting behavior visible instead of hidden inside a built-in function.
//@version=5
indicator("Manual Session VWAP", overlay=true)
var float cumVolPrice = 0.0
var float cumVol = 0.0
newSession = ta.change(time("D")) != 0
if newSession
cumVolPrice := 0.0
cumVol := 0.0
typicalPrice = (high + low + close) / 3
cumVolPrice += typicalPrice * volume
cumVol += volume
vwapValue = cumVol > 0 ? cumVolPrice / cumVol : na
plot(vwapValue, "VWAP", color=color.blue, linewidth=2) Use the built-in shortcut once you understand it
Pine Script ships a built-in ta.vwap() function that performs the same session-anchored calculation automatically and resets on each new trading day by default. Once the manual version above makes sense, most traders switch to the built-in for day-to-day use and save the manual version for anything that needs a custom reset condition, like anchoring to a session other than the calendar day.
//@version=5
indicator("Built-in VWAP", overlay=true)
plot(ta.vwap(hlc3), "VWAP", color=color.blue, linewidth=2) Common mistakes to check before trusting the plot
A VWAP that looks plausible is not the same as a VWAP that is correct. Confirm the reset timing matches the session you actually trade, and watch for symbols where volume data is unreliable.
- Confirm the script resets at your session's actual open, not just at midnight UTC.
- On symbols with thin or unreliable volume reporting, VWAP can be misleading regardless of how clean the code is.
- If you anchor VWAP to something other than the daily session, document the anchor condition clearly so it is obvious later why the line resets where it does.
Best next reads
These pages pick up the questions most readers usually have next, so you do not have to back out and start a fresh search.
Frequently asked questions
What is the simplest way to add VWAP to a Pine Script chart?
Use the built-in `ta.vwap()` function: `plot(ta.vwap(hlc3), "VWAP")`. It resets automatically at the start of each trading day.
Why build VWAP manually if Pine Script already has ta.vwap()?
Building it manually teaches the session-reset logic, which you need anyway if you ever want to anchor VWAP to something other than the calendar day, such as a custom session window or a specific event.
Does VWAP work the same way on every symbol?
No. VWAP depends on volume data being meaningful. On symbols with thin, unreliable, or proxy volume reporting, the weighting can be misleading even though the calculation itself is correct.