Anchored VWAP in Pine Script: Custom Indicator With Deviation Bands
Anchored VWAP accumulates a volume-weighted price average from a selected starting time. This tutorial implements that calculation in Pine Script and adds volume-weighted deviation bands. The result is a historical price reference, not intrinsic fair value, a record of institutional holdings or a proven entry signal.

What the Script Measures
For each included bar, multiply the chosen price source by volume. Sum those products and divide by total included volume. These examples use HLC3, the average of high, low and close. An OHLC4-based indicator can differ even with the same anchor.
A session VWAP commonly restarts each trading session; an anchored calculation can continue across sessions. The chosen anchor answers a specific question, such as the average representative price since an earnings event. The TradingView drawing tool is a separate way to place such a reference manually.
Basic Anchored VWAP Script
This example starts at the first loaded bar opening at or after the requested timestamp. It does not recover intrabar transactions before that bar. The default timestamp includes a UTC offset; select a date that exists within the chart's loaded history.
//@version=5
indicator("Anchored VWAP", overlay=true)
// Input for anchor date and time
anchorTime = input.time(timestamp("01 Jan 2024 09:15 +0530"), title="Anchor Date/Time")
// Variables to track anchor point and cumulative values
var int anchorBarIndex = na
var float cumulativeTPV = 0.0 // Total Price * Volume
var float cumulativeVolume = 0.0
// Detect anchor point
if na(anchorBarIndex) and time >= anchorTime
anchorBarIndex := bar_index
float anchoredVWAP = na
// Calculate anchored VWAP
if not na(anchorBarIndex) and bar_index >= anchorBarIndex
typicalPrice = (high + low + close) / 3.0
if not na(volume) and volume > 0
cumulativeTPV += typicalPrice * volume
cumulativeVolume += volume
anchoredVWAP := cumulativeVolume > 0 ? cumulativeTPV / cumulativeVolume : na
// Plot the line
plot(anchoredVWAP, color=color.blue, linewidth=2, title="Anchored VWAP")
The cumulative variables persist between bars. The plotted variable is declared in global scope and reassigned inside the condition, so the global plot can access it. TradingView's variable declaration documentation explains this scope rule.
Bars without positive, available volume are skipped. If all included volume is unavailable or zero, the output remains unavailable. Skipping missing observations does not make incomplete market data representative.
Add Volume-Weighted Deviation Bands
The enhanced version also accumulates price squared multiplied by volume. Its variance is the weighted second moment minus the square of the weighted mean. The square root gives a dispersion measure of the included representative bar prices.
//@version=5
indicator("Enhanced Anchored VWAP", overlay=true)
// Inputs
anchorTime = input.time(timestamp("01 Jan 2024 09:15 +0530"), title="Anchor Date/Time")
stdDev1 = input.float(1.0, title="Standard Deviation 1", minval=0.1, maxval=5.0)
stdDev2 = input.float(2.0, title="Standard Deviation 2", minval=0.1, maxval=5.0)
// Variables
var int anchorBarIndex = na
var float sumTPV = 0.0
var float sumVolume = 0.0
var float sumTPVSquared = 0.0
float vwap = na
float upperBand1 = na
float lowerBand1 = na
float upperBand2 = na
float lowerBand2 = na
// Detect anchor point
if na(anchorBarIndex) and time >= anchorTime
anchorBarIndex := bar_index
// Calculate values from anchor point
if not na(anchorBarIndex) and bar_index >= anchorBarIndex
tp = (high + low + close) / 3.0
if not na(volume) and volume > 0
sumTPV += tp * volume
sumVolume += volume
sumTPVSquared += tp * tp * volume
// Calculate VWAP
vwap := sumVolume > 0 ? sumTPV / sumVolume : na
// Calculate standard deviation
variance = sumVolume > 0 ? (sumTPVSquared / sumVolume) - (vwap * vwap) : na
stdDeviation = not na(variance) ? math.sqrt(math.max(variance, 0)) : na
// Calculate bands
upperBand1 := vwap + (stdDeviation * stdDev1)
lowerBand1 := vwap - (stdDeviation * stdDev1)
upperBand2 := vwap + (stdDeviation * stdDev2)
lowerBand2 := vwap - (stdDeviation * stdDev2)
// Plot everything
plot(vwap, color=color.blue, linewidth=2, title="Anchored VWAP")
upperPlot1 = plot(upperBand1, color=color.gray, title="Upper Band 1σ")
lowerPlot1 = plot(lowerBand1, color=color.gray, title="Lower Band 1σ")
plot(upperBand2, color=color.red, title="Upper Band 2σ")
plot(lowerBand2, color=color.red, title="Lower Band 2σ")
// Fill between bands for better visualization
fill(upperPlot1, lowerPlot1, color=color.new(color.blue, 95))
The variance is clamped at zero to handle small negative values from floating-point subtraction. For long histories or unusually large price magnitudes, compare the calculation with a numerically stable reference. These are price-dispersion bands, not a forecast distribution for future returns.
A two-standard-deviation band does not establish a 95% future containment probability. That interpretation would require distributional and sampling assumptions that this calculation does not establish. Price can remain outside a band during a trend.
Check the Anchor and Calculation
Before treating the output as a trading input:
- Select an anchor inside loaded history and locate the first eligible bar.
- Confirm its first VWAP equals HLC3 when its volume is positive.
- Check a short sequence manually. Hypothetical source prices of 100 and 102 with volumes of 10 and 30 produce VWAP 101.5, weighted variance 0.75 and standard deviation about 0.866.
- Change the timestamp to a time inside a bar and confirm accumulation begins at the next eligible opening.
- Test unavailable volume and a future anchor; neither should create a fabricated price line.
- Reload and compare completed-bar values. The open realtime bar may change as its prices and volume update.
If the anchor predates all loaded data, these examples begin at the first loaded bar rather than reconstructing missing history. If the timestamp is later than the last bar, no line appears. Changing timeframe changes price aggregation and potentially the first included bar.
Turn a Chart Idea into a Test
Possible hypotheses include a close crossing above the line, a return to the mean or continuation outside a band. These are different rules and should not be mixed after seeing the outcome. Specify entry timing, stop, exit, size and costs before evaluating them.
A price above VWAP is above the included weighted average. It does not justify increasing a position automatically. Similarly, an RSI filter or moving-average agreement needs a controlled comparison before being called a higher-probability setup.
For event anchors, record when the event became known. A swing low recognized only after several later bars cannot be used as if it were known at the low. Choosing anchors because historical price repeatedly bounced at them introduces selection bias.
The scripts are indicators, not strategies: they contain no orders and produce no Strategy Tester performance report. Build a separately specified strategy if you want to evaluate trading outcomes, and preserve an untouched period for validation.
Alerts and Extensions
The examples plot values but do not define custom alert conditions. You can inspect the TradingView alert dialog for supported plot-based conditions; custom combined events need explicit alert logic and testing. Changing script settings does not necessarily update an already-created alert's saved configuration.
An automatic anchor could be based on a predefined session, gap or event rule. Define exactly when it becomes true and what resets the accumulators. Automation removes repeated manual input; it does not remove bias from choosing the rule after looking at returns.
For Pine basics, see the tutorial guide. For the separate editor configuration and its exact-match timestamp behavior, see Pineify's Anchored VWAP guide.
Frequently Asked Questions
Which bar does the timestamp select?
These examples start at the first loaded bar whose opening time is at or after the timestamp. An anchor inside a bar therefore begins on a later bar, and an anchor before loaded history uses the first available bar.
Do deviation bands imply a certain chance of reversal?
No. They summarize weighted dispersion of included bar prices. They do not establish future return probabilities or a mean-reversion edge.
Why does another VWAP indicator show a different value?
Check the price source, anchor convention, timezone, timeframe, session and data feed. HLC3 and OHLC4 calculations can differ even with similar names.
Does the script identify institutional activity?
No. The calculation uses chart price and volume. Those inputs do not identify who traded or which positions they still hold.
Has this tutorial demonstrated trading profitability?
No. It supplies indicator calculations and validation checks. A profitable strategy would require separately specified trading rules and reproducible evidence after costs.

