Equivolume - volume as candle width
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © ant_tv

// Inspired by NinjaTrader's Equivolume candles: https://ninjatrader.com/blog/combine-price-volume-with-new-equivolume-charts/

//@version=5
indicator("Equivolume candles", overlay=true, max_lines_count=500, max_boxes_count=500)

// User configurable parameters
lookback_choice = input.int(title='Lookback candle count', defval=500, maxval=500, minval=1, tooltip='A maximum of 500 candles can be displayed with volume information')
use_color = input.bool(title='Use color', defval=false, tooltip='Vary transparency of candle to indicate relative volume')
use_width = input.bool(title='Use width', defval=true, tooltip='Vary width of candle to indicate relative volume')
bar_width_multiplier = input.int(20, title='Candle width multiplier', minval=1, maxval=50, tooltip='Increase the width of the candles to show volume more clearly')
show_closing_price_line = input.bool(title='Show closing price line', defval=true, tooltip='Shows background closing price line graph for context')
transparency_choice = input.string(title="Transparency range", defval="Medium", options=["High", "Medium", "Low"], tooltip='Alters how transparent low volume candles appear')
bull_color = input.color(title='Bull color', defval=color.green)
bear_color = input.color(title='Bear color', defval=color.red)

transparency_level = switch transparency_choice
    "High" => 100
    "Medium" => 75
    "Low" => 50

bars_available = ta.barssince(barstate.isfirst)

lookback_candles = lookback_choice > bars_available 
     ? bars_available 
     : lookback_choice

max_volume = ta.highest(volume, lookback_candles + 1)

plot(show_closing_price_line ? close : na, color=color.new(color.blue, transparency_level - 25))
plotchar(volume, title='Volume', char='', color=color.new(color.purple, 100))

if barstate.islast
    for i = lookback_candles to 0
        relative_volume = volume[i] / max_volume
        
        color = close[i] >= open[i] ? bull_color : bear_color
        
        color_alpha = color.new(color, (1 - relative_volume) * transparency_level) 
        bar_width = int(relative_volume * bar_width_multiplier)

        candle_color = use_color ? color_alpha : color
        
        // Candle wick (use boxes rather than lines here so I can use box and line limit of 500 for each)
        box.new(
             bar_index[i], 
             high[i], 
             bar_index[i], 
             low[i], 
             border_width=1,
             bgcolor=candle_color,
             border_color=candle_color)
             
        // Candle body
        line.new(
             bar_index[i], 
             open[i], 
             bar_index[i], 
             close[i], 
             width=use_width ? bar_width : 3, 
             color=candle_color)
        

