TradingView indicator guides

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.

Demonstration inputs, oldest to newest
BarCloseVolumeClose × volume
A100101,000
B102202,040
C107303,210
D101101,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

AverageWeightWindow / reset
VWMABar volumeLatest N bars; oldest bar leaves
SMAEqual weightLatest N observations
Linear WMAIncreasing weight toward newest barLatest N observations
Session VWAPBar volumeAll 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.

Pine Script v6
//@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.

InputExample defaultWhat to verify
Length20 barsAllowed: 1 to 500. Pick a bar horizon, not a promised best setting.
SourcecloseMatch 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

  1. Choose the symbol, feed, session and timeframe, then compare several closed bars against the calculation.
  2. 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.
  3. Ask Pineify's Pine Script AI Coding Agent to adapt the inputs, invalid-data handling and close confirmation. Include the rule in the prompt.
  4. 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.

Open Pine Script AI Coding Agent

VWMA questions

VWMA averages a price source over a rolling window, using each bar's volume as its weight. With complete data and positive total volume, it equals the sum of price times volume divided by the sum of volume. It describes the selected price and volume series; it does not estimate a guaranteed fair value.

VWMA uses a fixed rolling length. Session VWAP accumulates from the start of a session and resets at the next session. Other VWAP anchors can use longer periods or selected events. Match the price source before comparing them: this example uses close, while TradingView's VWAP defaults to hlc3.

A zero-volume bar contributes zero weight when the rest of the window has positive volume. An entirely zero-volume window has no defined weighted average. Missing volume is unknown, not zero. The strict-window example leaves the result empty if any bar lacks a source or volume value, or if total volume is zero.

There is no universal best length. This script starts at 20 bars with close as the source. Twenty daily bars and twenty five-minute bars describe different horizons. Choose the horizon first, then compare the output on the same symbol, data feed, session, price source, and chart timeframe.

No. For the same complete window, VWMA above SMA means the volume weights favor higher price levels relative to the equal-weight average. The newest bar can still close lower, as the worked example shows. A crossover alone does not establish a profitable trading rule.

Yes. Both price and volume can change while a bar is open, so the average and a temporary crossing can change too. The example keeps its plots live but waits for barstate.isconfirmed before showing a crossing marker or enabling its alert condition. Historical feed corrections can still change past values.