Volume Profile (Maps) [LuxAlgo]

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.


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


🔹 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 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 - - 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

  1. 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


  2. Step

    Another option is custom steps.
    After setting "Round" to "Step", choose the desired steps in price,

    •     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


🔹 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



🔹 Put

When the map doesn't contain a price, it will be added, using map.put(id, key, value)
In our code:
map.put(originalMap, price,  volume)
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)
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()
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 =<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.


  • 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)


• 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

Get Access to LuxAlgo indicators:

Join our 100k+ community:

All scripts & content provided by LuxAlgo are for informational & educational purposes only. Past performance does not guarantee future results.
Script de código abierto

Siguiendo el verdadero espíritu de TradingView, el autor de este script lo ha publicado en código abierto, para que los traders puedan entenderlo y verificarlo. ¡Un hurra por el autor! Puede utilizarlo de forma gratuita, aunque si vuelve a utilizar este código en una publicación, debe cumplir con lo establecido en las Normas internas. Puede añadir este script a sus favoritos y usarlo en un gráfico.

Exención de responsabilidad

La información y las publicaciones que ofrecemos, no implican ni constituyen un asesoramiento financiero, ni de inversión, trading o cualquier otro tipo de consejo o recomendación emitida o respaldada por TradingView. Puede obtener información adicional en las Condiciones de uso.

¿Quiere utilizar este script en un gráfico?