本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。
//@version=3
study("Volume Profile Free MAX SLI by RRB", shorttitle="VolumeProfileFree_MAX_RRB", overlay=true)
// Volume Profile Free MAX SLI by RagingRocketBull 2019
// Version 1.0
// All available Volume Profile Free MAX SLI versions are listed below (They are very similar and I don't want to publish them as separate indicators):
// ver 1.0: style columns implementation
// ver 2.0: style histogram implementation
// ver 3.0: style line implementation
//
// Differences between implementations:
//
// ver 1.0: ver 2.0 ver 3.0
// - style columns - style histogram - style line
// - manual min/max level - manual min/max level - manual min/max level
// - fixed 100% base width - fixed 100% base width - fixed 100% base width
// - hist_base (ugly redraw) - hist_base (ugly redraw) - no hist_base (cleaner redraw)
// - no level density (equalizer) - level density control (more solid) - line width control (outline from level center)
// - level gaps auto fill - level gaps auto fill - manual level height adjustments for normal/log
// - manual spacing - manual spacing - no spacing control, only width + compensation
// - better transparency - less transparency (density is in the way) - better transparency
//
//
// This indicator calculates Volume Profile for a given range and shows it as a histogram consisting of 50 horizontal bars.
// It can also show Point of Control (POC), Developing POC, Value Area/VWAP StdDev High/Low as dynamically moving levels.
// Free accounts can't access Standard TradingView Volume Profile, hence this indicator.
//
// There are several versions: Free Pro, Free MAX SLI, Free History. This is the Free MAX SLI version. The Differences are listed below:
// - Free Pro: 25 levels, +Developing POC, Value Area/VWAP High/Low Levels, Above/Below Area Dimming
// - Free MAX SLI: 50 levels, packed to the limit, 2x SLI modes for Buy/Sell or even higher res 150 levels
// - Free History: auto highest/lowest, historic poc/va levels for each session
//
// Features:
// - High-Res Volume Profile with up to 50 levels (3 implementations)
// - 20-30x faster than the old Pro versions especially on lower tfs with long history
// - 2x SLI modes for even higher res: 150 levels with 3x vertical SLI, 50 buy/sell levels with 2x horiz SLI
// - Calculate Volume Profile on full history
// - POC, Developing POC Levels
// - Buy/Sell/Total volume modes
// - Side Cover
// - Value Area, VAH/VAL dynamic levels
// - VWAP High/Low dynamic levels with Source, Length, StdDev as params
// - Show/Hide all levels
// - Dim Non Value Area Zones
// - Custom Range with Highlighting
// - 3 Anchor points for Volume Profile
// - Flip Levels Horizontally
// - Adjustable width, offset and spacing of levels
// - Custom Color for POC/VA/VWAP levels and Transparency for buy/sell levels
//
// Usage:
// - specify max_level/min_level/spacing (required)
// - select range (start_bar, range length), confirm with range highlighting
// - select volume type: Buy/Sell/Total
// - select mode Value Area/VWAP to show corresponding levels
// - flip/select anchor point to position the buy/sell levels
// - use Horiz SLI mode for 50 Buy/Sell or Vertical SLI for 150 levels if needed
// - use POC/Developing POC/VA/VWAP High/Low as S/R levels. Usually daily values from 1-3 days back are used as levels for the current day.
//
// SLI:
// - use SLI modes to extend the functionality of the indicator:
// - Horiz Buy/Sell 2x SLI lets you view 50 Buy/Sell Levels at the same time
// - Vertical Max_Vol 3x SLI lets you increase the resolution to 150 levels
// - you need at least 2 instances of the indicator attached to the same chart for SLI to work
//
// 1) Enable Horiz SLI:
// - attach 2 indicator instances to the chart
// - make sure all instances have the same min_level/max_level/range/spacing settings
// - select volume type for each instance: you can have a buy/sell or buy/total or sell/total SLI. Make sure your buy volume instance is the last attached to be displayed on top of sell/total instances without overlapping.
// - set buy_sell_sli_mode to true for indicator instances with volume_type = buy/sell, for type total this is optional.
// - this basically tells the script to calculate % lengths based on total volume instead of individual buy/sell volumes and use ext offset for sell levels
// - Sell Offset is calculated relative to Buy Offset to stack/extend sell after buy. Buy Offset = Zero - Buy Length. Sell Offset = Buy Offset - Sell Length = Zero - Buy Length - Sell Length
// - there are no master/slave instances in this mode, all indicators are equal, poc/va levels are not affected and can work independently, i.e. one instance can show va levels, another - vwap.
//
// 2) Enable Vertical SLI:
// - attach the first instance and evaluate the full range to roughly determine where is the highest max_vol/poc level i.e. 0..20000, poc is in the bottom half (third, middle etc) or
// - add more instances and split the full vertical range between them, i.e. set min_level/max_level of each corresponding instance to 0..10000, 10000..20000 etc
// - make sure all instances have the same range/spacing settings
// - an instance with a subrange containing the poc level of the full range is now your master instance (bottom half). All other instances are slaves, their levels will be calculated based on the max_vol/poc of the master instance instead of local values
// - set show_max_vol_sli to true for the master instance. for slave instances this is optional and can be used to check if master/slave max_vol values match and slave can read the master's value. This simply plots the max_vol value
// - you can also attach all instances and set show_max_vol_sli to true in all of them - the instance with the largest max_vol should become the master
//
// Auto/Manual Ext Max_Vol Modes:
// - for auto vertical max_vol SLI mode set max_vol_sli_src in all slave instances to the max_vol of the master indicator: "VolumeProfileFree_MAX_RRB: Max Volume for Vertical SLI Mode". It can be tricky with 2+ instances
// - in case auto SLI mode doesn't work - assign max_vol_sli_ext in all slave instances the max_vol value of the master indicator manually and repeat on each change
// - manual override max_vol_sli_ext has higher priority than auto max_vol_sli_src when both values are assigned, when they are 0 and close respectively - SLI is disabled
// - master/slave max_vol values must match on each bar at all times to maintain proper level scale, otherwise slave's levels will look larger than they should relative to the master's levels.
// - Max_vol (red) is the last param in the long list of indicator outputs
// - the only true max_vol/poc in this SLI mode is the master's max_vol/poc. All poc/va levels in slaves will be irrelevant and are disabled automatically. Slaves can only show VWAP levels.
// - VA Levels of the master instance in this SLI mode are calculated based on the subrange, not the whole range. Cross check with the full range.
//
// WARNING!
// - auto mode max_vol_sli_src is experimental and may not work as expected
// - you can only assign auto mode max_vol_sli_src = max_vol once due to some bug with unhandled exception/buffer overflow in Tradingview. Seems that you can clear the value only by removing the indicator instance
// - sometimes you may see a "study in error state" error when attempting to set it back to close. Remove indicator/Reload chart and start from scratch
// - volume profile may not finish to redraw and freeze in an ugly shape after an UI parameter change when max_vol_sli_src is assigned a max_vol value. Assign it to close - VP should redraw properly, but it may not clear the assigned max_vol value
// - you can't seem to be able to assign a proper auto max_vol value to the 3rd slave instance
// - 2x Vertical SLI works and tested in both auto/manual, 3x SLI - only manual seems to work
//
//
// Notes:
// - This code is 20x-30x faster (main for cycle is removed) especially on lower tfs with long history - only 2-3 sec load/redraw time vs 30-60 sec of the old Pro versions
// - Instead of repeatedly calculating the total sum of volumes for the whole range on each bar, vol sums are now increased on each bar and passed to the next in the range making it a per range vs per bar calculation that reduces time dramatically
// - hist_base for levels still results is ugly redraw
// - if you don't see a volume profile check range settings: min_level/max_level and spacing, set spacing to 0 (or adjust accordingly based on the symbol's precision, i.e. 0.00001)
// - you can view either of Buy/Sell/Total volumes, but you can't display Buy/Sell levels at the same time using a single instance (this would 2x reduce the number of levels). Use 2 indicator instances in horiz buy/sell sli mode for that.
// - Volume Profile/Value Area are calculated for a given range and updated on each bar. Each level has a fixed length. Offsets control visible level parts. Side Cover hides the invisible parts.
// - Custom Color for POC/VA/VWAP levels - UI Style color/transparency can only change shape's color and doesn't affect textcolor, hence this additional option
// - Custom Width - UI Style supports only width <= 4, hence this additional option
// - POC is visible in both modes. In VWAP mode Developing POC becomes VWAP, VA High and Low => VWAP High and Low correspondingly to minimize the number of plot outputs
// - You can't change buy/sell level colors from input (only plot transparency) - this requires 2x plot outputs => 2x reduces the number of levels to fit the max 64 limit. That's why 2 additional plots are used to dim the non Value Area zones
// - All buy/sell volume lengths are calculated as % of a fixed base width = 100 bars (100%). You can't set show_last from input to change it
// - There's no such thing as buy/sell volume, there's just volume, but for the purposes of the Volume Profile method, assume: bull candle = buy volume, bear candle = sell volume
//
//
// P.S. Gravitonium Levels Are Increasing. Unobtainium is nowhere to be found!
//
// Links on Volume Profile and Value Area calculation and usage:
// https://www.tradingview.com/wiki/Volume_Profile
// https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:volume_by_price
// https://onlinelibrary.wiley.com/doi/pdf/10.1002/9781118659724.app1
//
// More Scripts:
// https://www.tradingview.com/u/RagingRocketBull/
//
// ================================================================================================================
// Inputs
// ================================================================================================================
// Show/Hide Flags
show_levels = input(true, type=bool, title="Show Levels")
show_zero = input(true, type=bool, title="Show Zero Line")
show_poc = input(true, type=bool, title="Show POC Level")
show_poc2 = input(true, type=bool, title="Show Developing POC/VWAP Level")
show_va = input(true, type=bool, title="Show Value Area/VWAP High/Low Levels")
show_cover = input(true, type=bool, title="Show Side Cover")
dim_nva_zones = input(false, type=bool, title="Dim Non Value Area Zones")
flip_levels = input(false, type=bool, title="Flip Levels Horizontally")
// highlight_bars = input(false, type=bool, title="Highlight Range Bars")
highlight_background = input(false, type=bool, title="Highlight Range Background")
// SLI
// for horiz buy/sell SLI mode: set to true for indicator instances with volume_type = buy/sell, for type total - optional
buy_sell_sli_mode = input(false, type=bool, title="Horizontal Buy/Sell SLI Mode (Master/Slave)")
// enables vertical max_vol SLI mode in the master indicator instance, for slave instances - optional (to check if master/slave max_vol values match)
show_max_vol_sli = input(false, type=bool, title="Vertical Max Volume SLI Mode (Master Only)")
// for auto vertical max_vol SLI mode set in all slave instances to the max_vol of the master indicator: "VolumeProfileFree_MAX_RRB: Max Volume for Vertical SLI Mode"
max_vol_sli_src = input(close, type=source, title="Auto Ext Max Volume Override (Vertical SLI Mode Slave Only, Close - Disabled)")
// in case auto SLI mode doesn't work - assign all slave instances the max_vol value of the master indicator manually and repeat on each change
max_vol_sli_ext = input(0, type=float, minval=0, title="Manual Ext Max Volume Override (Vertical SLI Mode Slave Only, 0 - Disabled)")
// Levels, Range
num_levels = input(50, type=integer, minval=0, maxval=50, title="Num Levels [0..50]")
max_level = input(1000, type=float, minval=0, title="Max Price Level")
min_level = input(0, type=float, minval=0, title="Min Price Level")
spacing = input(10, type=float, minval=0, title="Vertical Spacing")
range = input(1000, type=integer, minval=0, title="VP Range Length (0 - All History)")
start_bar = input(0, type=integer, minval=0, title="VP Range Start Bar (0-Based)")
// Value Area & VWAP
levels_mode = input("va", type=string, title="Value Area/VWAP Mode", options=["va", "vwap"])
volume_type = input("total", type=string, title="Volume Type Buy/Sell/Total", options=["buy", "sell", "total"])
// there can only be 1 input type=source for ext sources to show up in the source dropdown for max vol SLI mode to work (max_vol_sli_src) - using string inputs for the 2nd and all subsequent sources instead
// vp_src = input(close, type=source, title="Volume Profile Source")
// vwap_src = input(hlc3, type=source, title="VWAP Source")
vp_src_str = input("close", type=string, title="Volume Profile Source", options=["open", "high", "low", "close", "hl2", "hlc3", "ohlc4"])
vwap_src_str = input("hlc3", type=string, title="VWAP Source", options=["open", "high", "low", "close", "hl2", "hlc3", "ohlc4"])
vwap_len = input(100, type=integer, minval=1, title="VWAP Length")
stddev = input(2, type=float, minval=0.1, title="VWAP Standard Deviation")
va_percent = input(70, type=float, minval=0, maxval=100, title="Value Area % Of Total Volume")
// Offset & Width
anchor = input("cur bar", type=string, title="Zero Line Anchor Point", options=["cur bar", "range start", "range end"])
zero_offset = input(80, type=integer, title="Zero Line Offset")
adj_zero_offset = input(0, type=integer, title="Zero Line Offset Adjustment (Depending on Scale)")
cover_offset = input(0, type=integer, title="Cover Offset (Relative to Zero Line)")
poc_offset = input(-40, type=integer, title="POC Line Offset (Relative to Zero Line)")
va_offset = input(-40, type=integer, title="VA High/Low Lines Offset (Relative to Zero Line)")
// you can only set width <= 4 in UI, hence these boxes allowing for larger values
// cover appears more solid with larger values (30-50) but this results in misalignment (especially when zoomed out) due to extreme bar thickness and requires micro adjustment of zero/cover offset depending on scale
// histogram becomes so thick that left sides of both side cover and zero levels (length = 0) are pushed beyond the zero line boundary which is not desirable
// 12 is the optimal level density for a solid look on both large/small zoom scales, higher values require micro adjustment when zoomed out
zero_width = input(2, type=integer, title="Zero Line Width")
cover_width = input(12, type=integer, title="Side Cover Density")
// Colors & Transparency for all levels
level_transp = input(40, type=integer, minval=0, maxval=100, title="Level Transparency")
non_va_transp = input(70, type=integer, minval=0, maxval=100, title="Non Value Area Level Transparency")
poc_col_str = input("", type=string, title="POC Level Color", options=["", "black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia", "green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua", "orange"])
poc2_col_str = input("", type=string, title="Developing POC Color", options=["", "black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia", "green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua", "orange"])
va_high_col_str = input("", type=string, title="VA High Level Color", options=["", "black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia", "green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua", "orange"])
va_low_col_str = input("", type=string, title="VA Low Level Color", options=["", "black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia", "green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua", "orange"])
vwap_col_str = input("", type=string, title="VWAP Level Color", options=["", "black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia", "green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua", "orange"])
vwap_high_col_str = input("", type=string, title="VWAP High Level Color", options=["", "black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia", "green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua", "orange"])
vwap_low_col_str = input("", type=string, title="VWAP Low Level Color", options=["", "black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia", "green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua", "orange"])
// Const
// Colors
// #0D68AF - default VPVR blue, #C18E24 - default VPVR yellow
level_color = #0D68AF // blue // teal // color(blue,90)
buy_color = green // color(green,90)
sell_color = red // color(red,90)
range_bg_color = color(aqua,80)
range_bar_color = yellow
poc_color = black
poc2_color = silver
va_high_color = red
va_low_color = green
vwap_color = orange
vwap_high_color = fuchsia
vwap_low_color = lime
zero_color = black
// color(white,80) transparency doesn't affect textcolor, plotshape transp=20 does
nva_zone_color = white
cover_color = white
// base width for buy/sell level length calculation: 100% length = 100 bars
// you can't set plot show_last from input or dynamically from script - must be constant. Change/recompile if needed.
length = 100
// you can't set style from input
// doesn't work - you can assign style from input using cond but it will not affect output - the false part of the cond is always used
// level_style == "histogram" ? histogram : columns
level_style = columns
// POC/VWAP Level Strings
poc_text = "_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _" // monospaced font - occupies less width
text_under = "____________________________________________________________________________________________"
text_upper = "‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾" // same width as text_under
// 26 lines = num_levels - should cover all 26 levels in a given dir (depends on scale)
// characters use their own units, their height depends on scale, so it is not possible to cover non va areas completely
line_block = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
// VA mode 1 - lines
va_high1_text = text_under
va_low1_text = text_under
// VA mode 2 - zones
va_high2_text = line_block + text_under
va_low2_text = text_upper + line_block
// level_text1 = "____________________________________________________________________________________________"
// level_text2 = "___ _ ___ _ ___ _ ___ _ ___ _ ___ _ ___ _ ___ _ ___ _ ___ _ ___ _ ___ _ ___ _ ___ _ ___ _ ___ "
// level_text3 = "__ ι ___ ι ___ ι ___ ι ___ ι ___ ι ___ ι ___ ι ___ ι ___ ι ___ ι ___ ι ___ ι ___ ι ___ ι ___ " // uses unicode char
// ================================================================================================================
// Functions
// ================================================================================================================
// convert string to color
// - you can set color from input if you cast str to color first
// - str can't be a color literal (i.e. #CC0000) - can't cast string to a # color literal
// - you can't set color_transp color(red, color_transp) from input (must be const), but you can set plot(... transp=plot_transp ...) (can be var)
// - this increases plot outputs 1x color => 2x color because color is the result of a cond
get_color(str, def) =>
// "", "black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia", "green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua", "orange"
get_color = str == "black" ? black : str == "silver" ? silver : str == "gray" ? gray : str == "white" ? white : str == "maroon" ? maroon : str == "red" ? red :
str == "purple" ? purple : str == "fuchsia" ? fuchsia : str == "green" ? green : str == "lime" ? lime : str == "olive" ? olive : str == "yellow" ? yellow :
str == "navy" ? navy : str == "blue" ? blue : str == "teal" ? teal : str == "aqua" ? aqua : str == "orange" ? orange : def
// extracts source from source str
get_src(src_str) =>
res = src_str == "open" ? open : src_str == "high" ? high : src_str == "low" ? low : src_str == "close" ? close : src_str == "hl2" ? hl2 : src_str == "hlc3" ? hlc3 : src_str == "ohlc4" ? ohlc4 : na
// Converts TF to mins - Respect the 40 Security Calls Limit
// 1. you can't convert timeframe to minutes directly! period returns string, interval - int TF multiplier. You don't have any string processing.
// - you can't use change(time(tf)) because it fails on gaps
// - you must use isdaily, isweekly... etc functions, but they don't have tf arg and only work for current TF, so you must use security on them
// 2. you can only have 40 security calls per script/computation cycle - does not compile, weird errors if exceeded: node from line undefined UP -1
// - you can't have a set of separate is_daily(tf) => security(tickerid, tf, isdaily) ... functions to call from tf_to_mins - does not compile, function has too many arguments 158 (max limit 100)
// - you can't have a set of direct security calls from from tf_to_mins: is_daily = security(tickerid, tf, isdaily) - does not compile
// - in general, you can't have 2-3 levels deep nested function calls with security. Instead, call security from the global scope cycle or from 1-2 level functions, keep track of all those calls <= 40
// - you must wrap all isdaily functions for current TF in tf_to_mins and then call one function using a single security call from global scope
tf_to_mins() =>
// time_range = 60 * 24 * 30 * 12 // min * hours * days * months
// isintraday, isdaily, isweekly, ismonthly are mutually exclusive. Only one returns true. isdaily, isweekly, ismonthly return:
// - true for "D", "2D", "4D" etc - their respective TFs with/without multipliers and
// - false for 1440 (D), 7D (W), 4W (M) (don't see 1440 as daily, 7D as weekly)
mins = isintraday ? interval * 1 : 1
days = isdaily ? interval * 1 * 24 * 60: 1
weeks = isweekly ? interval * 7 * 24 * 60: 1
months = ismonthly ? interval * 30 * 24 * 60: 1
result = mins * days * weeks * months
// check if price is within bounds
is_valid(price) =>
min_cond = (min_level == 0) or ((min_level > 0) and (min_level <= price))
max_cond = (max_level == 0) or ((max_level > 0) and (price <= max_level))
res = min_cond and max_cond
// ================================================================================================================
// Processing
// ================================================================================================================
// Sources
// convert src str inputs to sources
vp_src = get_src(vp_src_str)
vwap_src = get_src(vwap_src_str)
// Max Vol SLI Mode check
max_vol_sli_mode = (max_vol_sli_ext > 0) or (max_vol_sli_src != close)
// get ext max vol value
// manual override has higher priority than auto, 0 and close - disabled
max_vol_sli = max_vol_sli_ext > 0 ? max_vol_sli_ext : max_vol_sli_src != close ? max_vol_sli_src : 0
// Range
bar_range = 1000 * 60 * tf_to_mins() // cur period bar time in millisecs
first_bar = start_bar + range // must not use -1 to include the first bar (start_bar is 0-based)!
first_time = first_bar * bar_range
last_time = start_bar * bar_range
time_range = timenow - time
// time is in range check, starting from left to right
// range = 0 - process all history, starting from the first bar on a chart n = 0
is_after_start = ((time_range <= first_time) or (range == 0))
is_before_end = (time_range > last_time)
is_in_range = is_after_start and is_before_end
// first bar of the visible time based range - num_bars back
// range_start = is_in_range and not is_in_range[1]
// Range
// auto range
// ph = highest(range)
// pl = lowest(range)
// doesn't work - plot histbase must be a const expression, can be set from input, can't be var, mutable or function
// ph := max_level > 0 ? min(max_level, ph) : ph
// pl := min_level > 0 ? max(min_level, pl) : pl
// user defined price range
ph = max_level
pl = min_level
// level height/step
p_range = ph - pl
h = num_levels > 0 ? p_range/num_levels : 0
is_valid_range = is_in_range and (num_levels > 0) and (min_level <= max_level)
// Volume Totals
buy_vol1 = 0.0
buy_vol2 = 0.0
buy_vol3 = 0.0
buy_vol4 = 0.0
buy_vol5 = 0.0
buy_vol6 = 0.0
buy_vol7 = 0.0
buy_vol8 = 0.0
buy_vol9 = 0.0
buy_vol10 = 0.0
buy_vol11 = 0.0
buy_vol12 = 0.0
buy_vol13 = 0.0
buy_vol14 = 0.0
buy_vol15 = 0.0
buy_vol16 = 0.0
buy_vol17 = 0.0
buy_vol18 = 0.0
buy_vol19 = 0.0
buy_vol20 = 0.0
buy_vol21 = 0.0
buy_vol22 = 0.0
buy_vol23 = 0.0
buy_vol24 = 0.0
buy_vol25 = 0.0
buy_vol26 = 0.0
buy_vol27 = 0.0
buy_vol28 = 0.0
buy_vol29 = 0.0
buy_vol30 = 0.0
buy_vol31 = 0.0
buy_vol32 = 0.0
buy_vol33 = 0.0
buy_vol34 = 0.0
buy_vol35 = 0.0
buy_vol36 = 0.0
buy_vol37 = 0.0
buy_vol38 = 0.0
buy_vol39 = 0.0
buy_vol40 = 0.0
buy_vol41 = 0.0
buy_vol42 = 0.0
buy_vol43 = 0.0
buy_vol44 = 0.0
buy_vol45 = 0.0
buy_vol46 = 0.0
buy_vol47 = 0.0
buy_vol48 = 0.0
buy_vol49 = 0.0
buy_vol50 = 0.0
sell_vol1 = 0.0
sell_vol2 = 0.0
sell_vol3 = 0.0
sell_vol4 = 0.0
sell_vol5 = 0.0
sell_vol6 = 0.0
sell_vol7 = 0.0
sell_vol8 = 0.0
sell_vol9 = 0.0
sell_vol10 = 0.0
sell_vol11 = 0.0
sell_vol12 = 0.0
sell_vol13 = 0.0
sell_vol14 = 0.0
sell_vol15 = 0.0
sell_vol16 = 0.0
sell_vol17 = 0.0
sell_vol18 = 0.0
sell_vol19 = 0.0
sell_vol20 = 0.0
sell_vol21 = 0.0
sell_vol22 = 0.0
sell_vol23 = 0.0
sell_vol24 = 0.0
sell_vol25 = 0.0
sell_vol26 = 0.0
sell_vol27 = 0.0
sell_vol28 = 0.0
sell_vol29 = 0.0
sell_vol30 = 0.0
sell_vol31 = 0.0
sell_vol32 = 0.0
sell_vol33 = 0.0
sell_vol34 = 0.0
sell_vol35 = 0.0
sell_vol36 = 0.0
sell_vol37 = 0.0
sell_vol38 = 0.0
sell_vol39 = 0.0
sell_vol40 = 0.0
sell_vol41 = 0.0
sell_vol42 = 0.0
sell_vol43 = 0.0
sell_vol44 = 0.0
sell_vol45 = 0.0
sell_vol46 = 0.0
sell_vol47 = 0.0
sell_vol48 = 0.0
sell_vol49 = 0.0
sell_vol50 = 0.0
// you can only have 50 levels in this version
// save sums of buy/sell volumes updated on each bar
buy_vol1 := na(buy_vol1[1]) ? 0 : buy_vol1[1]
buy_vol2 := na(buy_vol2[1]) ? 0 : buy_vol2[1]
buy_vol3 := na(buy_vol3[1]) ? 0 : buy_vol3[1]
buy_vol4 := na(buy_vol4[1]) ? 0 : buy_vol4[1]
buy_vol5 := na(buy_vol5[1]) ? 0 : buy_vol5[1]
buy_vol6 := na(buy_vol6[1]) ? 0 : buy_vol6[1]
buy_vol7 := na(buy_vol7[1]) ? 0 : buy_vol7[1]
buy_vol8 := na(buy_vol8[1]) ? 0 : buy_vol8[1]
buy_vol9 := na(buy_vol9[1]) ? 0 : buy_vol9[1]
buy_vol10 := na(buy_vol10[1]) ? 0 : buy_vol10[1]
buy_vol11 := na(buy_vol11[1]) ? 0 : buy_vol11[1]
buy_vol12 := na(buy_vol12[1]) ? 0 : buy_vol12[1]
buy_vol13 := na(buy_vol13[1]) ? 0 : buy_vol13[1]
buy_vol14 := na(buy_vol14[1]) ? 0 : buy_vol14[1]
buy_vol15 := na(buy_vol15[1]) ? 0 : buy_vol15[1]
buy_vol16 := na(buy_vol16[1]) ? 0 : buy_vol16[1]
buy_vol17 := na(buy_vol17[1]) ? 0 : buy_vol17[1]
buy_vol18 := na(buy_vol18[1]) ? 0 : buy_vol18[1]
buy_vol19 := na(buy_vol19[1]) ? 0 : buy_vol19[1]
buy_vol20 := na(buy_vol20[1]) ? 0 : buy_vol20[1]
buy_vol21 := na(buy_vol21[1]) ? 0 : buy_vol21[1]
buy_vol22 := na(buy_vol22[1]) ? 0 : buy_vol22[1]
buy_vol23 := na(buy_vol23[1]) ? 0 : buy_vol23[1]
buy_vol24 := na(buy_vol24[1]) ? 0 : buy_vol24[1]
buy_vol25 := na(buy_vol25[1]) ? 0 : buy_vol25[1]
buy_vol26 := na(buy_vol26[1]) ? 0 : buy_vol26[1]
buy_vol27 := na(buy_vol27[1]) ? 0 : buy_vol27[1]
buy_vol28 := na(buy_vol28[1]) ? 0 : buy_vol28[1]
buy_vol29 := na(buy_vol29[1]) ? 0 : buy_vol29[1]
buy_vol30 := na(buy_vol30[1]) ? 0 : buy_vol30[1]
buy_vol31 := na(buy_vol31[1]) ? 0 : buy_vol31[1]
buy_vol32 := na(buy_vol32[1]) ? 0 : buy_vol32[1]
buy_vol33 := na(buy_vol33[1]) ? 0 : buy_vol33[1]
buy_vol34 := na(buy_vol34[1]) ? 0 : buy_vol34[1]
buy_vol35 := na(buy_vol35[1]) ? 0 : buy_vol35[1]
buy_vol36 := na(buy_vol36[1]) ? 0 : buy_vol36[1]
buy_vol37 := na(buy_vol37[1]) ? 0 : buy_vol37[1]
buy_vol38 := na(buy_vol38[1]) ? 0 : buy_vol38[1]
buy_vol39 := na(buy_vol39[1]) ? 0 : buy_vol39[1]
buy_vol40 := na(buy_vol40[1]) ? 0 : buy_vol40[1]
buy_vol41 := na(buy_vol41[1]) ? 0 : buy_vol41[1]
buy_vol42 := na(buy_vol42[1]) ? 0 : buy_vol42[1]
buy_vol43 := na(buy_vol43[1]) ? 0 : buy_vol43[1]
buy_vol44 := na(buy_vol44[1]) ? 0 : buy_vol44[1]
buy_vol45 := na(buy_vol45[1]) ? 0 : buy_vol45[1]
buy_vol46 := na(buy_vol46[1]) ? 0 : buy_vol46[1]
buy_vol47 := na(buy_vol47[1]) ? 0 : buy_vol47[1]
buy_vol48 := na(buy_vol48[1]) ? 0 : buy_vol48[1]
buy_vol49 := na(buy_vol49[1]) ? 0 : buy_vol49[1]
buy_vol50 := na(buy_vol50[1]) ? 0 : buy_vol50[1]
sell_vol1 := na(sell_vol1[1]) ? 0 : sell_vol1[1]
sell_vol2 := na(sell_vol2[1]) ? 0 : sell_vol2[1]
sell_vol3 := na(sell_vol3[1]) ? 0 : sell_vol3[1]
sell_vol4 := na(sell_vol4[1]) ? 0 : sell_vol4[1]
sell_vol5 := na(sell_vol5[1]) ? 0 : sell_vol5[1]
sell_vol6 := na(sell_vol6[1]) ? 0 : sell_vol6[1]
sell_vol7 := na(sell_vol7[1]) ? 0 : sell_vol7[1]
sell_vol8 := na(sell_vol8[1]) ? 0 : sell_vol8[1]
sell_vol9 := na(sell_vol9[1]) ? 0 : sell_vol9[1]
sell_vol10 := na(sell_vol10[1]) ? 0 : sell_vol10[1]
sell_vol11 := na(sell_vol11[1]) ? 0 : sell_vol11[1]
sell_vol12 := na(sell_vol12[1]) ? 0 : sell_vol12[1]
sell_vol13 := na(sell_vol13[1]) ? 0 : sell_vol13[1]
sell_vol14 := na(sell_vol14[1]) ? 0 : sell_vol14[1]
sell_vol15 := na(sell_vol15[1]) ? 0 : sell_vol15[1]
sell_vol16 := na(sell_vol16[1]) ? 0 : sell_vol16[1]
sell_vol17 := na(sell_vol17[1]) ? 0 : sell_vol17[1]
sell_vol18 := na(sell_vol18[1]) ? 0 : sell_vol18[1]
sell_vol19 := na(sell_vol19[1]) ? 0 : sell_vol19[1]
sell_vol20 := na(sell_vol20[1]) ? 0 : sell_vol20[1]
sell_vol21 := na(sell_vol21[1]) ? 0 : sell_vol21[1]
sell_vol22 := na(sell_vol22[1]) ? 0 : sell_vol22[1]
sell_vol23 := na(sell_vol23[1]) ? 0 : sell_vol23[1]
sell_vol24 := na(sell_vol24[1]) ? 0 : sell_vol24[1]
sell_vol25 := na(sell_vol25[1]) ? 0 : sell_vol25[1]
sell_vol26 := na(sell_vol26[1]) ? 0 : sell_vol26[1]
sell_vol27 := na(sell_vol27[1]) ? 0 : sell_vol27[1]
sell_vol28 := na(sell_vol28[1]) ? 0 : sell_vol28[1]
sell_vol29 := na(sell_vol29[1]) ? 0 : sell_vol29[1]
sell_vol30 := na(sell_vol30[1]) ? 0 : sell_vol30[1]
sell_vol31 := na(sell_vol31[1]) ? 0 : sell_vol31[1]
sell_vol32 := na(sell_vol32[1]) ? 0 : sell_vol32[1]
sell_vol33 := na(sell_vol33[1]) ? 0 : sell_vol33[1]
sell_vol34 := na(sell_vol34[1]) ? 0 : sell_vol34[1]
sell_vol35 := na(sell_vol35[1]) ? 0 : sell_vol35[1]
sell_vol36 := na(sell_vol36[1]) ? 0 : sell_vol36[1]
sell_vol37 := na(sell_vol37[1]) ? 0 : sell_vol37[1]
sell_vol38 := na(sell_vol38[1]) ? 0 : sell_vol38[1]
sell_vol39 := na(sell_vol39[1]) ? 0 : sell_vol39[1]
sell_vol40 := na(sell_vol40[1]) ? 0 : sell_vol40[1]
sell_vol41 := na(sell_vol41[1]) ? 0 : sell_vol41[1]
sell_vol42 := na(sell_vol42[1]) ? 0 : sell_vol42[1]
sell_vol43 := na(sell_vol43[1]) ? 0 : sell_vol43[1]
sell_vol44 := na(sell_vol44[1]) ? 0 : sell_vol44[1]
sell_vol45 := na(sell_vol45[1]) ? 0 : sell_vol45[1]
sell_vol46 := na(sell_vol46[1]) ? 0 : sell_vol46[1]
sell_vol47 := na(sell_vol47[1]) ? 0 : sell_vol47[1]
sell_vol48 := na(sell_vol48[1]) ? 0 : sell_vol48[1]
sell_vol49 := na(sell_vol49[1]) ? 0 : sell_vol49[1]
sell_vol50 := na(sell_vol50[1]) ? 0 : sell_vol50[1]
// Price Volume Profile
//
// 1. Determine the highest/lowest range for the entire period.
// 2. Divide this range by the number of levels (profile resolution) to create a set of vertically distributed price zones.
// 3. Total the buy/sell volume traded within each price zone (based on price close and candle dir)
// process range
k = na
// sum of volumes is calculated only within the range till the end of range
// - if start_bar = 0 - the range "never ends" and sum of volumes continues to be updated on each new bar
// - if start_bar > 0 - the range ends at a fixed point in time (start_bar bars back), sum of volumes remains const after the end of range
if is_valid_range
// both range and start_bar can be > n producing negative index values
// range_bars = range == 0 ? n - start_bar : start_bar + range - 1
// for i = start_bar to range_bars
// Pro Tip:
// this code is 20x-30x faster than for i above especially on lower tfs with long history - only 2 sec load/redraw time vs 30-60 sec
// instead of repeatedly calculating the total sum of volumes for the whole range on each bar, vol sums are increased on each bar and passed to the next in the range making it a per range vs per bar calculation that reduces time dramatically
price = vp_src // vp_src[i] // close[i]
// check if price is within bounds
if is_valid(price)
// find volume profile level matching cur bar's price
k := floor((price - pl) / h) + 1
if not na(k)
// for volume_type=total total_vol = buy vol + sell vol - regardless of the dir sign
dir = sign(close - open)
// we could calculate any one of the buy/sell/total volumes instead of all of them if it weren't for the buy/sell sli mode
// vol_cond = volume_type == "buy" ? dir >= 0 : volume_type == "sell" ? dir < 0 : true
// if vol_cond
// if k == 1
// vol1 := vol1 + volume
// ...
// increase sums of buy/sell volumes for matching price level when inside the range
// for buy_sell_sli_mode we need to calculate both buy and sell volumes at all times
// redundant code below is required - you don't have arrays
if k == 1
buy_vol1 := dir >= 0 ? buy_vol1 + volume : buy_vol1
sell_vol1 := dir < 0 ? sell_vol1 + volume : sell_vol1
if k == 2
buy_vol2 := dir >= 0 ? buy_vol2 + volume : buy_vol2
sell_vol2 := dir < 0 ? sell_vol2 + volume : sell_vol2
if k == 3
buy_vol3 := dir >= 0 ? buy_vol3 + volume : buy_vol3
sell_vol3 := dir < 0 ? sell_vol3 + volume : sell_vol3
if k == 4
buy_vol4 := dir >= 0 ? buy_vol4 + volume : buy_vol4
sell_vol4 := dir < 0 ? sell_vol4 + volume : sell_vol4
if k == 5
buy_vol5 := dir >= 0 ? buy_vol5 + volume : buy_vol5
sell_vol5 := dir < 0 ? sell_vol5 + volume : sell_vol5
if k == 6
buy_vol6 := dir >= 0 ? buy_vol6 + volume : buy_vol6
sell_vol6 := dir < 0 ? sell_vol6 + volume : sell_vol6
if k == 7
buy_vol7 := dir >= 0 ? buy_vol7 + volume : buy_vol7
sell_vol7 := dir < 0 ? sell_vol7 + volume : sell_vol7
if k == 8
buy_vol8 := dir >= 0 ? buy_vol8 + volume : buy_vol8
sell_vol8 := dir < 0 ? sell_vol8 + volume : sell_vol8
if k == 9
buy_vol9 := dir >= 0 ? buy_vol9 + volume : buy_vol9
sell_vol9 := dir < 0 ? sell_vol9 + volume : sell_vol9
if k == 10
buy_vol10 := dir >= 0 ? buy_vol10 + volume : buy_vol10
sell_vol10 := dir < 0 ? sell_vol10 + volume : sell_vol10
if k == 11
buy_vol11 := dir >= 0 ? buy_vol11 + volume : buy_vol11
sell_vol11 := dir < 0 ? sell_vol11 + volume : sell_vol11
if k == 12
buy_vol12 := dir >= 0 ? buy_vol12 + volume : buy_vol12
sell_vol12 := dir < 0 ? sell_vol12 + volume : sell_vol12
if k == 13
buy_vol13 := dir >= 0 ? buy_vol13 + volume : buy_vol13
sell_vol13 := dir < 0 ? sell_vol13 + volume : sell_vol13
if k == 14
buy_vol14 := dir >= 0 ? buy_vol14 + volume : buy_vol14
sell_vol14 := dir < 0 ? sell_vol14 + volume : sell_vol14
if k == 15
buy_vol15 := dir >= 0 ? buy_vol15 + volume : buy_vol15
sell_vol15 := dir < 0 ? sell_vol15 + volume : sell_vol15
if k == 16
buy_vol16 := dir >= 0 ? buy_vol16 + volume : buy_vol16
sell_vol16 := dir < 0 ? sell_vol16 + volume : sell_vol16
if k == 17
buy_vol17 := dir >= 0 ? buy_vol17 + volume : buy_vol17
sell_vol17 := dir < 0 ? sell_vol17 + volume : sell_vol17
if k == 18
buy_vol18 := dir >= 0 ? buy_vol18 + volume : buy_vol18
sell_vol18 := dir < 0 ? sell_vol18 + volume : sell_vol18
if k == 19
buy_vol19 := dir >= 0 ? buy_vol19 + volume : buy_vol19
sell_vol19 := dir < 0 ? sell_vol19 + volume : sell_vol19
if k == 20
buy_vol20 := dir >= 0 ? buy_vol20 + volume : buy_vol20
sell_vol20 := dir < 0 ? sell_vol20 + volume : sell_vol20
if k == 21
buy_vol21 := dir >= 0 ? buy_vol21 + volume : buy_vol21
sell_vol21 := dir < 0 ? sell_vol21 + volume : sell_vol21
if k == 22
buy_vol22 := dir >= 0 ? buy_vol22 + volume : buy_vol22
sell_vol22 := dir < 0 ? sell_vol22 + volume : sell_vol22
if k == 23
buy_vol23 := dir >= 0 ? buy_vol23 + volume : buy_vol23
sell_vol23 := dir < 0 ? sell_vol23 + volume : sell_vol23
if k == 24
buy_vol24 := dir >= 0 ? buy_vol24 + volume : buy_vol24
sell_vol24 := dir < 0 ? sell_vol24 + volume : sell_vol24
if k == 25
buy_vol25 := dir >= 0 ? buy_vol25 + volume : buy_vol25
sell_vol25 := dir < 0 ? sell_vol25 + volume : sell_vol25
if k == 26
buy_vol26 := dir >= 0 ? buy_vol26 + volume : buy_vol26
sell_vol26 := dir < 0 ? sell_vol26 + volume : sell_vol26
if k == 27
buy_vol27 := dir >= 0 ? buy_vol27 + volume : buy_vol27
sell_vol27 := dir < 0 ? sell_vol27 + volume : sell_vol27
if k == 28
buy_vol28 := dir >= 0 ? buy_vol28 + volume : buy_vol28
sell_vol28 := dir < 0 ? sell_vol28 + volume : sell_vol28
if k == 29
buy_vol29 := dir >= 0 ? buy_vol29 + volume : buy_vol29
sell_vol29 := dir < 0 ? sell_vol29 + volume : sell_vol29
if k == 30
buy_vol30 := dir >= 0 ? buy_vol30 + volume : buy_vol30
sell_vol30 := dir < 0 ? sell_vol30 + volume : sell_vol30
if k == 31
buy_vol31 := dir >= 0 ? buy_vol31 + volume : buy_vol31
sell_vol31 := dir < 0 ? sell_vol31 + volume : sell_vol31
if k == 32
buy_vol32 := dir >= 0 ? buy_vol32 + volume : buy_vol32
sell_vol32 := dir < 0 ? sell_vol32 + volume : sell_vol32
if k == 33
buy_vol33 := dir >= 0 ? buy_vol33 + volume : buy_vol33
sell_vol33 := dir < 0 ? sell_vol33 + volume : sell_vol33
if k == 34
buy_vol34 := dir >= 0 ? buy_vol34 + volume : buy_vol34
sell_vol34 := dir < 0 ? sell_vol34 + volume : sell_vol34
if k == 35
buy_vol35 := dir >= 0 ? buy_vol35 + volume : buy_vol35
sell_vol35 := dir < 0 ? sell_vol35 + volume : sell_vol35
if k == 36
buy_vol36 := dir >= 0 ? buy_vol36 + volume : buy_vol36
sell_vol36 := dir < 0 ? sell_vol36 + volume : sell_vol36
if k == 37
buy_vol37 := dir >= 0 ? buy_vol37 + volume : buy_vol37
sell_vol37 := dir < 0 ? sell_vol37 + volume : sell_vol37
if k == 38
buy_vol38 := dir >= 0 ? buy_vol38 + volume : buy_vol38
sell_vol38 := dir < 0 ? sell_vol38 + volume : sell_vol38
if k == 39
buy_vol39 := dir >= 0 ? buy_vol39 + volume : buy_vol39
sell_vol39 := dir < 0 ? sell_vol39 + volume : sell_vol39
if k == 40
buy_vol40 := dir >= 0 ? buy_vol40 + volume : buy_vol40
sell_vol40 := dir < 0 ? sell_vol40 + volume : sell_vol40
if k == 41
buy_vol41 := dir >= 0 ? buy_vol41 + volume : buy_vol41
sell_vol41 := dir < 0 ? sell_vol41 + volume : sell_vol41
if k == 42
buy_vol42 := dir >= 0 ? buy_vol42 + volume : buy_vol42
sell_vol42 := dir < 0 ? sell_vol42 + volume : sell_vol42
if k == 43
buy_vol43 := dir >= 0 ? buy_vol43 + volume : buy_vol43
sell_vol43 := dir < 0 ? sell_vol43 + volume : sell_vol43
if k == 44
buy_vol44 := dir >= 0 ? buy_vol44 + volume : buy_vol44
sell_vol44 := dir < 0 ? sell_vol44 + volume : sell_vol44
if k == 45
buy_vol45 := dir >= 0 ? buy_vol45 + volume : buy_vol45
sell_vol45 := dir < 0 ? sell_vol45 + volume : sell_vol45
if k == 46
buy_vol46 := dir >= 0 ? buy_vol46 + volume : buy_vol46
sell_vol46 := dir < 0 ? sell_vol46 + volume : sell_vol46
if k == 47
buy_vol47 := dir >= 0 ? buy_vol47 + volume : buy_vol47
sell_vol47 := dir < 0 ? sell_vol47 + volume : sell_vol47
if k == 48
buy_vol48 := dir >= 0 ? buy_vol48 + volume : buy_vol48
sell_vol48 := dir < 0 ? sell_vol48 + volume : sell_vol48
if k == 49
buy_vol49 := dir >= 0 ? buy_vol49 + volume : buy_vol49
sell_vol49 := dir < 0 ? sell_vol49 + volume : sell_vol49
if k == 50
buy_vol50 := dir >= 0 ? buy_vol50 + volume : buy_vol50
sell_vol50 := dir < 0 ? sell_vol50 + volume : sell_vol50
// use calculated buy/sell volumes - must remain after
// buy volumes array (read only)
buy_volumes(group) =>
// res = 0.0
// if (group >= 1) and (group <= num_levels)
res = group == 1 ? buy_vol1 : group == 2 ? buy_vol2 : group == 3 ? buy_vol3 : group == 4 ? buy_vol4 : group == 5 ? buy_vol5 : group == 6 ? buy_vol6 : group == 7 ? buy_vol7 : group == 8 ? buy_vol8 : group == 9 ? buy_vol9 : group == 10 ? buy_vol10 :
group == 11 ? buy_vol11 : group == 12 ? buy_vol12 : group == 13 ? buy_vol13 : group == 14 ? buy_vol14 : group == 15 ? buy_vol15 : group == 16 ? buy_vol16 : group == 17 ? buy_vol17 : group == 18 ? buy_vol18 : group == 19 ? buy_vol19 : group == 20 ? buy_vol20 :
group == 21 ? buy_vol21 : group == 22 ? buy_vol22 : group == 23 ? buy_vol23 : group == 24 ? buy_vol24 : group == 25 ? buy_vol25 : group == 26 ? buy_vol26 : group == 27 ? buy_vol27 : group == 28 ? buy_vol28 : group == 29 ? buy_vol29 : group == 30 ? buy_vol30 :
group == 31 ? buy_vol31 : group == 32 ? buy_vol32 : group == 33 ? buy_vol33 : group == 34 ? buy_vol34 : group == 35 ? buy_vol35 : group == 36 ? buy_vol36 : group == 37 ? buy_vol37 : group == 38 ? buy_vol38 : group == 39 ? buy_vol39 : group == 40 ? buy_vol40 :
group == 41 ? buy_vol41 : group == 42 ? buy_vol42 : group == 43 ? buy_vol43 : group == 44 ? buy_vol44 : group == 45 ? buy_vol45 : group == 46 ? buy_vol46 : group == 47 ? buy_vol47 : group == 48 ? buy_vol48 : group == 49 ? buy_vol49 : group == 50 ? buy_vol50 : 0.0 // na
// returns 0 instead of na - important!
// res
// sell volumes array (read only)
sell_volumes(group) =>
// res = 0.0
// if (group >= 1) and (group <= num_levels)
res = group == 1 ? sell_vol1 : group == 2 ? sell_vol2 : group == 3 ? sell_vol3 : group == 4 ? sell_vol4 : group == 5 ? sell_vol5 : group == 6 ? sell_vol6 : group == 7 ? sell_vol7 : group == 8 ? sell_vol8 : group == 9 ? sell_vol9 : group == 10 ? sell_vol10 :
group == 11 ? sell_vol11 : group == 12 ? sell_vol12 : group == 13 ? sell_vol13 : group == 14 ? sell_vol14 : group == 15 ? sell_vol15 : group == 16 ? sell_vol16 : group == 17 ? sell_vol17 : group == 18 ? sell_vol18 : group == 19 ? sell_vol19 : group == 20 ? sell_vol20 :
group == 21 ? sell_vol21 : group == 22 ? sell_vol22 : group == 23 ? sell_vol23 : group == 24 ? sell_vol24 : group == 25 ? sell_vol25 : group == 26 ? sell_vol26 : group == 27 ? sell_vol27 : group == 28 ? sell_vol28 : group == 29 ? sell_vol29 : group == 30 ? sell_vol30 :
group == 31 ? sell_vol31 : group == 32 ? sell_vol32 : group == 33 ? sell_vol33 : group == 34 ? sell_vol34 : group == 35 ? sell_vol35 : group == 36 ? sell_vol36 : group == 37 ? sell_vol37 : group == 38 ? sell_vol38 : group == 39 ? sell_vol39 : group == 40 ? sell_vol40 :
group == 41 ? sell_vol41 : group == 42 ? sell_vol42 : group == 43 ? sell_vol43 : group == 44 ? sell_vol44 : group == 45 ? sell_vol45 : group == 46 ? sell_vol46 : group == 47 ? sell_vol47 : group == 48 ? sell_vol48 : group == 49 ? sell_vol49 : group == 50 ? sell_vol50 : 0.0 // na
// returns 0 instead of na - important!
// res
// Pro Tip:
// apparently you can't have a function/call a function with the total number of vars inside all function bodies in a call stack > 100
// doesn't work: script has a function with too many arguments: 103. The limit is 100 error => 2 function calls with 50 vars each: 50 + 50 + 3
// total_volumes(group) =>
// res = 0.0
// if (group >= 1) and (group <= num_levels)
// bv = buy_volumes(group)
// sv = sell_volumes(group)
// res := bv + sv
// res
// res = buy_volumes(group) + sell_volumes(group)
// buy_volumes(group) + sell_volumes(group)
// Max/Total Volumes
// max_vol sli override
// in vertical sli mode max_vol from the master indicator instance is used as base length for all slave's levels
// in all slave instances poc/poc2/va levels are auto hidden, but vwap levels will work, since they don't depend on the range
max_vol = max_vol_sli
max_buy_vol = 0.0
max_sell_vol = 0.0
max_vol2 = 0.0
total_vol = 0.0
poc_index = 0
poc2_index = 0
poc_level = 0.0
poc2_level = 0.0
// no max_vol processing in max vol sli mode - using external max_vol value instead
// is_valid_range := is_valid_range and (max_vol_sli == 0)
// if is_valid_range
// calculate max_vol and show levels even after the end of range
if is_after_start and not max_vol_sli_mode
// - for total - we always calculate max_total volume/poc
// - for buy/sell in normal mode => max_buy/max_sell volumes/poc. individual max_buy/max_sell levels may differ from max_total
// - for buy/sell in buy_sell_sli_mode with extended buy + sell offset for sell => max_total volume/poc in both master/slave indicators
a = (volume_type == "total") or buy_sell_sli_mode ? 1 : volume_type == "buy" ? 1 : volume_type == "sell" ? 0 : 0
b = (volume_type == "total") or buy_sell_sli_mode ? 1 : volume_type == "buy" ? 0 : volume_type == "sell" ? 1 : 0
for i = 1 to num_levels
// max buy/sell volumes for buy_sell_sli_mode
bv = buy_volumes(i)
if max_buy_vol < bv
max_buy_vol := bv
sv = sell_volumes(i)
if max_sell_vol < sv
max_sell_vol := sv
// calculate max_vol and poc with respect to volume_type
vol = a * bv + b * sv
total_vol := total_vol + vol
// max total volume for a given price level in a range - POC level
// nested structure enables further search for the 2nd largest Developing POC till the end of range even after the main POC is found
// check for Developing POC
if max_vol2 < vol
// check for POC
// in 1,2,3 sequence will assign POC=3, POC2=2
if max_vol < vol
// save cur max_vol and poc_index as Developing POC
max_vol2 := max_vol
poc2_index := poc_index
// save new max_vol and poc_index as POC
max_vol := vol
poc_index := i
else
// in 1,3,2 sequence will still assign POC=3, POC2=2 properly instead of POC=3, POC2=1 which is incorrect
// in 1,4,2,3,5 sequence will correctly assign POC=5, POC2=4
// save new max_vol and poc_index as Developing POC only if further POC check failed
max_vol2 := vol
poc2_index := i
// POC, Developing POC Levels
poc_level := pl + (poc_index - 1) * h + h/2
poc2_level := poc2_index > 0 ? pl + (poc2_index - 1) * h + h/2 : 0.0
// Value Area VAH/VAL
// Point of Control (POC) – price level with the highest traded volume for the time period
// Value Area (VA) – range of price levels with the sum of traded volumes = 70% of the total traded volume during the time period
// Value Area High (VAH) – highest price level within the value area
// Value Area Low (VAL) – lowest price level within the value area
//
// 1. Calculate the total volume (buy and sell) traded in the profile.
// 2. VA % target = 70% of total volume
// 3. Start with POC
// - VA Volume0 = POC Total Volume
// - VA Area0/VAH0/VAL0 = POC
// 4. Get the sums of total volumes:
// - of the 2 rows above the current VAH (VAH0 = POC) => sum above
// - of the 2 rows below the current VAL (VAL0 = POC) => sum below
// 5. Increase VA Volume with the largest of the 2 sums: VA Volume1 = VA Volume0 + max(sum above, sum below)
// 6. Increase VA Area above or below with 2 rows (+2 rows in the dir of the largest of the 2 sums):
// - if sum above > sum below VAH1 = VAH0 + 2 else VAL1 = VAL0 - 2
// - if sum above = sum below choose the level closest to the middle of the range
// - VA Area1 = [VAL1..VAH1] range of rows
// 7. Repeat steps 4-6 until VA Volume matches or exceeds the 70% target: VA Volume_i >= VA % Target
// 8. final VAH = VAH i - highest row of VA Area i, final VAL = VAL i - lowest row of VA Area i
va_limit = total_vol * va_percent / 100
mid_index = num_levels/2
// POC - starting point for Value Area Calculation
va_vol = max_vol // buy_volumes(poc_index) + sell_volumes(poc_index)
va_high = poc_index
va_low = poc_index
va_high_level = 0.0
va_low_level = 0.0
// POC = num_levels => show only VAL, don't show VAH above num_levels
// POC = 1 => show only VAH, don't show VAL below 1
// empty volume range - don't show anything
// is_valid_range := is_valid_range and (va_vol > 0)
// no va levels processing in max vol sli mode max_vol_sli > 0 - va levels in a slave indicator instance are always hidden
// using num_levels but there are max num_levels/2 estimated total iterations where 2 is the number of adj levels in each dir
// if is_valid_range
// calculate and show va_levels even after the end of range
if is_after_start and not max_vol_sli_mode and (va_vol > 0)
for i = 1 to num_levels
// calculate and compare the sum of volumes for 2 rows above and below to expand Value Area in either dir
// va_low/va_high are adjusted independently and can fall outside of range [1..num_levels] => buy/sell_volumes must return 0 instead of na for va levels to be calculated properly - important!
// above_vol = total_volumes(va_high + 1) + total_volumes(va_high + 2)
// below_vol = total_volumes(va_low - 1) + total_volumes(va_low - 2)
above_vol = buy_volumes(va_high + 1) + sell_volumes(va_high + 1) + buy_volumes(va_high + 2) + sell_volumes(va_high + 2)
below_vol = buy_volumes(va_low - 1) + sell_volumes(va_low - 1) + buy_volumes(va_low - 2) + sell_volumes(va_low - 2)
// increase value area volume with the max sum of volumes
// va_vol := va_vol + max(above_vol, below_vol)
// when above_vol > below_vol include the 2 rows above into the value area
// when above_vol = below_vol the area closest to the middle of the range is included in the Value Area
// and when they both have the same volume and are also equidistant from the middle of the range - only the above area is included
if (va_high <= num_levels)
if (above_vol > below_vol) or ( (above_vol == below_vol) and (abs(va_high + 2 - mid_index) <= abs(va_low - 2 - mid_index)) )
va_high := va_high + 2
va_vol := va_vol + above_vol
// when above_vol < below_vol include the 2 rows below into the value area
if (va_low > 0)
if (above_vol < below_vol) or ( (above_vol == below_vol) and (abs(va_high + 2 - mid_index) > abs(va_low - 2 - mid_index)) )
va_low := va_low - 2
va_vol := va_vol + below_vol
// value area limit target reached or the whole range is processed
if (va_vol >= va_limit) or ((va_low <= 0) and (va_high > num_levels))
break
va_high := (va_high > num_levels) ? num_levels : va_high
va_low := (va_low <= 0) ? 1 : va_low
// both va low / va high include their underlying levels
// low boundary of a level = level, high boundary of a level = level_top
va_high_level := pl + va_high * h - spacing // h/2
// lower boundary of a level
va_low_level := pl + (va_low - 1) * h - spacing // h/2
// VWAP
vwap_level = vwap(vwap_src)
vwap_stdev = stdev(vwap_src, vwap_len) * stddev
vwap_up = vwap_level + vwap_stdev
vwap_down = vwap_level - vwap_stdev
// in VWAP mode POC2, VAH/VAL are reused and become => VWAP, VWAP High/Low to minimize plot outputs
// doesn't need a valid range
// in max vol sli mode - a slave indicator instance can show vwap levels, while the master instance - poc2/va levels
// wvap levels are the same for both master/slave versions - they are duplicate levels
if (levels_mode == "vwap")
poc2_level := vwap_level
va_high_level := vwap_up
va_low_level := vwap_down
// Buy/Sell/Total Lengths as % of Base Width
len1 = 0
len2 = 0
len3 = 0
len4 = 0
len5 = 0
len6 = 0
len7 = 0
len8 = 0
len9 = 0
len10 = 0
len11 = 0
len12 = 0
len13 = 0
len14 = 0
len15 = 0
len16 = 0
len17 = 0
len18 = 0
len19 = 0
len20 = 0
len21 = 0
len22 = 0
len23 = 0
len24 = 0
len25 = 0
len26 = 0
len27 = 0
len28 = 0
len29 = 0
len30 = 0
len31 = 0
len32 = 0
len33 = 0
len34 = 0
len35 = 0
len36 = 0
len37 = 0
len38 = 0
len39 = 0
len40 = 0
len41 = 0
len42 = 0
len43 = 0
len44 = 0
len45 = 0
len46 = 0
len47 = 0
len48 = 0
len49 = 0
len50 = 0
// calculate base level length
// - for total - we need to use max total volume
// - for buy/sell in normal mode => max_buy/max_sell volumes. individual max_buy/max_sell levels may differ from max_total
// - for buy/sell in buy_sell_sli_mode with extended buy + sell offset for sell => max total volume in both master/slave indicators
a = volume_type == "buy" ? 1 : volume_type == "sell" ? buy_sell_sli_mode ? 1 : 0 : volume_type == "total" ? 1 : 0
b = volume_type == "buy" ? 0 : volume_type == "sell" ? 1 : volume_type == "total" ? 1 : 0
vol1 = a * buy_vol1 + b * sell_vol1
vol2 = a * buy_vol2 + b * sell_vol2
vol3 = a * buy_vol3 + b * sell_vol3
vol4 = a * buy_vol4 + b * sell_vol4
vol5 = a * buy_vol5 + b * sell_vol5
vol6 = a * buy_vol6 + b * sell_vol6
vol7 = a * buy_vol7 + b * sell_vol7
vol8 = a * buy_vol8 + b * sell_vol8
vol9 = a * buy_vol9 + b * sell_vol9
vol10 = a * buy_vol10 + b * sell_vol10
vol11 = a * buy_vol11 + b * sell_vol11
vol12 = a * buy_vol12 + b * sell_vol12
vol13 = a * buy_vol13 + b * sell_vol13
vol14 = a * buy_vol14 + b * sell_vol14
vol15 = a * buy_vol15 + b * sell_vol15
vol16 = a * buy_vol16 + b * sell_vol16
vol17 = a * buy_vol17 + b * sell_vol17
vol18 = a * buy_vol18 + b * sell_vol18
vol19 = a * buy_vol19 + b * sell_vol19
vol20 = a * buy_vol20 + b * sell_vol20
vol21 = a * buy_vol21 + b * sell_vol21
vol22 = a * buy_vol22 + b * sell_vol22
vol23 = a * buy_vol23 + b * sell_vol23
vol24 = a * buy_vol24 + b * sell_vol24
vol25 = a * buy_vol25 + b * sell_vol25
vol26 = a * buy_vol26 + b * sell_vol26
vol27 = a * buy_vol27 + b * sell_vol27
vol28 = a * buy_vol28 + b * sell_vol28
vol29 = a * buy_vol29 + b * sell_vol29
vol30 = a * buy_vol30 + b * sell_vol30
vol31 = a * buy_vol31 + b * sell_vol31
vol32 = a * buy_vol32 + b * sell_vol32
vol33 = a * buy_vol33 + b * sell_vol33
vol34 = a * buy_vol34 + b * sell_vol34
vol35 = a * buy_vol35 + b * sell_vol35
vol36 = a * buy_vol36 + b * sell_vol36
vol37 = a * buy_vol37 + b * sell_vol37
vol38 = a * buy_vol38 + b * sell_vol38
vol39 = a * buy_vol39 + b * sell_vol39
vol40 = a * buy_vol40 + b * sell_vol40
vol41 = a * buy_vol41 + b * sell_vol41
vol42 = a * buy_vol42 + b * sell_vol42
vol43 = a * buy_vol43 + b * sell_vol43
vol44 = a * buy_vol44 + b * sell_vol44
vol45 = a * buy_vol45 + b * sell_vol45
vol46 = a * buy_vol46 + b * sell_vol46
vol47 = a * buy_vol47 + b * sell_vol47
vol48 = a * buy_vol48 + b * sell_vol48
vol49 = a * buy_vol49 + b * sell_vol49
vol50 = a * buy_vol50 + b * sell_vol50
// check for non empty volume range, prevent division by zero
if max_vol > 0
len1 := floor(vol1/max_vol * length)
len2 := floor(vol2/max_vol * length)
len3 := floor(vol3/max_vol * length)
len4 := floor(vol4/max_vol * length)
len5 := floor(vol5/max_vol * length)
len6 := floor(vol6/max_vol * length)
len7 := floor(vol7/max_vol * length)
len8 := floor(vol8/max_vol * length)
len9 := floor(vol9/max_vol * length)
len10 := floor(vol10/max_vol * length)
len11 := floor(vol11/max_vol * length)
len12 := floor(vol12/max_vol * length)
len13 := floor(vol13/max_vol * length)
len14 := floor(vol14/max_vol * length)
len15 := floor(vol15/max_vol * length)
len16 := floor(vol16/max_vol * length)
len17 := floor(vol17/max_vol * length)
len18 := floor(vol18/max_vol * length)
len19 := floor(vol19/max_vol * length)
len20 := floor(vol20/max_vol * length)
len21 := floor(vol21/max_vol * length)
len22 := floor(vol22/max_vol * length)
len23 := floor(vol23/max_vol * length)
len24 := floor(vol24/max_vol * length)
len25 := floor(vol25/max_vol * length)
len26 := floor(vol26/max_vol * length)
len27 := floor(vol27/max_vol * length)
len28 := floor(vol28/max_vol * length)
len29 := floor(vol29/max_vol * length)
len30 := floor(vol30/max_vol * length)
len31 := floor(vol31/max_vol * length)
len32 := floor(vol32/max_vol * length)
len33 := floor(vol33/max_vol * length)
len34 := floor(vol34/max_vol * length)
len35 := floor(vol35/max_vol * length)
len36 := floor(vol36/max_vol * length)
len37 := floor(vol37/max_vol * length)
len38 := floor(vol38/max_vol * length)
len39 := floor(vol39/max_vol * length)
len40 := floor(vol40/max_vol * length)
len41 := floor(vol41/max_vol * length)
len42 := floor(vol42/max_vol * length)
len43 := floor(vol43/max_vol * length)
len44 := floor(vol44/max_vol * length)
len45 := floor(vol45/max_vol * length)
len46 := floor(vol46/max_vol * length)
len47 := floor(vol47/max_vol * length)
len48 := floor(vol48/max_vol * length)
len49 := floor(vol49/max_vol * length)
len50 := floor(vol50/max_vol * length)
// Buy/Sell Levels
// levels are relative to pl with step h
level1 = pl + 0 * h
level2 = pl + 1 * h
level3 = pl + 2 * h
level4 = pl + 3 * h
level5 = pl + 4 * h
level6 = pl + 5 * h
level7 = pl + 6 * h
level8 = pl + 7 * h
level9 = pl + 8 * h
level10 = pl + 9 * h
level11 = pl + 10 * h
level12 = pl + 11 * h
level13 = pl + 12 * h
level14 = pl + 13 * h
level15 = pl + 14 * h
level16 = pl + 15 * h
level17 = pl + 16 * h
level18 = pl + 17 * h
level19 = pl + 18 * h
level20 = pl + 19 * h
level21 = pl + 20 * h
level22 = pl + 21 * h
level23 = pl + 22 * h
level24 = pl + 23 * h
level25 = pl + 24 * h
level26 = pl + 25 * h
level27 = pl + 26 * h
level28 = pl + 27 * h
level29 = pl + 28 * h
level30 = pl + 29 * h
level31 = pl + 30 * h
level32 = pl + 31 * h
level33 = pl + 32 * h
level34 = pl + 33 * h
level35 = pl + 34 * h
level36 = pl + 35 * h
level37 = pl + 36 * h
level38 = pl + 37 * h
level39 = pl + 38 * h
level40 = pl + 39 * h
level41 = pl + 40 * h
level42 = pl + 41 * h
level43 = pl + 42 * h
level44 = pl + 43 * h
level45 = pl + 44 * h
level46 = pl + 45 * h
level47 = pl + 46 * h
level48 = pl + 47 * h
level49 = pl + 48 * h
level50 = pl + 49 * h
// level tops - height of the histogram bar for a level
level1_top = level1 + h - spacing
level2_top = level2 + h - spacing
level3_top = level3 + h - spacing
level4_top = level4 + h - spacing
level5_top = level5 + h - spacing
level6_top = level6 + h - spacing
level7_top = level7 + h - spacing
level8_top = level8 + h - spacing
level9_top = level9 + h - spacing
level10_top = level10 + h - spacing
level11_top = level11 + h - spacing
level12_top = level12 + h - spacing
level13_top = level13 + h - spacing
level14_top = level14 + h - spacing
level15_top = level15 + h - spacing
level16_top = level16 + h - spacing
level17_top = level17 + h - spacing
level18_top = level18 + h - spacing
level19_top = level19 + h - spacing
level20_top = level20 + h - spacing
level21_top = level21 + h - spacing
level22_top = level22 + h - spacing
level23_top = level23 + h - spacing
level24_top = level24 + h - spacing
level25_top = level25 + h - spacing
level26_top = level26 + h - spacing
level27_top = level27 + h - spacing
level28_top = level28 + h - spacing
level29_top = level29 + h - spacing
level30_top = level30 + h - spacing
level31_top = level31 + h - spacing
level32_top = level32 + h - spacing
level33_top = level33 + h - spacing
level34_top = level34 + h - spacing
level35_top = level35 + h - spacing
level36_top = level36 + h - spacing
level37_top = level37 + h - spacing
level38_top = level38 + h - spacing
level39_top = level39 + h - spacing
level40_top = level40 + h - spacing
level41_top = level41 + h - spacing
level42_top = level42 + h - spacing
level43_top = level43 + h - spacing
level44_top = level44 + h - spacing
level45_top = level45 + h - spacing
level46_top = level46 + h - spacing
level47_top = level47 + h - spacing
level48_top = level48 + h - spacing
level49_top = level49 + h - spacing
level50_top = level50 + h - spacing
// Level Offsets
dir = flip_levels ? 1 : -1
range_offset = anchor == "cur bar" ? 0 : anchor == "range start" ? start_bar : start_bar + range - 1
// zero line offset
// zero offset is added to the anchor point
z_offset = zero_offset - range_offset
// for levels facing left from zero (default) - apply offset to the last bar, for flipped levels facing right from zero - apply offset to the first bar
l_offset = dir == 1 ? z_offset : z_offset + length
// micro adjustments for zero and cover offsets depending on the cover/level histogram bar width for proper alignment
adj_z_offset = z_offset - dir * adj_zero_offset
c_offset = dir == 1 ? z_offset : z_offset + length
c_offset := c_offset - dir * cover_offset
// for plotshape you need z_offset, for plot columns - l_offset with length
// relative to zero = inverse dir
poc_offset := z_offset - dir * poc_offset
va_offset := z_offset - dir * va_offset
offset1 = l_offset + dir * len1
offset2 = l_offset + dir * len2
offset3 = l_offset + dir * len3
offset4 = l_offset + dir * len4
offset5 = l_offset + dir * len5
offset6 = l_offset + dir * len6
offset7 = l_offset + dir * len7
offset8 = l_offset + dir * len8
offset9 = l_offset + dir * len9
offset10 = l_offset + dir * len10
offset11 = l_offset + dir * len11
offset12 = l_offset + dir * len12
offset13 = l_offset + dir * len13
offset14 = l_offset + dir * len14
offset15 = l_offset + dir * len15
offset16 = l_offset + dir * len16
offset17 = l_offset + dir * len17
offset18 = l_offset + dir * len18
offset19 = l_offset + dir * len19
offset20 = l_offset + dir * len20
offset21 = l_offset + dir * len21
offset22 = l_offset + dir * len22
offset23 = l_offset + dir * len23
offset24 = l_offset + dir * len24
offset25 = l_offset + dir * len25
offset26 = l_offset + dir * len26
offset27 = l_offset + dir * len27
offset28 = l_offset + dir * len28
offset29 = l_offset + dir * len29
offset30 = l_offset + dir * len30
offset31 = l_offset + dir * len31
offset32 = l_offset + dir * len32
offset33 = l_offset + dir * len33
offset34 = l_offset + dir * len34
offset35 = l_offset + dir * len35
offset36 = l_offset + dir * len36
offset37 = l_offset + dir * len37
offset38 = l_offset + dir * len38
offset39 = l_offset + dir * len39
offset40 = l_offset + dir * len40
offset41 = l_offset + dir * len41
offset42 = l_offset + dir * len42
offset43 = l_offset + dir * len43
offset44 = l_offset + dir * len44
offset45 = l_offset + dir * len45
offset46 = l_offset + dir * len46
offset47 = l_offset + dir * len47
offset48 = l_offset + dir * len48
offset49 = l_offset + dir * len49
offset50 = l_offset + dir * len50
// Levels
// this script uses max 64 plot outputs:
// - 50 * 1x color plots (levels) = 50
// - 2 * 1x color plots (zero + cover) = 2
// - 2 * 2x color plots (poc levels) = 4
// - 2 * 2x color plots (va lines) + 2 * 1x color plots (va zones) = 6
// - 1 * 1x color plot (bgcolor) = 1
// - 1 * 1x color plot (max_vol for sli) = 1
//
// - you can't plot dynamic profile levels using plotchar because you can't modify show_last in script - can ony hide using is_in_range na cond, but can't delete history
// - you can only plot dynamic levels using text labels - prototype discarded
// - histbase can't be var/function/mutable (doesn't affect the output), can only be const expression, can be set from input
// - line_width affects only line and histogram styles, not columns
//
// Pro Tip:
// - you can use Atom/VS Code multi-caret editing, auto numbering and pine snippets to speed up code generation and even debug it in some cases (FF60+ also supports multi-caret editing)
// - the following set of 50 lines is auto generated by these 2 Emmet lines (Ctrl-E to expand in Atom):
// {plot(show_levels and (num_levels >= $) ? level$_top : na, title="Volume $", style=level_style, histbase=level$, color=level_color, transp=level_transp, offset=offset$, show_last=length)
// }*50
// you can only have 50 levels
plot(show_levels and (num_levels >= 1) ? level1_top : na, title="Volume 1", style=level_style, histbase=level1, color=level_color, transp=level_transp, offset=offset1, show_last=length)
plot(show_levels and (num_levels >= 2) ? level2_top : na, title="Volume 2", style=level_style, histbase=level2, color=level_color, transp=level_transp, offset=offset2, show_last=length)
plot(show_levels and (num_levels >= 3) ? level3_top : na, title="Volume 3", style=level_style, histbase=level3, color=level_color, transp=level_transp, offset=offset3, show_last=length)
plot(show_levels and (num_levels >= 4) ? level4_top : na, title="Volume 4", style=level_style, histbase=level4, color=level_color, transp=level_transp, offset=offset4, show_last=length)
plot(show_levels and (num_levels >= 5) ? level5_top : na, title="Volume 5", style=level_style, histbase=level5, color=level_color, transp=level_transp, offset=offset5, show_last=length)
plot(show_levels and (num_levels >= 6) ? level6_top : na, title="Volume 6", style=level_style, histbase=level6, color=level_color, transp=level_transp, offset=offset6, show_last=length)
plot(show_levels and (num_levels >= 7) ? level7_top : na, title="Volume 7", style=level_style, histbase=level7, color=level_color, transp=level_transp, offset=offset7, show_last=length)
plot(show_levels and (num_levels >= 8) ? level8_top : na, title="Volume 8", style=level_style, histbase=level8, color=level_color, transp=level_transp, offset=offset8, show_last=length)
plot(show_levels and (num_levels >= 9) ? level9_top : na, title="Volume 9", style=level_style, histbase=level9, color=level_color, transp=level_transp, offset=offset9, show_last=length)
plot(show_levels and (num_levels >= 10) ? level10_top : na, title="Volume 10", style=level_style, histbase=level10, color=level_color, transp=level_transp, offset=offset10, show_last=length)
plot(show_levels and (num_levels >= 11) ? level11_top : na, title="Volume 11", style=level_style, histbase=level11, color=level_color, transp=level_transp, offset=offset11, show_last=length)
plot(show_levels and (num_levels >= 12) ? level12_top : na, title="Volume 12", style=level_style, histbase=level12, color=level_color, transp=level_transp, offset=offset12, show_last=length)
plot(show_levels and (num_levels >= 13) ? level13_top : na, title="Volume 13", style=level_style, histbase=level13, color=level_color, transp=level_transp, offset=offset13, show_last=length)
plot(show_levels and (num_levels >= 14) ? level14_top : na, title="Volume 14", style=level_style, histbase=level14, color=level_color, transp=level_transp, offset=offset14, show_last=length)
plot(show_levels and (num_levels >= 15) ? level15_top : na, title="Volume 15", style=level_style, histbase=level15, color=level_color, transp=level_transp, offset=offset15, show_last=length)
plot(show_levels and (num_levels >= 16) ? level16_top : na, title="Volume 16", style=level_style, histbase=level16, color=level_color, transp=level_transp, offset=offset16, show_last=length)
plot(show_levels and (num_levels >= 17) ? level17_top : na, title="Volume 17", style=level_style, histbase=level17, color=level_color, transp=level_transp, offset=offset17, show_last=length)
plot(show_levels and (num_levels >= 18) ? level18_top : na, title="Volume 18", style=level_style, histbase=level18, color=level_color, transp=level_transp, offset=offset18, show_last=length)
plot(show_levels and (num_levels >= 19) ? level19_top : na, title="Volume 19", style=level_style, histbase=level19, color=level_color, transp=level_transp, offset=offset19, show_last=length)
plot(show_levels and (num_levels >= 20) ? level20_top : na, title="Volume 20", style=level_style, histbase=level20, color=level_color, transp=level_transp, offset=offset20, show_last=length)
plot(show_levels and (num_levels >= 21) ? level21_top : na, title="Volume 21", style=level_style, histbase=level21, color=level_color, transp=level_transp, offset=offset21, show_last=length)
plot(show_levels and (num_levels >= 22) ? level22_top : na, title="Volume 22", style=level_style, histbase=level22, color=level_color, transp=level_transp, offset=offset22, show_last=length)
plot(show_levels and (num_levels >= 23) ? level23_top : na, title="Volume 23", style=level_style, histbase=level23, color=level_color, transp=level_transp, offset=offset23, show_last=length)
plot(show_levels and (num_levels >= 24) ? level24_top : na, title="Volume 24", style=level_style, histbase=level24, color=level_color, transp=level_transp, offset=offset24, show_last=length)
plot(show_levels and (num_levels >= 25) ? level25_top : na, title="Volume 25", style=level_style, histbase=level25, color=level_color, transp=level_transp, offset=offset25, show_last=length)
plot(show_levels and (num_levels >= 26) ? level26_top : na, title="Volume 26", style=level_style, histbase=level26, color=level_color, transp=level_transp, offset=offset26, show_last=length)
plot(show_levels and (num_levels >= 27) ? level27_top : na, title="Volume 27", style=level_style, histbase=level27, color=level_color, transp=level_transp, offset=offset27, show_last=length)
plot(show_levels and (num_levels >= 28) ? level28_top : na, title="Volume 28", style=level_style, histbase=level28, color=level_color, transp=level_transp, offset=offset28, show_last=length)
plot(show_levels and (num_levels >= 29) ? level29_top : na, title="Volume 29", style=level_style, histbase=level29, color=level_color, transp=level_transp, offset=offset29, show_last=length)
plot(show_levels and (num_levels >= 30) ? level30_top : na, title="Volume 30", style=level_style, histbase=level30, color=level_color, transp=level_transp, offset=offset30, show_last=length)
plot(show_levels and (num_levels >= 31) ? level31_top : na, title="Volume 31", style=level_style, histbase=level31, color=level_color, transp=level_transp, offset=offset31, show_last=length)
plot(show_levels and (num_levels >= 32) ? level32_top : na, title="Volume 32", style=level_style, histbase=level32, color=level_color, transp=level_transp, offset=offset32, show_last=length)
plot(show_levels and (num_levels >= 33) ? level33_top : na, title="Volume 33", style=level_style, histbase=level33, color=level_color, transp=level_transp, offset=offset33, show_last=length)
plot(show_levels and (num_levels >= 34) ? level34_top : na, title="Volume 34", style=level_style, histbase=level34, color=level_color, transp=level_transp, offset=offset34, show_last=length)
plot(show_levels and (num_levels >= 35) ? level35_top : na, title="Volume 35", style=level_style, histbase=level35, color=level_color, transp=level_transp, offset=offset35, show_last=length)
plot(show_levels and (num_levels >= 36) ? level36_top : na, title="Volume 36", style=level_style, histbase=level36, color=level_color, transp=level_transp, offset=offset36, show_last=length)
plot(show_levels and (num_levels >= 37) ? level37_top : na, title="Volume 37", style=level_style, histbase=level37, color=level_color, transp=level_transp, offset=offset37, show_last=length)
plot(show_levels and (num_levels >= 38) ? level38_top : na, title="Volume 38", style=level_style, histbase=level38, color=level_color, transp=level_transp, offset=offset38, show_last=length)
plot(show_levels and (num_levels >= 39) ? level39_top : na, title="Volume 39", style=level_style, histbase=level39, color=level_color, transp=level_transp, offset=offset39, show_last=length)
plot(show_levels and (num_levels >= 40) ? level40_top : na, title="Volume 40", style=level_style, histbase=level40, color=level_color, transp=level_transp, offset=offset40, show_last=length)
plot(show_levels and (num_levels >= 41) ? level41_top : na, title="Volume 41", style=level_style, histbase=level41, color=level_color, transp=level_transp, offset=offset41, show_last=length)
plot(show_levels and (num_levels >= 42) ? level42_top : na, title="Volume 42", style=level_style, histbase=level42, color=level_color, transp=level_transp, offset=offset42, show_last=length)
plot(show_levels and (num_levels >= 43) ? level43_top : na, title="Volume 43", style=level_style, histbase=level43, color=level_color, transp=level_transp, offset=offset43, show_last=length)
plot(show_levels and (num_levels >= 44) ? level44_top : na, title="Volume 44", style=level_style, histbase=level44, color=level_color, transp=level_transp, offset=offset44, show_last=length)
plot(show_levels and (num_levels >= 45) ? level45_top : na, title="Volume 45", style=level_style, histbase=level45, color=level_color, transp=level_transp, offset=offset45, show_last=length)
plot(show_levels and (num_levels >= 46) ? level46_top : na, title="Volume 46", style=level_style, histbase=level46, color=level_color, transp=level_transp, offset=offset46, show_last=length)
plot(show_levels and (num_levels >= 47) ? level47_top : na, title="Volume 47", style=level_style, histbase=level47, color=level_color, transp=level_transp, offset=offset47, show_last=length)
plot(show_levels and (num_levels >= 48) ? level48_top : na, title="Volume 48", style=level_style, histbase=level48, color=level_color, transp=level_transp, offset=offset48, show_last=length)
plot(show_levels and (num_levels >= 49) ? level49_top : na, title="Volume 49", style=level_style, histbase=level49, color=level_color, transp=level_transp, offset=offset49, show_last=length)
plot(show_levels and (num_levels >= 50) ? level50_top : na, title="Volume 50", style=level_style, histbase=level50, color=level_color, transp=level_transp, offset=offset50, show_last=length)
// Zero line, Cover
// can't assign show_last dynamically must use a set of 2 plots
plot(show_cover ? ph : na, title="Side Cover", style=histogram, histbase=pl, color=cover_color, linewidth=cover_width, transp=0, offset=c_offset, show_last=length)
plot(show_zero ? ph : na, title="Zero Line", style=histogram, histbase=pl, color=zero_color, linewidth=zero_width, offset=adj_z_offset, show_last=1)
// POC Lines
// - POC line is a dynamic level and can't be a plot because you can't delete history. Dynamic levels can only be implemented with plotshape/plotchar fixed str text labels
// - you can't set textcolor from TradingView Style UI, its color option only affects plot color, not textcolor => custom textbox input for textcolor and str to color conversion is necessary
// - setting only textcolor from input: 1x color => 2x color outputs
// - setting both color and textcolor from input: 1x color => 3x color outputs - would reduce the number of levels even more - you can manually set shape (dot) color from Style UI instead
poc_col = get_color(poc_col_str, poc_color)
poc2_col = get_color(poc2_col_str, poc2_color)
// in VWAP mode Developing POC => VWAP Level
if levels_mode == "vwap"
poc2_col := get_color(vwap_col_str, vwap_color)
// POC and developing POC (2nd largest traded volume)
// don' confuse poc_color (1x outputs) with poc_col (2x outputs)
plotshape(show_poc and (poc_level > 0) ? poc_level : na, title="POC Level", style=shape.circle, color=poc_color, text=poc_text, textcolor=poc_col, transp=0, location=location.absolute, size=size.auto, offset=poc_offset, show_last=1)
plotshape(show_poc2 and (poc2_level > 0) ? poc2_level : na, title="Developing POC/VWAP Level", style=shape.circle, color=poc2_color, text=poc_text, textcolor=poc2_col, transp=0, location=location.absolute, size=size.auto, offset=poc_offset, show_last=1)
// Value Area/VWAP High/Low
va_high_col = get_color(va_high_col_str, va_high_color)
va_low_col = get_color(va_low_col_str, va_low_color)
// in VWAP mode VAH/VAL => VWAP High/Low
if levels_mode == "vwap"
va_high_col := get_color(vwap_high_col_str, vwap_high_color)
va_low_col := get_color(vwap_low_col_str, vwap_low_color)
// VA mode 2 - zones
// textcolor = na => 2x plot outputs
va_zone_high = va_high_level + spacing
va_zone_low = va_low_level + spacing
plotshape(show_va and dim_nva_zones and (va_high_level > 0) ? va_zone_high : na, title="Zone Above VA/VWAP High", style=shape.labeldown, color=nva_zone_color, text=va_high2_text, textcolor=nva_zone_color, transp=20, location=location.absolute, size=size.auto, offset=va_offset, show_last=1)
plotshape(show_va and dim_nva_zones and (va_low_level > 0) ? va_zone_low : na, title="Zone Below VA/VWAP Low", style=shape.labelup, color=nva_zone_color, text=va_low2_text, textcolor=nva_zone_color, transp=20, location=location.absolute, size=size.auto, offset=va_offset, show_last=1)
// VA mode 1 - lines
// objects further down are plotted above prev ones - lines must remain after zones
// don' confuse va_high_color (1x outputs) with va_high_col (2x outputs)
plotshape(show_va and (va_high_level > 0) ? va_high_level : na, title="VA/VWAP High", style=shape.circle, color=va_high_color, text=va_high1_text, textcolor=va_high_col, transp=0, location=location.absolute, size=size.auto, offset=va_offset, show_last=1)
plotshape(show_va and (va_low_level > 0) ? va_low_level : na, title="VA/VWAP Low", style=shape.circle, color=va_low_color, text=va_low1_text, textcolor=va_low_col, transp=0, location=location.absolute, size=size.auto, offset=va_offset, show_last=1)
// Highlight Range
bgcolor_cond = highlight_background and is_in_range ? range_bg_color : na
bgcolor(bgcolor_cond, title="Range Background Highlight Color")
// not enough plot outputs for this
// barcolor_cond = highlight_bars and is_in_range ? range_bar_color : na
// barcolor(barcolor_cond, title="Range Bar Highlight Color")
// Max Volume for Vertical SLI
plot(show_max_vol_sli ? max_vol : na, color=red, title="Max Volume For Vertical SLI Mode", show_last=1)
// plot(n, color=red)