Volume Profile (Maps)

Works on the Following Platforms
The Pine Script® developers have unleashed "maps"!
Volume Profile (Maps) displays volume, associated with price, above and below the latest price, by using maps
The largest and second-largest volume is highlighted.
USAGE
The proposed script can highlight more frequent closing prices/prices with the highest volume, potentially highlighting more liquid areas. The prices with the highest associated volume (in red and orange in the indicator) can eventually be used as support/resistance levels.
Voids within the volume profile can highlight large price displacements (volatile variations).
CONCEPTS
Maps
A map object is a collection that consists of key-value pairs
Each key is unique and can only appear once. When adding a new value with a key that the map already contains, that value replaces the old value associated with the key. You can change the value of a particular key though, for example adding volume (value) at the same price (key), the latter technique is used in this script.
- Volume is added to the map, associated with a particular price (default close, can be set at high, low, open,...)
- When the map already contains the same price (key), the value (volume) is added to the existing volume at the associated price.
A map can contain maximum 50K values, which is more than enough to hold 20K bars (Basic 5K - Premium plan 20K), so the whole history can be put into a map.
Visible line/box limit
We can only display maximum 500 line.new() though. The code locates the current (last) close, and displays volume values around this price, using lines, for example 250 lines above and 250 lines below current price. If one side contains fewer values, the other side can show more lines, taking the maximum out of the 500 visible line limitation.
Example (max. 500 lines visible) • 100 values below close • 2000 values above close
-
100 values will be displayed below close
-
400 remaining -> 400 values will be displayed above close
Pushing the limits even further, when 'Amount of bars' is set higher than 500, boxes - box.new() - will be used as well. These have a limit of 500 as well, bringing the total limit to 1000.
Note that there are visual differences when boxes overlap against lines.
If this is confusing, please keep 'Amount of bars' at max. 500 (then only lines will be used).
Rounding function
This publication contains 2 round functions, which can be used to widen the Volume Profile
- Round
• "Round" set at zero -> nothing changes to the source number • "Round" set below zero -> x digit(s) after the decimal point, starting from the right side, and rounded. • "Round" set above zero -> x digit(s) before the decimal point, starting from the right side, and rounded.
Example: 123456.789
0->123456.789 1->123456.79 2->123456.8 3->123457
- 1->123460
- 2->123500
- Step
Another option is custom steps. After setting "Round" to "Step", choose the desired steps in price,
Examples • 2 -> 1234.00, 1236.00, 1238.00, 1240.00 • 5 -> 1230.00, 1235.00, 1240.00, 1245.00 • 100 -> 1200.00, 1300.00, 1400.00, 1500.00 • 0.05 -> 1234.00, 1234.05, 1234.10, 1234.15 •••
FEATURES
Adjust position & width
Table
The table shows the details: • Size originalMap: amount of elements in original map • # higher: amount of elements, higher than last "close" (source) • index "close": index of last "close" (source), or # element, lower than source • Size newMap: amount of elements in new map (used for display lines) • # higher: amount of elements in newMap, higher than last "close" (source) • # lower: amount of elements in newMap, lower than last "close" (source)
Volume * currency
Let's take as example BTCUSD, relative to USD, 10 volume at a price of 100 BTCUSD will be very different than 10 volume at a price of 30000 (1K vs. 300K) If you want volume to be associated with USD, enable Volume * currency. Volume will then be multiplied by the price: • 10 volume, 1 BTC = 100 -> 1000 • 10 volume, 1 BTC = 30K -> 300K
Disabled
Enabled
DETAILS
Put
When the map doesn't contain a price, it will be added, using map.put(id, key, value) In our code:
or
originalMap.put(price, volume)```
A key (price) is now associated with a value (volume) -> *key : value*
Since all keys are unique, we don't have to know its position to extract the value, we just need to know the key -> [map.get(id, key) ](https://www.tradingview.com/pine-script-reference/v5/#fun_map.get)
We use *map.get()* when a certain key already exists in the map, and we want to add volume with that value.
```if originalMap.contains(price)
originalMap.put(price, originalMap.get(price) + volume)```
- > At the last bar, all prices (source) are now associated with volume.
## Copy & sort
Next, every key of the map is copied and sorted (array of keys), after which the index (idx) is retrieved of last (current) price.
copyK = originalMap.keys().copy()
copyK.sort()
idx = copyK.binary_search_leftmost(src)
Then left and right side of idx is investigated to show a maximum amount of lines at both sides of last price.
## New map & display
The keys (from sorted array of copied keys) that will be displayed are put in a new map, with the associated volume values from the original map.
```newMap = map.new<float, float>()```
## Re-cap
• put in original amp (price key, volume value)
• copy & sort
• find index of last price
• fetch relevant keys left/right from that index
• put keys in new map and fetch volume associated with these keys (from original map)
Simple example (only show 5 lines)
bar 0, price = 2, volume = 23 bar 1, price = 4, volume = 3 bar 2, price = 8, volume = 21 bar 3, price = 6, volume = 7 bar 4, price = 9, volume = 13 bar 5, price = 5, volume = 85 bar 6, price = 3, volume = 13 bar 7, price = 1, volume = 4 bar 8, price = 7, volume = 9
Original map: [2:23, 4:3, 8:21, 6:7, 9:13, 5:85, 3:13, 1:4, 7:9] Copied keys array: [2, 4, 8, 6, 9, 5, 3, 1, 7] Sorted: [1, 2, 3, 4, 5, 6, 7, 8, 9]
-
5 keys around last price (7) are fetched (5, 6, 7, 8, 9)
-
keys are placed into new map + volume values from original map
[5:85, 6:7, 7:9, 8:21, 9:13]
Lastly, these values are displayed.
# SETTINGS
- *Source*: Set source of choice; default *close*, can be set as *high*, *low*, *open*, ...
- *Volume & currency*: Enable to multiply volume with price (see *Features*)
- *Amount of bars*: Set amount of bars which you want to include in the *Volume Profile*
- *Max lines*: maximum 1000 (if you want to use only lines, and no boxes -> max. 500, see *Concepts*)
## Round -> '*Round/Step*'
- Round -> see *Concepts*
- Step -> see *Concepts*
## Display Volume Profile
- Offset: shifts the Volume Profile (max. 500 bars to the right of last bar, see *Features*)
- Max width Volume Profile: largest volume will be x bars wide, the rest is displayed as a ratio against largest volume (see *Features*)
- *Show table*: Show details (see *Features*)
# LIMITATIONS
• Lines won't go further than first bar (coded).
• The Volume Profile can be placed maximum 500 bar to the right of last price.
• Maximum 500 lines/boxes can be displayed
Trading is risky and many will lose money in connection with trading activities. All content on this site is not intended to, and should not be, construed as financial advice. Decisions to buy, sell, hold or trade in securities, commodities and other markets involve risk and are best made based on the advice of qualified financial professionals. Past performance does not guarantee future results.
Hypothetical or Simulated performance results have certain limitations. Unlike an actual performance record, simulated results do not represent actual trading. Also, since the trades have not been executed, the results may have under-or-over compensated for the impact, if any, of certain market factors, including, but not limited to, lack of liquidity. Simulated trading programs in general are designed with the benefit of hindsight, and are based on historical information. No representation is being made that any account will or is likely to achieve profit or losses similar to those shown.
Testimonials appearing on this website may not be representative of other clients or customers and is not a guarantee of future performance or success.
As a provider of technical analysis tools for charting platforms, we do not have access to the personal trading accounts or brokerage statements of our customers. As a result, we have no reason to believe our customers perform better or worse than traders as a whole based on any content or tool we provide.
Charts used on this site are by TradingView in which the majority of our tools are built on. TradingView® is a registered trademark of TradingView, Inc. www.TradingView.com. TradingView® has no affiliation with the owner, developer, or provider of the Services described herein.
This does not represent our full Disclaimer. Please read our full disclaimer.
© 2025 LuxAlgo Global, LLC.