Indicator · Pine Script v4 · On the chart

Equivolume Bars

by regalouisei· code credited to rumpypumpydumpy

Equivolume Bars displays custom candlestick boxes on the main price chart, where each bar's width is proportional to its volume relative to a rolling lookback sum.

View on GitHub

GitHub stars2on the repository
Pine versionv4older, still runs
Lines of code197
Settings9inputs
LicenceNone statedfile: MPL-2.0
Last update8 months ago25 Feb 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

197 lines of Pine Script v4 from pinescript/editors_picks/equivolume-bars.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

equivolume-bars.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © rumpypumpydumpy

//@version=4
study("Equivolume Bars", overlay = true, max_boxes_count = 500, scale = scale.right)

num_boxes =     input(165, title = "Number of equivolume boxes to display", maxval = 165, tooltip = "Maximum 165")
lb =            input(60, title = "Volume lookback", tooltip = "Number of bars to sum")
full_width =    input(500, title = "Full width in number of bars", tooltip = "Width where current bar's volume = sum of volume lookback\nHigher values result in less rounding with the trade off of using more chart space")
up_col =        input(color.white, title = "Up bar color")
dn_col =        input(color.blue, title = "Down bar color")
hl_col =        input(color.gray, title = "Wick color")
border_col =    input(color.rgb(255, 255, 255, 66), title = "Border color")
top_perc =    input(8, title = "Top margin %")
bottom_perc = input(20, title = "Bottom margin %")



// -----------------------------------------------------------------------------
// Equivolume Calculation
// -----------------------------------------------------------------------------
float   sum_volume =    sum(volume, lb)
float   ratio =         volume / sum_volume[1]
int     width =         max(round(ratio * full_width), 1) // Determines width of equivolume box in bars
// -----------------------------------------------------------------------------



// -----------------------------------------------------------------------------
// Current live bar
// -----------------------------------------------------------------------------
var box current_body =  box.new(left = na, top = na, right = na, bottom = na, border_width = 1, border_color = border_col)
var box current_high =  box.new(left = na, top = na, right = na, bottom = na, border_width = 1, border_color = border_col, bgcolor = hl_col)
var box current_low =   box.new(left = na, top = na, right = na, bottom = na, border_width = 1, border_color = border_col, bgcolor = hl_col)

box.set_lefttop(current_body,       left = bar_index,           top = max(close,open))
box.set_rightbottom(current_body,   right = bar_index + width,  bottom = min(close, open))

box.set_bgcolor(current_body,       color = close >= open ? up_col : dn_col)

box.set_lefttop(current_high,       left = bar_index,           top = high)
box.set_rightbottom(current_high,   right = bar_index + width,  bottom = max(close, open))

box.set_lefttop(current_low,        left = bar_index,           top = min(close, open))
box.set_rightbottom(current_low,    right = bar_index + width,  bottom = low)
// -----------------------------------------------------------------------------



// -----------------------------------------------------------------------------
// Historical bars
// -----------------------------------------------------------------------------

// Historical bar values
var float[] historical_body_tops = array.new_float(num_boxes)
var float[] historical_body_bottoms = array.new_float(num_boxes)
var float[] historical_highs = array.new_float(num_boxes)
var float[] historical_lows = array.new_float(num_boxes)
var bool[]  historical_direction = array.new_bool(num_boxes)
var int[]   historical_widths = array.new_int(num_boxes)

// Historical equivolume boxes
var box[]   historical_bodies = array.new_box(na)
var box[]   historical_high_wicks = array.new_box(na)
var box[]   historical_low_wicks = array.new_box(na)

// Initialize historical box arrays
if barstate.isfirst
    for i = 0 to num_boxes - 1
        array.unshift(historical_bodies,        box.new(left = na, top = na, right = na, bottom = na, border_width = 1, border_color = border_col))
        array.unshift(historical_high_wicks,    box.new(left = na, top = na, right = na, bottom = na, border_width = 1, border_color = border_col, bgcolor = hl_col))
        array.unshift(historical_low_wicks,     box.new(left = na, top = na, right = na, bottom = na, border_width = 1, border_color = border_col, bgcolor = hl_col))
        
// Once the current live bar is on it's last update
if barstate.isconfirmed
    // Add the latest bar's values to historical arrays and remove the oldest
    array.unshift(historical_body_tops, max(open, close)),      array.pop(historical_body_tops)
    array.unshift(historical_body_bottoms, min(open, close)),   array.pop(historical_body_bottoms)
    array.unshift(historical_highs, high),                      array.pop(historical_highs)
    array.unshift(historical_lows, low),                        array.pop(historical_lows)
    array.unshift(historical_direction, close >= open),         array.pop(historical_direction)
    array.unshift(historical_widths, width),                    array.pop(historical_widths)
    
    int offset = 0 // used to track the starting bar_index for subsequent historical bars
    
    for i = 0 to num_boxes - 1
        // Ensure we don't try and draw on a negative bar index
        if offset < bar_index
            // get values for historical bar : i
            high_box =  array.get(historical_high_wicks, i)
            low_box =   array.get(historical_low_wicks, i)
            body_box =  array.get(historical_bodies, i)
            box_width = array.get(historical_widths, i)
        
            left_index =    bar_index - offset - box_width
            right_index =   bar_index - offset
        
            body_top_val =      array.get(historical_body_tops, i)
            body_bottom_val =   array.get(historical_body_bottoms, i)
            high_val =          array.get(historical_highs, i)
            low_val =           array.get(historical_lows, i)
            up_bar =            array.get(historical_direction, i)
            
            //update offset for next historical bar
            offset := offset + box_width + 1        

            // adjust box properties for historical bar
            box.set_lefttop(body_box, left = left_index, top = body_top_val)
            box.set_rightbottom(body_box, right = right_index, bottom = body_bottom_val)
            box.set_bgcolor(body_box, color = up_bar ? up_col : dn_col)
        
            box.set_lefttop(high_box, left = left_index, top = high_val)
            box.set_rightbottom(high_box, right = right_index, bottom = body_top_val)
        
            box.set_lefttop(low_box, left = left_index, top = body_bottom_val)
            box.set_rightbottom(low_box, right = right_index, bottom = low_val)
        else
            break
// -----------------------------------------------------------------------------



// -----------------------------------------------------------------------------
// Setup margin lines
// -----------------------------------------------------------------------------

var line top_margin_line = line.new(x1 = na, y1 = na, x2 = na, y2 = na, extend = extend.both, color = color.rgb(0, 0, 0, 100))
var line bottom_margin_line = line.new(x1 = na, y1 = na, x2 = na, y2 = na, extend = extend.both, color = color.rgb(0, 0, 0, 100))

hh = highest(high, num_boxes)
ll = lowest(low, num_boxes)
range = hh - ll
bars_perc = 100 - top_perc - bottom_perc
interval = range / bars_perc
top_margin = hh + interval * top_perc
bottom_margin = ll - interval * bottom_perc

line.set_xy1(top_margin_line, x = bar_index, y = top_margin)
line.set_xy2(top_margin_line, x = bar_index + 1, y = top_margin)
line.set_xy1(bottom_margin_line, x = bar_index, y = bottom_margin)
line.set_xy2(bottom_margin_line, x = bar_index + 1, y = bottom_margin)

View in Pine Editor・141 lines
Use on chart
8
5
7
23
18 856
Nov 15, 2020
Equivolume bars. Width is determined by volume. Please note that equivolume bars are rendered independently of the time scale.

Makes use of LonesomeTheBlue's "Start the Script on Last Nth Bar" in order to prevent time out. As such you are only able to view the most recent bars and no bar replay beyond that range.
Nov 16, 2020
Release Notes
Added a secondary style which makes OHLC visible. With the new style the left vertical line is always the low, right vertical line the high. Horizontal lines are shift to open/close.
Jul 9, 2021
Release Notes
Referencing length error fix
Jul 22, 2021
Release Notes
Major update
Complete rewrite to take advantage of new box() functions.

Instructions

This has been coded in a specific way due to certain chart properties being inaccessible via Pine. It requires a few simple manual steps to be set up correctly.

First add the equivolume indicator(s) to your chart

Next from the chart toolbar, change the chart type to line chart.

Then from the chart settings (right click chart / Settings). Under the Symbol section, change the Line color opacity to 0 (fully transparent).

From the chart settings in the Appearance section, set the top and bottom margins to 0 (Margins will be controlled from within the script).

Next set the chart's ticker scale to no scale (the three dot symbol to the right of the ticker id on the chart itself), select Pin to scale / No scale (fullscreen)

Then lastly, set the indicator(s) scales the same way, but make sure they are pinned to the same left or right scale (usually A). It doesn't matter which as long it's the same one.
The exception is the volume bar overlay which should be set to no scale as well.

If you change any of the margin settings / equivolume settings you need to ensure they are copied over to the other overlays to ensure that everything is positioned the same.

At this point, zoom out to ensure the full bar set is loaded. Everything should line up at this point and you can zoom back in if you want to.

The available addons for equivolume can be found here
Open-source script

In true TradingView spirit, the creator of this script has made it open-source, so that traders can review and verify its functionality. Kudos to the author! While you can use it for free, remember that republishing the code is subject to our House Rules.

rumpypumpydumpy
WIZARD
Follow
equivolume
Volume
Disclaimer
The information and publications are not meant to be, and do not constitute, financial, investment, trading, or other types of advice or recommendations supplied or endorsed by TradingView. Read more in the Terms of Use.

Overview

The script calculates volume ratios to stretch or shrink historical and live price bodies and wicks using box drawings. Users can configure the volume lookback period, maximum displayed boxes, width scaling, and color preferences for up bars, down bars, and wicks. It draws directly overlaying price to visually emphasize high-volume candles.

Details

Published by

regalouisei on GitHub

Code credit

rumpypumpydumpy, as written in the script's header

Type

Indicator, Pine Script v4

Draws

On the price chart

Category

Volume, Candlestick patterns

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Number of equivolume boxes to displayint165num_boxes
Volume lookbackint60lb
Full width in number of barsint500full_width
Up bar colorcolorcolor.whiteup_col
Down bar colorcolorcolor.bluedn_col
Wick colorcolorcolor.grayhl_col
Border colorcolorcolor.rgb(255, 255, 255, 66)border_col
Top margin %int8top_perc
Bottom margin %int20bottom_perc
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

Vector Candles

by benso87
24 stars

Vector Candles is an overlay indicator that recolors price candles using PVSRA volume rules taken from the Traders Reality concept. It compares each bar's volume with the average of the previous ten bars and also checks the product of spread and volume against

Indicator v5 VolumeCandlestick patterns
Updated 4 years ago · MPL-2.0 GitHub repository of Vector Candles
23 stars

Point-Clip Unified Indicator plots breakout and directional labels on the price chart. It scores volume spikes against a volume average, range or opening-range breaks, optional VWAP or session-anchored VWAP, fast and slow EMA trend, and a higher-timeframe EMA

Indicator v6 BreakoutVolume Repaints
Updated 3 weeks ago · Custom licence GitHub repository of Point-Clip Unified Indicator
4 stars

This indicator recolors price candles from recent volume and range. It marks climax bars when current volume times range exceeds the prior ten-bar peak or volume is at least twice a ten-bar average, and rising bars at one and a half times that average. Bullish

Indicator v5 VolumeCandlestick patterns
Updated 9 months ago · None stated GitHub repository of Price-Volume Analysis

This overlay indicator draws rounded psychological price levels and optional PVSRA vector candle colors on the price chart. It plots quarter, half, and whole levels from a user-set rounding value, with separate color, line style, and width for each. Vector col

Indicator v5 Support & resistanceVolume
Updated 5 months ago · None stated GitHub repository of Level Theory + Vector Candles

Stella's Smart Money Proxy

by stella-entry
3 stars

This indicator detects institutional or large-scale market activity using candle body size and trading volume. It compares current candle bodies against a 20-period simple moving average and checks for volume spikes above an adjustable moving average filter. I

Indicator v6 VolumeCandlestick patterns
Updated 8 months ago · MIT GitHub repository of Stella's Smart Money Proxy

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers