Generating a Fixed-Range Volume Profile from OHLCV Data

Published on October 20, 2025

Volume Profile reveals where the majority of trading activity occurred within a range — a powerful insight for understanding market behavior. In this post, we’ll see how to generate a fixed-range volume profile from OHLCV data using Python. It is advisable that such volume profile is always generated on most granular data that is available. More granular data is used, more accurate it is.

1. Understanding the Inputs

timestamp, open, high, low, close, volume
2025-10-15 09:15, 21600, 21620, 21570, 21595, 125000
2025-10-15 09:16, 21595, 21610, 21580, 21605, 98000
...

2. Creating Price Buckets


price_min = df['low'].min()
price_max = df['high'].max()
bucket_size = 10
bins = np.arange(price_min, price_max + bucket_size, bucket_size)

3. Distributing Volume


for _, row in df.iterrows():
    price_range = np.arange(row['low'], row['high'] + bucket_size, bucket_size)
    vol_per_bucket = row['volume'] / len(price_range)
    for p in price_range:
        volume_profile[p] += vol_per_bucket

4. Interpreting the Profile

This POC (or LOC, line of control) is the price which will also act as a good resistance or support. Mostly, traders track the changing PoC to understand whether any reversal is about to come or not. This is one of my tools (in addition to Anchored VWAP) to take quick fire, momentum based trades.

Same concept can be used at higher timeframes (calculation will still occur at lowest possible timeframe) to understand positional trends.