Volume weighted moving average: formula and limits
The volume weighted moving average (VWMA) averages a price source over a rolling window using each bar's volume as its weight. A bar with more volume receives more weight, wherever it sits in that window. In Pine Script, ta.vwma(source, length) provides the built-in calculation.
VWMA = Σ(source × volume) / Σ(volume)
Both sums cover the same latest N bars with complete data. Total volume must be positive. The three-bar example below gives 104.1667, compared with an SMA of 103.
A rolling window you can calculate by hand
These are hypothetical consecutive bars within one session, not market data or a backtest. Use close as the source and a length of 3. Volume is in arbitrary, consistent units.
| Bar | Close | Volume | Close × volume |
|---|---|---|---|
| A | 100 | 10 | 1,000 |
| B | 102 | 20 | 2,040 |
| C | 107 | 30 | 3,210 |
| D | 101 | 10 | 1,010 |
At C, VWMA = (1,000 + 2,040 + 3,210) / (10 + 20 + 30) = 104.1667. SMA = (100 + 102 + 107) / 3 = 103. The high-price bar C receives half of the total weight.
At D, A leaves the rolling window. VWMA = (2,040 + 3,210 + 1,010) / 60 = 104.3333; SMA = (102 + 107 + 101) / 3 = 103.3333. The close fell from 107 to 101, yet VWMA rose because the outgoing 100-price bar was replaced by a 101-price bar of equal volume.
VWMA above SMA describes the relationship between price levels and volume weights inside the window. It does not prove that the latest bar had buying pressure or that the next bar will rise.
For a session VWAP using these same closes and starting at A, all four bars remain at D: 7,260 / 70 = 103.7143. It differs because A is still included. When a new session starts, session VWAP resets; the three-bar VWMA keeps rolling across the session boundary.
VWMA, SMA, WMA and session VWAP
| Average | Weight | Window / reset |
|---|---|---|
| VWMA | Bar volume | Latest N bars; oldest bar leaves |
| SMA | Equal weight | Latest N observations |
| Linear WMA | Increasing weight toward newest bar | Latest N observations |
| Session VWAP | Bar volume | All bars since session start; resets next session |
The comparison assumes complete data. VWMA has no automatic preference for the newest bar: an older high-volume bar can dominate until it leaves. With equal positive volumes, VWMA equals SMA. Multiplying every volume in a window by the same positive constant leaves VWMA unchanged.
TradingView's VWAP supports anchors beyond Session and defaults to hlc3. Comparing that default with a close-based VWMA mixes two changes: source and window. Set the source consistently before attributing a difference to the weighting.
For the other calculations, see the SMA guide and linear WMA guide.
Volume and history limits to check first
Zero volume is different from missing volume
One zero-volume bar adds nothing to either weighted sum. If every bar has zero volume, the denominator is zero and VWMA is undefined. Missing volume is an unknown value. Replacing it with zero silently assumes that no activity occurred.
The code below adopts a strict policy: require N consecutive bars with a non-missing source and nonnegative, non-missing volume, plus positive total volume. Otherwise leave the strict result empty. It also plots the built-in VWMA so you can inspect differences on the actual feed instead of assuming that every function handles missing observations identically.
Volume belongs to the selected feed
TradingView documents different volume units across instruments, including shares, contracts and base-currency amounts. Check the symbol and provider before comparing values. Missing volume cannot be repaired by choosing a shorter period; a different source or an average without volume may be needed.
Splits require a consistent price and volume basis
TradingView adjusts historical prices for stock splits. When reproducing a VWMA from an export or another vendor, check the adjustment basis for both price and volume. Do not combine a raw pre-split price with post-split units and interpret the resulting discontinuity as a trading signal.
Hypothetical 2-for-1 split example: a pre-split bar at 100 with volume 10 becomes price 50 and volume 20 when expressed in post-split share units. Combine it with a later bar at 52 and volume 20: the consistent average is (50 × 20 + 52 × 20) / 40 = 51. Mixing the raw pre-split pair with the later bar gives 68. This is a unit-conversion demonstration, not a claim about every provider's adjustment policy.
Pine Script v6: audit the window and confirmation
Paste this indicator into TradingView's Pine Editor and add it to the chart. The blue line is the built-in VWMA, orange circles are the strict-window calculation, and gray is SMA. Open the Data Window to inspect the strict-minus-built-in difference on valid windows; allow for floating-point rounding.
//@version=6
indicator("VWMA window audit", overlay=true)
length = input.int(20, "Length", minval=1, maxval=500)
src = input.source(close, "Source")
builtIn = ta.vwma(src, length)
smaValue = ta.sma(src, length)
// Require every bar in the exact window to have valid data.
validBar = not na(src) and not na(volume) and volume >= 0
validCount = math.sum(validBar ? 1.0 : 0.0, length)
weightedSum = math.sum(validBar ? src * volume : 0.0, length)
volumeSum = math.sum(validBar ? volume : 0.0, length)
windowReady = bar_index >= length - 1 and validCount == length and volumeSum > 0
strictVwma = windowReady ? weightedSum / volumeSum : na
crossedAbove = ta.crossover(src, strictVwma)
confirmedCross = barstate.isconfirmed and windowReady and not na(strictVwma[1]) and crossedAbove
plot(builtIn, "Built-in VWMA", color=color.blue, linewidth=2)
plot(strictVwma, "Strict window VWMA", color=color.orange, style=plot.style_circles)
plot(smaValue, "SMA", color=color.gray)
plot(windowReady ? strictVwma - builtIn : na, "Strict minus built-in", display=display.data_window)
plotshape(confirmedCross, title="Confirmed cross above", text="Cross", style=shape.triangleup, location=location.belowbar, color=color.blue, size=size.tiny)
alertcondition(confirmedCross, "Confirmed VWMA cross", "Source crossed above the strict VWMA on a closed bar.")The first strict value needs a full valid window. A crossing marker also needs the previous strict value, so the first valid average alone cannot trigger it. The plots update during the open bar; only the marker and alert condition wait for the close. Create a TradingView alert from this condition if you want notifications.
| Input | Example default | What to verify |
|---|---|---|
| Length | 20 bars | Allowed: 1 to 500. Pick a bar horizon, not a promised best setting. |
| Source | close | Match it across the manual calculation and comparison indicators. |
This is an indicator and calculation check, not a complete strategy. It defines no exits, position sizing, fees or slippage. Educational information only; not investment advice.
Turn the checked calculation into your script
- Choose the symbol, feed, session and timeframe, then compare several closed bars against the calculation.
- Set Length to 3 to audit a small window. Check that the oldest bar drops out and that zero or missing volume follows your stated policy.
- Ask Pineify's Pine Script AI Coding Agent to adapt the inputs, invalid-data handling and close confirmation. Include the rule in the prompt.
- Inspect the generated code and chart values before adding exits, sizing and trading costs for a separate strategy test.
Example prompt
Create a Pine Script v6 VWMA indicator with adjustable source and length. Require a complete fixed window and positive total volume. Plot SMA for comparison and signal a cross only after the chart bar closes. Leave invalid results empty.
VWMA questions
Sources and related guides
Official documentation checked October 17, 2026. Numeric examples are original hypothetical calculations.