Functions

Volume Profile Functions

Accessor functions for the volume_profile source — extract buy/sell volume, delta, point of control, and price range from each bar's price-level ladder.

The volume_profile source carries a variable number of price-level buckets per bar — each bucket is [priceLow, priceHigh, buyVol, sellVol]. Because the bucket count changes from bar to bar, the source has no scalar properties; you can't read .buy / .sell off it directly. Instead, use these accessor functions to pull scalar timeseries out of the profile.

Data structure

Each bar of a volume_profile timeseries is a row shaped like:

[ timestamp, [priceLow, priceHigh, buyVol, sellVol], [priceLow, priceHigh, buyVol, sellVol], … ]
  • Slot 0 is the bar timestamp.
  • Every later slot is one price-level bucket: [priceLow, priceHigh, buyVol, sellVol].
  • The number of buckets varies per bar — it depends on the bar's price range and ticksPerBar.

For scalar values, prefer the vp* accessors below. To iterate the buckets yourself — e.g. to draw one marker or pie per price level with plotBatches — read the raw row directly: vpa[0] is the current bar's row, and vpa[0][i + 1] is the i-th bucket (slot 0 is the timestamp):

Raw bucket access
timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);

func drawBucket(i) {
  var bucket  = vpa[0][i + 1];                 // [priceLow, priceHigh, buyVol, sellVol]
  var price   = (bucket[0] + bucket[1]) / 2;   // bucket midprice
  var buyVol  = bucket[2];
  var sellVol = bucket[3];
  plotPie(value=[buyVol, sellVol], price=price, radius=8, colors=["#22c55e", "#ef4444"], display="none");
}
plotBatches(vpBucketCount(vpa), drawBucket);

Accessor functions

Open the source first, then pass it to any accessor. Besides the required symbol and exchange, it accepts an optional ticksPerBar (default 1) that merges every N price levels into one bucket — fewer, wider buckets, which lowers vpBucketCount — and an optional currency ("USD" or "Coin", default "Coin") that quotes each bucket's volume in USD (dollar notional) instead of coins (base-asset units), mirroring the Volume Footprint indicator's currency toggle:

Opening a volume_profile source
timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);
var totalBuy  = vpBuy(vpa);
var totalSell = vpSell(vpa);
var poc       = vpPoc(vpa);

// Optional: coarsen the ladder (merge every 5 price levels into one bucket)
timeseries vpaCoarse = volume_profile(symbol=currentSymbol, exchange=currentExchange, ticksPerBar=5);

// Optional: quote bucket volume in USD (dollar notional) instead of coins
timeseries vpaUsd = volume_profile(symbol=currentSymbol, exchange=currentExchange, currency="USD");
FunctionDescription
vpBuyTotal buy volume across all price buckets at the bar
vpSellTotal sell volume across all price buckets at the bar
vpDeltaNet buy/sell delta (vpBuy − vpSell) at the bar
vpTotalCombined buy + sell volume across all buckets at the bar
vpPocPoint of Control — price of the highest-volume bucket
vpPocVolumeCombined volume at the POC bucket
vpBucketCountNumber of price-level buckets at the bar
vpPriceHighHighest price covered by the profile at the bar
vpPriceLowLowest price covered by the profile at the bar

vpBuy

vpBuy(source: TimeSeries): number — total buy volume summed across all price-level buckets at the current bar.

ParameterTypeDescription
sourceTimeSeriesA volume_profile timeseries

Returns: number — total buy volume at this bar.

timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);
timeseries totalBuy = vpBuy(vpa);
plotLine(value=totalBuy, colors=["#26a69a"], width=2, label=["Total Buy"], desc=["Sum of buy volume per bar"]);

vpSell

vpSell(source: TimeSeries): number — total sell volume summed across all price-level buckets at the current bar.

ParameterTypeDescription
sourceTimeSeriesA volume_profile timeseries

Returns: number — total sell volume at this bar.

timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);
timeseries totalSell = vpSell(vpa);
plotLine(value=totalSell, colors=["#ef5350"], width=2, label=["Total Sell"], desc=["Sum of sell volume per bar"]);

vpDelta

vpDelta(source: TimeSeries): number — net buy/sell delta at the current bar (vpBuy − vpSell). Positive = buy dominant, negative = sell dominant.

ParameterTypeDescription
sourceTimeSeriesA volume_profile timeseries

Returns: number — buy minus sell volume at this bar.

timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);
timeseries delta = vpDelta(vpa);
plotBar(value=delta, colors=["#26a69a", "#ef5350"], label=["Delta"], desc=["Net buy/sell pressure"]);

vpTotal

vpTotal(source: TimeSeries): number — total volume (buy + sell) summed across all buckets at the current bar.

ParameterTypeDescription
sourceTimeSeriesA volume_profile timeseries

Returns: number — combined buy + sell volume at this bar.

timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);
timeseries total = vpTotal(vpa);
plotLine(value=total, colors=["#9e9e9e"], width=2, label=["Total"], desc=["Combined volume"]);

vpPoc

vpPoc(source: TimeSeries): number — Point of Control: the midprice of the bucket with the highest combined buy + sell volume at the current bar.

ParameterTypeDescription
sourceTimeSeriesA volume_profile timeseries

Returns: number — POC price (NaN if no buckets at this bar).

timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);
timeseries poc = vpPoc(vpa);
plotLine(value=poc, colors=["#ff9800"], width=2, label=["POC"], desc=["Point of Control"]);

vpPocVolume

vpPocVolume(source: TimeSeries): number — combined buy + sell volume at the POC bucket (the bucket with the highest combined volume).

ParameterTypeDescription
sourceTimeSeriesA volume_profile timeseries

Returns: number — volume at the POC bucket.

timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);
timeseries pocVol = vpPocVolume(vpa);

vpBucketCount

vpBucketCount(source: TimeSeries): number — number of price-level buckets present at the current bar.

ParameterTypeDescription
sourceTimeSeriesA volume_profile timeseries

Returns: number — count of price buckets at this bar.

timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);
timeseries depth = vpBucketCount(vpa);

vpPriceHigh

vpPriceHigh(source: TimeSeries): number — highest priceHigh across all buckets at the current bar (top of the volume-profile range).

ParameterTypeDescription
sourceTimeSeriesA volume_profile timeseries

Returns: number — highest price covered by the profile (NaN if empty).

timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);
timeseries top = vpPriceHigh(vpa);

vpPriceLow

vpPriceLow(source: TimeSeries): number — lowest priceLow across all buckets at the current bar (bottom of the volume-profile range).

ParameterTypeDescription
sourceTimeSeriesA volume_profile timeseries

Returns: number — lowest price covered by the profile (NaN if empty).

timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);
timeseries bottom = vpPriceLow(vpa);

Best Practices

Always Use Accessors
The volume_profile source has no scalar properties — reading .buy / .sell directly will not work. Pull every value through the vp* accessors.
Watch the POC
The Point of Control marks the price with the most traded volume and often acts as a magnet for price. Pair vpPoc with vpPocVolume to gauge how dominant that level is.
Read Delta for Pressure
vpDelta summarizes net aggressor flow per bar. Sustained positive delta signals buy-side control; sustained negative delta signals sell-side control.