---
title: Volume Profile Functions
description: 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`](../core-concepts/data-sources.md) 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.

Open the source first, then pass it to any accessor:

```javascript title="Opening a volume_profile source" lines wrap
timeseries vpa = volume_profile(symbol=currentSymbol, exchange=currentExchange);
var totalBuy  = vpBuy(vpa);
var totalSell = vpSell(vpa);
var poc       = vpPoc(vpa);
```

| Function                          | Description                                              |
| --------------------------------- | -------------------------------------------------------- |
| [`vpBuy`](#vpbuy)                 | Total buy volume across all price buckets at the bar     |
| [`vpSell`](#vpsell)               | Total sell volume across all price buckets at the bar    |
| [`vpDelta`](#vpdelta)             | Net buy/sell delta (`vpBuy − vpSell`) at the bar         |
| [`vpTotal`](#vptotal)             | Combined buy + sell volume across all buckets at the bar |
| [`vpPoc`](#vppoc)                 | Point of Control — price of the highest-volume bucket    |
| [`vpPocVolume`](#vppocvolume)     | Combined volume at the POC bucket                        |
| [`vpBucketCount`](#vpbucketcount) | Number of price-level buckets at the bar                 |
| [`vpPriceHigh`](#vppricehigh)     | Highest price covered by the profile at the bar          |
| [`vpPriceLow`](#vppricelow)       | Lowest 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.

| Parameter | Type       | Description                  |
| --------- | ---------- | --------------------------- |
| `source`  | TimeSeries | A `volume_profile` timeseries |

**Returns:** `number` — total buy volume at this bar.

```javascript
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.

| Parameter | Type       | Description                  |
| --------- | ---------- | --------------------------- |
| `source`  | TimeSeries | A `volume_profile` timeseries |

**Returns:** `number` — total sell volume at this bar.

```javascript
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.

| Parameter | Type       | Description                  |
| --------- | ---------- | --------------------------- |
| `source`  | TimeSeries | A `volume_profile` timeseries |

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

```javascript
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.

| Parameter | Type       | Description                  |
| --------- | ---------- | --------------------------- |
| `source`  | TimeSeries | A `volume_profile` timeseries |

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

```javascript
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.

| Parameter | Type       | Description                  |
| --------- | ---------- | --------------------------- |
| `source`  | TimeSeries | A `volume_profile` timeseries |

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

```javascript
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).

| Parameter | Type       | Description                  |
| --------- | ---------- | --------------------------- |
| `source`  | TimeSeries | A `volume_profile` timeseries |

**Returns:** `number` — volume at the POC bucket.

```javascript
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.

| Parameter | Type       | Description                  |
| --------- | ---------- | --------------------------- |
| `source`  | TimeSeries | A `volume_profile` timeseries |

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

```javascript
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).

| Parameter | Type       | Description                  |
| --------- | ---------- | --------------------------- |
| `source`  | TimeSeries | A `volume_profile` timeseries |

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

```javascript
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).

| Parameter | Type       | Description                  |
| --------- | ---------- | --------------------------- |
| `source`  | TimeSeries | A `volume_profile` timeseries |

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

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

## Best Practices

<table data-view="cards"><tbody>
<tr><td>Always Use Accessors</td><td>The `volume_profile` source has no scalar properties — reading `.buy` / `.sell` directly will not work. Pull every value through the `vp*` accessors.</td><td></td></tr>
<tr><td>Watch the POC</td><td>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.</td><td></td></tr>
<tr><td>Read Delta for Pressure</td><td>`vpDelta` summarizes net aggressor flow per bar. Sustained positive delta signals buy-side control; sustained negative delta signals sell-side control.</td><td></td></tr>
</tbody></table>
