本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。
//@version=4
study("Volume Profile Free Ultra SLI by RRB", shorttitle="VolumeProfileFree_Ultra_RRB", overlay=true)
// Volume Profile Free Ultra SLI by RagingRocketBull 2019
// Version 1.0
//
// This indicator calculates Volume Profile for a given range and shows it as a histogram consisting of 100 horizontal bars.
// This is basically the MAX SLI version with +50 more Pinescript v4 line objects added as levels.
// 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 Ultra SLI, Free History. This is the Free Ultra 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, 2x SLI modes for Buy/Sell or even higher res 150 levels
// - Free Ultra SLI: 100 levels, packed to the limit, 2x SLI modes for Buy/Sell or even higher res 300 levels
// - Free History: auto highest/lowest, historic poc/va levels for each session
//
// Features:
// - High-Res Volume Profile with up to 100 levels (line implementation)
// - 2x SLI modes for even higher res: 300 levels with 3x vertical SLI, 100 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, Transparency for buy/sell levels
//
// WARNING:
// - Compilation Time: 1 min 20 sec
//
// 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 Buy/Sell SLI mode with 100 or Vertical SLI with 300 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 100 Buy/Sell Levels at the same time
// - Vertical Max_Vol 3x SLI lets you increase the resolution to 300 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 and may be inaccurate. 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 (you can have a mixed mode: 2nd instance - auto, 3rd - manual)
//
//
// Notes:
// - This code uses Pinescript v3 compatibility framework
// - This code is 20x-30x faster (main for cycle is removed) especially on lower tfs with long history - only 4-5 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
// - 100 levels consist of 50 main plot levels and 50 line objects used as alternate levels, differences are:
// - line objects are always shown on top of other objects, such as plot levels, zero line and side cover, it's not possible to cover/move them below.
// - all line objects have variable lengths, use actual x,y coords and don't need side cover, while all plot levels have a fixed length of 100 bars, use offset and require cover.
// - all key properties of line objects, such as x,y coords, color can be modified, objects can be moved/deleted, while this is not possible for static plot levels.
// - large width values cause line objects to expand only up/down from center while their length remains the same and stays within the level's start/end points similar to an area style.
// - large width values make plot levels expand in all directions (both h/v), beyond level start/end points, sometimes overlapping zero line, making them an inaccurate % length representation, as opposed to line objects/plot levels with area style.
// - large width values translate into different widths on screen for line objects and plot levels.
// - you can't compensate for this unwanted horiz width expansion of plot levels because width uses its own units, that don't translate into bars/pixels.
// - line objects are visible only when num_levels > 50, plot levels are used otherwise
// - Since line objects are lines, plot levels also use style line because other style implementations will break the symmetry/spacing between levels.
// - 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 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
// - You can change level transparency of line objects. Due to Pinescript limitations, only discrete values are supported.
// - Inverse transp correlation creates the necessary illusion of "covered" line objects, although they are shown on top of the cover all the time
// - If custom lines_transp is set the illusion will break because transp range can't be skewed easily (i.e. transp 0..100 is always mapped to 100..0 and can't be mapped to 50..0)
// - transparency can applied to lines dynamically but nva top zone can't be completely removed because plot/mixed type of levels are still used when num_levels < 50 and require cover
// - transparency can't be applied to plot levels dynamically from script this can be done only once from UI, and you can't change plot color for the past length bars
// - 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
// - Range selection/Anchoring is not accurate on charts with time gaps since you can only anchor from a point in the future and measure distance in time periods, not actual bars, and there's no way of knowing the number of future gaps in advance.
// - Adjust Width for Log Scale mode now also works on high precision charts with small prices (i.e. 0.00001)
// - in Adjust Width for Log Scale mode Level1 width extremes can be capped using max deviation (when level1 = 0, shift = 0 width becomes infinite)
// - 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. I am your grandfather, Luke! Now, join the Dark Side in your father's steps or be destroyed! Once more the Sith will rule the Galaxy, and we shall have peace...
// 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/
//
// ================================================================================================================
// Pinescript v3 Compatibility Framework
// This code makes most v3 scripts work in v4 with only a few minor changes below. Place this code before the first input statement
// some lines are commented out to minimize the total number of vars used <= max 1000 vars limit
// Input types
// types can't be var names hence _
bool_ = input.bool
integer_ = input.integer
float_ = input.float
string_ = input.string
// resolution = input.resolution
// session = input.session
source = input.source
// symbol = input.symbol
// doesn't work
// color_ = input.color
// Styles
// plot styles
// line can't be a var name
lines = plot.style_line
// linebr = plot.style_linebr
// stepline = plot.style_stepline
histogram = plot.style_histogram
// cross = plot.style_cross
area = plot.style_area
// areabr = plot.style_areabr
// columns = plot.style_columns
// circles = plot.style_circles
// hline styles
// solid = hline.style_solid
// dotted = hline.style_dotted
// dashed = hline.style_dashed
// Colors
aqua = color.aqua
black = color.black
blue = color.blue
fuchsia = color.fuchsia
gray = color.gray
green = color.green
lime = color.lime
maroon = color.maroon
navy = color.navy
olive = color.olive
orange = color.orange
purple = color.purple
red = color.red
silver = color.silver
teal = color.teal
white = color.white
yellow = color.yellow
// doesn't work
// color can't be a var name error, transp can't be int must be const, const param becomes int var
// color_(col, transp) =>
// color.new(col, transp)
// Days
// monday = dayofweek.monday
// tuesday = dayofweek.tuesday
// wednesday = dayofweek.wednesday
// thursday = dayofweek.thursday
// friday = dayofweek.friday
// saturday = dayofweek.saturday
// sunday = dayofweek.sunday
// Timeframe
interval = timeframe.multiplier
period = timeframe.period
isintraday = timeframe.isintraday
isdaily = timeframe.isdaily
isweekly = timeframe.isweekly
ismonthly = timeframe.ismonthly
// isdwm = timeframe.isdwm
// Ticker
// ticker = syminfo.ticker
// tickerid = syminfo.tickerid
// Bar index
n = bar_index
// ================================================================================================================
// Inputs
// ================================================================================================================
// Show/Hide Flags
show_levels = input(true, type=bool_, title="Show Plot Levels")
show_lines = input(true, type=bool_, title="Show Alternate 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")
adjust_width = input(false, type=bool_, title="Adjust Level Width for Log Scale")
// 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(100, type=integer_, minval=0, maxval=100, title="Num Levels [0..100]")
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)")
// compensate level price for large width outline, % of step h
// important! either level_shift or 100.0 must be float otherwise level_shift/100 => integer 0 instead of 0.5! => width1 = 0, level1 shows with default tiny width=1
level_shift = input(50, type=float_, minval=0, maxval=100, title="Level Vertical Shift % (50% - middle)")
// you can only set width <= 4 in UI, hence these boxes allowing for larger values
// levels appear 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
line_width = input(12, type=integer_, title="Level Width")
// line_width is used for normal scale and line_width * width_multiplier for log scale, so that you can switch without adjusting each time
width_multiplier = input(200, type=float_, minval=0, title="Level Width Multiplier (Log Scale)")
// in adjust width for log scale mode when level1 = 0 (shift = 0) line_width1 = log(0) = na => disappears/becomes infinite and is assigned line_width2 * max_deviation instead
max_deviation = input(2, type=float_, minval=0, title="Max Level Width Deviation (Log Scale)")
zero_width = input(2, type=integer_, title="Zero Line Width")
// compensate for large width outline - cover additional area above/below, N = step h
cover_ext_height = input(2, type=integer_, title="Extend Cover by N Levels Up/Down/Right")
// Level Colors & Transparency
level_transp = input(40, type=integer_, minval=0, maxval=100, title="Plot Level Transparency [0..100]")
lines_transp = input(40, type=integer_, minval=0, maxval=100, title="Alternate Level Transparency [0..100], step 10", options=[0,10,20,30,40,50,60,70,80,90,100])
nva_transp = input(20, type=integer_, minval=0, maxval=100, title="Non Value Area Level Transparency [0..100], step 10", options=[0,10,20,30,40,50,60,70,80,90,100])
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
dim_transp = 20
// #0D68AF - default VPVR blue, #C18E24 - default VPVR yellow
level_color = #0D68AF // blue // teal // color(blue,90)
lines_color = color.new(#0D68AF, 40)
buy_color = green // color(green,90)
sell_color = red // color(red,90)
range_bg_color = color.new(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
ext_length = 50
// since line objects have a fixed style lines this style is also used for plot levels to make all levels look/behave similarly
level_style = lines
// 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
// in Pinescript v4 dots (.) or spaces at start/end are required or the whole \n string will be discarded as empty with only the first line visible
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
// ================================================================================================================
// working - not for highest/highestbars/security
// cast series to int
to_int(val) =>
k = 0
p = 0 // 0.0
d = 0.0 // can't be 0 int => can't assign series to int error
pow = 1
// for i = floor(val) to round(val)
// for i = 1 to round(val)
s = val
for i = 0 to 9
// get last digit
d := s % 10 // s - floor(s/10)*10
// k := k + 1 can't be inside if => series
// if s > 0
k := -1
for j = 0 to 9
k := k + 1
if j == d
break
pow := 1
if i > 0
for m = 0 to i-1
pow := 10 * pow
p := p + k * pow // can't use pow(10, i) => series
s := floor(s/10)
if s == 0
break
p
// 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 (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
// cast n to int to prevent can't assign series to int error later
// n - 0-based bar count, total bars = n + 1, first bar offset is always n
total_bars = to_int(n)
// start_bar can't exceed total_bars => in this case range starts and ends on the first bar n=0, has length 1 bar
// range can exceed total_bars
// start_bars = min(total_bars, start_bar)
// if range = 0 (All History) range_bars is always the offset to the first bar n=0 on the chart regardless of start_bar it is applied to cur_bar not start_bar
// range_bars = range == 0 ? max(0, min(total_bars, total_bars - start_bars)) : min(total_bars, start_bars + range - 1)
range_bars = range == 0 ? total_bars : range
first_bar = range == 0 ? total_bars : 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_start_bars = barssince(range_start)
// range_end = is_in_range and (range_start_bars == range_bars) // is_in_range[1] and not is_in_range - 1 bar lag
// range_end_bars = barssince(range_end)
// Range
// auto range
// will result in curves, not straight lines, due to variable min/max bounds
// you can't delete plot history or predict future highest/lowest points to expand the range
// ph = highest(range)
// pl = lowest(range)
// doesn't work - cover plot histbase must be a const expression, can be set from input, can't be var, mutable or function
// even if completely replaced with label object min/max level must be const because buy/sell vol is accumulated on each bar in this version
// ph := max_level > 0 ? min(max_level, ph) : ph
// pl := min_level > 0 ? max(min_level, pl) : pl
// fixed 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
var buy_vol1 = 0.0
var buy_vol2 = 0.0
var buy_vol3 = 0.0
var buy_vol4 = 0.0
var buy_vol5 = 0.0
var buy_vol6 = 0.0
var buy_vol7 = 0.0
var buy_vol8 = 0.0
var buy_vol9 = 0.0
var buy_vol10 = 0.0
var buy_vol11 = 0.0
var buy_vol12 = 0.0
var buy_vol13 = 0.0
var buy_vol14 = 0.0
var buy_vol15 = 0.0
var buy_vol16 = 0.0
var buy_vol17 = 0.0
var buy_vol18 = 0.0
var buy_vol19 = 0.0
var buy_vol20 = 0.0
var buy_vol21 = 0.0
var buy_vol22 = 0.0
var buy_vol23 = 0.0
var buy_vol24 = 0.0
var buy_vol25 = 0.0
var buy_vol26 = 0.0
var buy_vol27 = 0.0
var buy_vol28 = 0.0
var buy_vol29 = 0.0
var buy_vol30 = 0.0
var buy_vol31 = 0.0
var buy_vol32 = 0.0
var buy_vol33 = 0.0
var buy_vol34 = 0.0
var buy_vol35 = 0.0
var buy_vol36 = 0.0
var buy_vol37 = 0.0
var buy_vol38 = 0.0
var buy_vol39 = 0.0
var buy_vol40 = 0.0
var buy_vol41 = 0.0
var buy_vol42 = 0.0
var buy_vol43 = 0.0
var buy_vol44 = 0.0
var buy_vol45 = 0.0
var buy_vol46 = 0.0
var buy_vol47 = 0.0
var buy_vol48 = 0.0
var buy_vol49 = 0.0
var buy_vol50 = 0.0
var buy_vol51 = 0.0
var buy_vol52 = 0.0
var buy_vol53 = 0.0
var buy_vol54 = 0.0
var buy_vol55 = 0.0
var buy_vol56 = 0.0
var buy_vol57 = 0.0
var buy_vol58 = 0.0
var buy_vol59 = 0.0
var buy_vol60 = 0.0
var buy_vol61 = 0.0
var buy_vol62 = 0.0
var buy_vol63 = 0.0
var buy_vol64 = 0.0
var buy_vol65 = 0.0
var buy_vol66 = 0.0
var buy_vol67 = 0.0
var buy_vol68 = 0.0
var buy_vol69 = 0.0
var buy_vol70 = 0.0
var buy_vol71 = 0.0
var buy_vol72 = 0.0
var buy_vol73 = 0.0
var buy_vol74 = 0.0
var buy_vol75 = 0.0
var buy_vol76 = 0.0
var buy_vol77 = 0.0
var buy_vol78 = 0.0
var buy_vol79 = 0.0
var buy_vol80 = 0.0
var buy_vol81 = 0.0
var buy_vol82 = 0.0
var buy_vol83 = 0.0
var buy_vol84 = 0.0
var buy_vol85 = 0.0
var buy_vol86 = 0.0
var buy_vol87 = 0.0
var buy_vol88 = 0.0
var buy_vol89 = 0.0
var buy_vol90 = 0.0
var buy_vol91 = 0.0
var buy_vol92 = 0.0
var buy_vol93 = 0.0
var buy_vol94 = 0.0
var buy_vol95 = 0.0
var buy_vol96 = 0.0
var buy_vol97 = 0.0
var buy_vol98 = 0.0
var buy_vol99 = 0.0
var buy_vol100 = 0.0
var sell_vol1 = 0.0
var sell_vol2 = 0.0
var sell_vol3 = 0.0
var sell_vol4 = 0.0
var sell_vol5 = 0.0
var sell_vol6 = 0.0
var sell_vol7 = 0.0
var sell_vol8 = 0.0
var sell_vol9 = 0.0
var sell_vol10 = 0.0
var sell_vol11 = 0.0
var sell_vol12 = 0.0
var sell_vol13 = 0.0
var sell_vol14 = 0.0
var sell_vol15 = 0.0
var sell_vol16 = 0.0
var sell_vol17 = 0.0
var sell_vol18 = 0.0
var sell_vol19 = 0.0
var sell_vol20 = 0.0
var sell_vol21 = 0.0
var sell_vol22 = 0.0
var sell_vol23 = 0.0
var sell_vol24 = 0.0
var sell_vol25 = 0.0
var sell_vol26 = 0.0
var sell_vol27 = 0.0
var sell_vol28 = 0.0
var sell_vol29 = 0.0
var sell_vol30 = 0.0
var sell_vol31 = 0.0
var sell_vol32 = 0.0
var sell_vol33 = 0.0
var sell_vol34 = 0.0
var sell_vol35 = 0.0
var sell_vol36 = 0.0
var sell_vol37 = 0.0
var sell_vol38 = 0.0
var sell_vol39 = 0.0
var sell_vol40 = 0.0
var sell_vol41 = 0.0
var sell_vol42 = 0.0
var sell_vol43 = 0.0
var sell_vol44 = 0.0
var sell_vol45 = 0.0
var sell_vol46 = 0.0
var sell_vol47 = 0.0
var sell_vol48 = 0.0
var sell_vol49 = 0.0
var sell_vol50 = 0.0
var sell_vol51 = 0.0
var sell_vol52 = 0.0
var sell_vol53 = 0.0
var sell_vol54 = 0.0
var sell_vol55 = 0.0
var sell_vol56 = 0.0
var sell_vol57 = 0.0
var sell_vol58 = 0.0
var sell_vol59 = 0.0
var sell_vol60 = 0.0
var sell_vol61 = 0.0
var sell_vol62 = 0.0
var sell_vol63 = 0.0
var sell_vol64 = 0.0
var sell_vol65 = 0.0
var sell_vol66 = 0.0
var sell_vol67 = 0.0
var sell_vol68 = 0.0
var sell_vol69 = 0.0
var sell_vol70 = 0.0
var sell_vol71 = 0.0
var sell_vol72 = 0.0
var sell_vol73 = 0.0
var sell_vol74 = 0.0
var sell_vol75 = 0.0
var sell_vol76 = 0.0
var sell_vol77 = 0.0
var sell_vol78 = 0.0
var sell_vol79 = 0.0
var sell_vol80 = 0.0
var sell_vol81 = 0.0
var sell_vol82 = 0.0
var sell_vol83 = 0.0
var sell_vol84 = 0.0
var sell_vol85 = 0.0
var sell_vol86 = 0.0
var sell_vol87 = 0.0
var sell_vol88 = 0.0
var sell_vol89 = 0.0
var sell_vol90 = 0.0
var sell_vol91 = 0.0
var sell_vol92 = 0.0
var sell_vol93 = 0.0
var sell_vol94 = 0.0
var sell_vol95 = 0.0
var sell_vol96 = 0.0
var sell_vol97 = 0.0
var sell_vol98 = 0.0
var sell_vol99 = 0.0
var sell_vol100 = 0.0
// 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
int 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 faster than for i above especially on lower tfs with long history
// 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
if k == 51
buy_vol51 := dir >= 0 ? buy_vol51 + volume : buy_vol51
sell_vol51 := dir < 0 ? sell_vol51 + volume : sell_vol51
if k == 52
buy_vol52 := dir >= 0 ? buy_vol52 + volume : buy_vol52
sell_vol52 := dir < 0 ? sell_vol52 + volume : sell_vol52
if k == 53
buy_vol53 := dir >= 0 ? buy_vol53 + volume : buy_vol53
sell_vol53 := dir < 0 ? sell_vol53 + volume : sell_vol53
if k == 54
buy_vol54 := dir >= 0 ? buy_vol54 + volume : buy_vol54
sell_vol54 := dir < 0 ? sell_vol54 + volume : sell_vol54
if k == 55
buy_vol55 := dir >= 0 ? buy_vol55 + volume : buy_vol55
sell_vol55 := dir < 0 ? sell_vol55 + volume : sell_vol55
if k == 56
buy_vol56 := dir >= 0 ? buy_vol56 + volume : buy_vol56
sell_vol56 := dir < 0 ? sell_vol56 + volume : sell_vol56
if k == 57
buy_vol57 := dir >= 0 ? buy_vol57 + volume : buy_vol57
sell_vol57 := dir < 0 ? sell_vol57 + volume : sell_vol57
if k == 58
buy_vol58 := dir >= 0 ? buy_vol58 + volume : buy_vol58
sell_vol58 := dir < 0 ? sell_vol58 + volume : sell_vol58
if k == 59
buy_vol59 := dir >= 0 ? buy_vol59 + volume : buy_vol59
sell_vol59 := dir < 0 ? sell_vol59 + volume : sell_vol59
if k == 60
buy_vol60 := dir >= 0 ? buy_vol60 + volume : buy_vol60
sell_vol60 := dir < 0 ? sell_vol60 + volume : sell_vol60
if k == 61
buy_vol61 := dir >= 0 ? buy_vol61 + volume : buy_vol61
sell_vol61 := dir < 0 ? sell_vol61 + volume : sell_vol61
if k == 62
buy_vol62 := dir >= 0 ? buy_vol62 + volume : buy_vol62
sell_vol62 := dir < 0 ? sell_vol62 + volume : sell_vol62
if k == 63
buy_vol63 := dir >= 0 ? buy_vol63 + volume : buy_vol63
sell_vol63 := dir < 0 ? sell_vol63 + volume : sell_vol63
if k == 64
buy_vol64 := dir >= 0 ? buy_vol64 + volume : buy_vol64
sell_vol64 := dir < 0 ? sell_vol64 + volume : sell_vol64
if k == 65
buy_vol65 := dir >= 0 ? buy_vol65 + volume : buy_vol65
sell_vol65 := dir < 0 ? sell_vol65 + volume : sell_vol65
if k == 66
buy_vol66 := dir >= 0 ? buy_vol66 + volume : buy_vol66
sell_vol66 := dir < 0 ? sell_vol66 + volume : sell_vol66
if k == 67
buy_vol67 := dir >= 0 ? buy_vol67 + volume : buy_vol67
sell_vol67 := dir < 0 ? sell_vol67 + volume : sell_vol67
if k == 68
buy_vol68 := dir >= 0 ? buy_vol68 + volume : buy_vol68
sell_vol68 := dir < 0 ? sell_vol68 + volume : sell_vol68
if k == 69
buy_vol69 := dir >= 0 ? buy_vol69 + volume : buy_vol69
sell_vol69 := dir < 0 ? sell_vol69 + volume : sell_vol69
if k == 70
buy_vol70 := dir >= 0 ? buy_vol70 + volume : buy_vol70
sell_vol70 := dir < 0 ? sell_vol70 + volume : sell_vol70
if k == 71
buy_vol71 := dir >= 0 ? buy_vol71 + volume : buy_vol71
sell_vol71 := dir < 0 ? sell_vol71 + volume : sell_vol71
if k == 72
buy_vol72 := dir >= 0 ? buy_vol72 + volume : buy_vol72
sell_vol72 := dir < 0 ? sell_vol72 + volume : sell_vol72
if k == 73
buy_vol73 := dir >= 0 ? buy_vol73 + volume : buy_vol73
sell_vol73 := dir < 0 ? sell_vol73 + volume : sell_vol73
if k == 74
buy_vol74 := dir >= 0 ? buy_vol74 + volume : buy_vol74
sell_vol74 := dir < 0 ? sell_vol74 + volume : sell_vol74
if k == 75
buy_vol75 := dir >= 0 ? buy_vol75 + volume : buy_vol75
sell_vol75 := dir < 0 ? sell_vol75 + volume : sell_vol75
if k == 76
buy_vol76 := dir >= 0 ? buy_vol76 + volume : buy_vol76
sell_vol76 := dir < 0 ? sell_vol76 + volume : sell_vol76
if k == 77
buy_vol77 := dir >= 0 ? buy_vol77 + volume : buy_vol77
sell_vol77 := dir < 0 ? sell_vol77 + volume : sell_vol77
if k == 78
buy_vol78 := dir >= 0 ? buy_vol78 + volume : buy_vol78
sell_vol78 := dir < 0 ? sell_vol78 + volume : sell_vol78
if k == 79
buy_vol79 := dir >= 0 ? buy_vol79 + volume : buy_vol79
sell_vol79 := dir < 0 ? sell_vol79 + volume : sell_vol79
if k == 80
buy_vol80 := dir >= 0 ? buy_vol80 + volume : buy_vol80
sell_vol80 := dir < 0 ? sell_vol80 + volume : sell_vol80
if k == 81
buy_vol81 := dir >= 0 ? buy_vol81 + volume : buy_vol81
sell_vol81 := dir < 0 ? sell_vol81 + volume : sell_vol81
if k == 82
buy_vol82 := dir >= 0 ? buy_vol82 + volume : buy_vol82
sell_vol82 := dir < 0 ? sell_vol82 + volume : sell_vol82
if k == 83
buy_vol83 := dir >= 0 ? buy_vol83 + volume : buy_vol83
sell_vol83 := dir < 0 ? sell_vol83 + volume : sell_vol83
if k == 84
buy_vol84 := dir >= 0 ? buy_vol84 + volume : buy_vol84
sell_vol84 := dir < 0 ? sell_vol84 + volume : sell_vol84
if k == 85
buy_vol85 := dir >= 0 ? buy_vol85 + volume : buy_vol85
sell_vol85 := dir < 0 ? sell_vol85 + volume : sell_vol85
if k == 86
buy_vol86 := dir >= 0 ? buy_vol86 + volume : buy_vol86
sell_vol86 := dir < 0 ? sell_vol86 + volume : sell_vol86
if k == 87
buy_vol87 := dir >= 0 ? buy_vol87 + volume : buy_vol87
sell_vol87 := dir < 0 ? sell_vol87 + volume : sell_vol87
if k == 88
buy_vol88 := dir >= 0 ? buy_vol88 + volume : buy_vol88
sell_vol88 := dir < 0 ? sell_vol88 + volume : sell_vol88
if k == 89
buy_vol89 := dir >= 0 ? buy_vol89 + volume : buy_vol89
sell_vol89 := dir < 0 ? sell_vol89 + volume : sell_vol89
if k == 90
buy_vol90 := dir >= 0 ? buy_vol90 + volume : buy_vol90
sell_vol90 := dir < 0 ? sell_vol90 + volume : sell_vol90
if k == 91
buy_vol91 := dir >= 0 ? buy_vol91 + volume : buy_vol91
sell_vol91 := dir < 0 ? sell_vol91 + volume : sell_vol91
if k == 92
buy_vol92 := dir >= 0 ? buy_vol92 + volume : buy_vol92
sell_vol92 := dir < 0 ? sell_vol92 + volume : sell_vol92
if k == 93
buy_vol93 := dir >= 0 ? buy_vol93 + volume : buy_vol93
sell_vol93 := dir < 0 ? sell_vol93 + volume : sell_vol93
if k == 94
buy_vol94 := dir >= 0 ? buy_vol94 + volume : buy_vol94
sell_vol94 := dir < 0 ? sell_vol94 + volume : sell_vol94
if k == 95
buy_vol95 := dir >= 0 ? buy_vol95 + volume : buy_vol95
sell_vol95 := dir < 0 ? sell_vol95 + volume : sell_vol95
if k == 96
buy_vol96 := dir >= 0 ? buy_vol96 + volume : buy_vol96
sell_vol96 := dir < 0 ? sell_vol96 + volume : sell_vol96
if k == 97
buy_vol97 := dir >= 0 ? buy_vol97 + volume : buy_vol97
sell_vol97 := dir < 0 ? sell_vol97 + volume : sell_vol97
if k == 98
buy_vol98 := dir >= 0 ? buy_vol98 + volume : buy_vol98
sell_vol98 := dir < 0 ? sell_vol98 + volume : sell_vol98
if k == 99
buy_vol99 := dir >= 0 ? buy_vol99 + volume : buy_vol99
sell_vol99 := dir < 0 ? sell_vol99 + volume : sell_vol99
if k == 100
buy_vol100 := dir >= 0 ? buy_vol100 + volume : buy_vol100
sell_vol100 := dir < 0 ? sell_vol100 + volume : sell_vol100
// buy volumes array (read only)
// uses calculated buy/sell volumes - must remain after
// returns 0 instead of na - important!
// single buy_volume with 100 vars => script has a function with too many arguments: 101 => you must split it into 2 functions and call them separately
buy_volumes1(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
buy_volumes2(group) =>
res = group == 51 ? buy_vol51 : group == 52 ? buy_vol52 : group == 53 ? buy_vol53 : group == 54 ? buy_vol54 : group == 55 ? buy_vol55 : group == 56 ? buy_vol56 : group == 57 ? buy_vol57 : group == 58 ? buy_vol58 : group == 59 ? buy_vol59 : group == 60 ? buy_vol60 :
group == 61 ? buy_vol61 : group == 62 ? buy_vol62 : group == 63 ? buy_vol63 : group == 64 ? buy_vol64 : group == 65 ? buy_vol65 : group == 66 ? buy_vol66 : group == 67 ? buy_vol67 : group == 68 ? buy_vol68 : group == 69 ? buy_vol69 : group == 70 ? buy_vol70 :
group == 71 ? buy_vol71 : group == 72 ? buy_vol72 : group == 73 ? buy_vol73 : group == 74 ? buy_vol74 : group == 75 ? buy_vol75 : group == 76 ? buy_vol76 : group == 77 ? buy_vol77 : group == 78 ? buy_vol78 : group == 79 ? buy_vol79 : group == 80 ? buy_vol80 :
group == 81 ? buy_vol81 : group == 82 ? buy_vol82 : group == 83 ? buy_vol83 : group == 84 ? buy_vol84 : group == 85 ? buy_vol85 : group == 86 ? buy_vol86 : group == 87 ? buy_vol87 : group == 88 ? buy_vol88 : group == 89 ? buy_vol89 : group == 90 ? buy_vol90 :
group == 91 ? buy_vol91 : group == 92 ? buy_vol92 : group == 93 ? buy_vol93 : group == 94 ? buy_vol94 : group == 95 ? buy_vol95 : group == 96 ? buy_vol96 : group == 97 ? buy_vol97 : group == 98 ? buy_vol98 : group == 99 ? buy_vol99 : group == 100 ? buy_vol100 : 0.0
// 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: 101. The limit is 100 error => 2 function calls with 50 vars each: 50 + 50 + 1
// buy_volumes(group) =>
// res = group <= 50 ? buy_volumes1(group) : buy_volumes2(group)
// group <= 50 ? buy_volumes1(group) : buy_volumes2(group)
// sell volumes array (read only)
// returns 0 instead of na - important!
sell_volumes1(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
sell_volumes2(group) =>
res = group == 51 ? sell_vol51 : group == 52 ? sell_vol52 : group == 53 ? sell_vol53 : group == 54 ? sell_vol54 : group == 55 ? sell_vol55 : group == 56 ? sell_vol56 : group == 57 ? sell_vol57 : group == 58 ? sell_vol58 : group == 59 ? sell_vol59 : group == 60 ? sell_vol60 :
group == 61 ? sell_vol61 : group == 62 ? sell_vol62 : group == 63 ? sell_vol63 : group == 64 ? sell_vol64 : group == 65 ? sell_vol65 : group == 66 ? sell_vol66 : group == 67 ? sell_vol67 : group == 68 ? sell_vol68 : group == 69 ? sell_vol69 : group == 70 ? sell_vol70 :
group == 71 ? sell_vol71 : group == 72 ? sell_vol72 : group == 73 ? sell_vol73 : group == 74 ? sell_vol74 : group == 75 ? sell_vol75 : group == 76 ? sell_vol76 : group == 77 ? sell_vol77 : group == 78 ? sell_vol78 : group == 79 ? sell_vol79 : group == 80 ? sell_vol80 :
group == 81 ? sell_vol81 : group == 82 ? sell_vol82 : group == 83 ? sell_vol83 : group == 84 ? sell_vol84 : group == 85 ? sell_vol85 : group == 86 ? sell_vol86 : group == 87 ? sell_vol87 : group == 88 ? sell_vol88 : group == 89 ? sell_vol89 : group == 90 ? sell_vol90 :
group == 91 ? sell_vol91 : group == 92 ? sell_vol92 : group == 93 ? sell_vol93 : group == 94 ? sell_vol94 : group == 95 ? sell_vol95 : group == 96 ? sell_vol96 : group == 97 ? sell_vol97 : group == 98 ? sell_vol98 : group == 99 ? sell_vol99 : group == 100 ? sell_vol100 : 0.0
// 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
// compensate level price with vertical shift because line width is center-based, not bottom-based
// either level_shift or 100.0 must be float otherwise width1 = 0 and level1 will have a tiny default width
shift = level_shift/100 * h
// 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
// here we calculate the denominator/divisor max_vol of the vol/max_vol ratio (fraction bottom)
// - for total - we always calculate max_total volume/poc
// - for buy/sell in normal mode => respective 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)
// to access 100 vol vars we must call 2 separate array functions with 50 vars each
bv = i <= 50 ? buy_volumes1(i) : buy_volumes2(i)
if max_buy_vol < bv
max_buy_vol := bv
// sv = sell_volumes(i)
sv = i <= 50 ? sell_volumes1(i) : sell_volumes2(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 + shift // h/2
poc2_level := poc2_index > 0 ? pl + (poc2_index - 1) * h + shift : 0.0 // h/2
// 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!
// doesn't work with 100 vars
// 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)
// single total_volumes/buy_volume with 100 vars => script has a function with too many arguments: 101 => you must split it into 2 functions and call them separately
buy_vol_vh1 = va_high + 1 <= 50 ? buy_volumes1(va_high + 1) : buy_volumes2(va_high + 1)
buy_vol_vh2 = va_high + 2 <= 50 ? buy_volumes1(va_high + 2) : buy_volumes2(va_high + 2)
sell_vol_vh1 = va_high + 1 <= 50 ? sell_volumes1(va_high + 1) : sell_volumes2(va_high + 1)
sell_vol_vh2 = va_high + 2 <= 50 ? sell_volumes1(va_high + 2) : sell_volumes2(va_high + 2)
buy_vol_vl1 = va_low - 1 <= 50 ? buy_volumes1(va_low - 1) : buy_volumes2(va_low - 1)
buy_vol_vl2 = va_low - 2 <= 50 ? buy_volumes1(va_low - 2) : buy_volumes2(va_low - 2)
sell_vol_vl1 = va_low - 1 <= 50 ? sell_volumes1(va_low - 1) : sell_volumes2(va_low - 1)
sell_vol_vl2 = va_low - 2 <= 50 ? sell_volumes1(va_low - 2) : sell_volumes2(va_low - 2)
above_vol = buy_vol_vh1 + sell_vol_vh1 + buy_vol_vh2 + sell_vol_vh2
below_vol = buy_vol_vl1 + sell_vol_vl1 + buy_vol_vl2 + sell_vol_vl2
// 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, doesn't need shift
va_high_level := pl + va_high * h - spacing // + shift // h/2
// lower boundary of a level
va_low_level := pl + (va_low - 1) * h - spacing // + shift // h/2
// VWAP
// is not affected by shift
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
len51 = 0
len52 = 0
len53 = 0
len54 = 0
len55 = 0
len56 = 0
len57 = 0
len58 = 0
len59 = 0
len60 = 0
len61 = 0
len62 = 0
len63 = 0
len64 = 0
len65 = 0
len66 = 0
len67 = 0
len68 = 0
len69 = 0
len70 = 0
len71 = 0
len72 = 0
len73 = 0
len74 = 0
len75 = 0
len76 = 0
len77 = 0
len78 = 0
len79 = 0
len80 = 0
len81 = 0
len82 = 0
len83 = 0
len84 = 0
len85 = 0
len86 = 0
len87 = 0
len88 = 0
len89 = 0
len90 = 0
len91 = 0
len92 = 0
len93 = 0
len94 = 0
len95 = 0
len96 = 0
len97 = 0
len98 = 0
len99 = 0
len100 = 0
// calculate base level length
// - for total - we need to use total buy+sell volume
// - for buy/sell in normal mode => respective buy/sell volumes
// - for buy/sell in buy_sell_sli_mode with extended buy + sell offset for sell => total buy+sell volume for sell, buy volume for buy master/slave indicator
// - basically for buy level we use buy len, for sell level - buy + sell len, but the buy part is below/covered by the corresponding buy level because each sell is an extension of a buy level, so it's technically a sell len with a buy len offset
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
// 100 static vol vars removed and replaced with a function to minimize the total number of vars <= max 1000 vars limit
get_vol(buy_vol, sell_vol) =>
res = a * buy_vol + b * sell_vol
// check for non empty volume range, prevent division by zero
if max_vol > 0
len1 := round(get_vol(buy_vol1, sell_vol1)/max_vol * length)
len2 := round(get_vol(buy_vol2, sell_vol2)/max_vol * length)
len3 := round(get_vol(buy_vol3, sell_vol3)/max_vol * length)
len4 := round(get_vol(buy_vol4, sell_vol4)/max_vol * length)
len5 := round(get_vol(buy_vol5, sell_vol5)/max_vol * length)
len6 := round(get_vol(buy_vol6, sell_vol6)/max_vol * length)
len7 := round(get_vol(buy_vol7, sell_vol7)/max_vol * length)
len8 := round(get_vol(buy_vol8, sell_vol8)/max_vol * length)
len9 := round(get_vol(buy_vol9, sell_vol9)/max_vol * length)
len10 := round(get_vol(buy_vol10, sell_vol10)/max_vol * length)
len11 := round(get_vol(buy_vol11, sell_vol11)/max_vol * length)
len12 := round(get_vol(buy_vol12, sell_vol12)/max_vol * length)
len13 := round(get_vol(buy_vol13, sell_vol13)/max_vol * length)
len14 := round(get_vol(buy_vol14, sell_vol14)/max_vol * length)
len15 := round(get_vol(buy_vol15, sell_vol15)/max_vol * length)
len16 := round(get_vol(buy_vol16, sell_vol16)/max_vol * length)
len17 := round(get_vol(buy_vol17, sell_vol17)/max_vol * length)
len18 := round(get_vol(buy_vol18, sell_vol18)/max_vol * length)
len19 := round(get_vol(buy_vol19, sell_vol19)/max_vol * length)
len20 := round(get_vol(buy_vol20, sell_vol20)/max_vol * length)
len21 := round(get_vol(buy_vol21, sell_vol21)/max_vol * length)
len22 := round(get_vol(buy_vol22, sell_vol22)/max_vol * length)
len23 := round(get_vol(buy_vol23, sell_vol23)/max_vol * length)
len24 := round(get_vol(buy_vol24, sell_vol24)/max_vol * length)
len25 := round(get_vol(buy_vol25, sell_vol25)/max_vol * length)
len26 := round(get_vol(buy_vol26, sell_vol26)/max_vol * length)
len27 := round(get_vol(buy_vol27, sell_vol27)/max_vol * length)
len28 := round(get_vol(buy_vol28, sell_vol28)/max_vol * length)
len29 := round(get_vol(buy_vol29, sell_vol29)/max_vol * length)
len30 := round(get_vol(buy_vol30, sell_vol30)/max_vol * length)
len31 := round(get_vol(buy_vol31, sell_vol31)/max_vol * length)
len32 := round(get_vol(buy_vol32, sell_vol32)/max_vol * length)
len33 := round(get_vol(buy_vol33, sell_vol33)/max_vol * length)
len34 := round(get_vol(buy_vol34, sell_vol34)/max_vol * length)
len35 := round(get_vol(buy_vol35, sell_vol35)/max_vol * length)
len36 := round(get_vol(buy_vol36, sell_vol36)/max_vol * length)
len37 := round(get_vol(buy_vol37, sell_vol37)/max_vol * length)
len38 := round(get_vol(buy_vol38, sell_vol38)/max_vol * length)
len39 := round(get_vol(buy_vol39, sell_vol39)/max_vol * length)
len40 := round(get_vol(buy_vol40, sell_vol40)/max_vol * length)
len41 := round(get_vol(buy_vol41, sell_vol41)/max_vol * length)
len42 := round(get_vol(buy_vol42, sell_vol42)/max_vol * length)
len43 := round(get_vol(buy_vol43, sell_vol43)/max_vol * length)
len44 := round(get_vol(buy_vol44, sell_vol44)/max_vol * length)
len45 := round(get_vol(buy_vol45, sell_vol45)/max_vol * length)
len46 := round(get_vol(buy_vol46, sell_vol46)/max_vol * length)
len47 := round(get_vol(buy_vol47, sell_vol47)/max_vol * length)
len48 := round(get_vol(buy_vol48, sell_vol48)/max_vol * length)
len49 := round(get_vol(buy_vol49, sell_vol49)/max_vol * length)
len50 := round(get_vol(buy_vol50, sell_vol50)/max_vol * length)
len51 := round(get_vol(buy_vol51, sell_vol51)/max_vol * length)
len52 := round(get_vol(buy_vol52, sell_vol52)/max_vol * length)
len53 := round(get_vol(buy_vol53, sell_vol53)/max_vol * length)
len54 := round(get_vol(buy_vol54, sell_vol54)/max_vol * length)
len55 := round(get_vol(buy_vol55, sell_vol55)/max_vol * length)
len56 := round(get_vol(buy_vol56, sell_vol56)/max_vol * length)
len57 := round(get_vol(buy_vol57, sell_vol57)/max_vol * length)
len58 := round(get_vol(buy_vol58, sell_vol58)/max_vol * length)
len59 := round(get_vol(buy_vol59, sell_vol59)/max_vol * length)
len60 := round(get_vol(buy_vol60, sell_vol60)/max_vol * length)
len61 := round(get_vol(buy_vol61, sell_vol61)/max_vol * length)
len62 := round(get_vol(buy_vol62, sell_vol62)/max_vol * length)
len63 := round(get_vol(buy_vol63, sell_vol63)/max_vol * length)
len64 := round(get_vol(buy_vol64, sell_vol64)/max_vol * length)
len65 := round(get_vol(buy_vol65, sell_vol65)/max_vol * length)
len66 := round(get_vol(buy_vol66, sell_vol66)/max_vol * length)
len67 := round(get_vol(buy_vol67, sell_vol67)/max_vol * length)
len68 := round(get_vol(buy_vol68, sell_vol68)/max_vol * length)
len69 := round(get_vol(buy_vol69, sell_vol69)/max_vol * length)
len70 := round(get_vol(buy_vol70, sell_vol70)/max_vol * length)
len71 := round(get_vol(buy_vol71, sell_vol71)/max_vol * length)
len72 := round(get_vol(buy_vol72, sell_vol72)/max_vol * length)
len73 := round(get_vol(buy_vol73, sell_vol73)/max_vol * length)
len74 := round(get_vol(buy_vol74, sell_vol74)/max_vol * length)
len75 := round(get_vol(buy_vol75, sell_vol75)/max_vol * length)
len76 := round(get_vol(buy_vol76, sell_vol76)/max_vol * length)
len77 := round(get_vol(buy_vol77, sell_vol77)/max_vol * length)
len78 := round(get_vol(buy_vol78, sell_vol78)/max_vol * length)
len79 := round(get_vol(buy_vol79, sell_vol79)/max_vol * length)
len80 := round(get_vol(buy_vol80, sell_vol80)/max_vol * length)
len81 := round(get_vol(buy_vol81, sell_vol81)/max_vol * length)
len82 := round(get_vol(buy_vol82, sell_vol82)/max_vol * length)
len83 := round(get_vol(buy_vol83, sell_vol83)/max_vol * length)
len84 := round(get_vol(buy_vol84, sell_vol84)/max_vol * length)
len85 := round(get_vol(buy_vol85, sell_vol85)/max_vol * length)
len86 := round(get_vol(buy_vol86, sell_vol86)/max_vol * length)
len87 := round(get_vol(buy_vol87, sell_vol87)/max_vol * length)
len88 := round(get_vol(buy_vol88, sell_vol88)/max_vol * length)
len89 := round(get_vol(buy_vol89, sell_vol89)/max_vol * length)
len90 := round(get_vol(buy_vol90, sell_vol90)/max_vol * length)
len91 := round(get_vol(buy_vol91, sell_vol91)/max_vol * length)
len92 := round(get_vol(buy_vol92, sell_vol92)/max_vol * length)
len93 := round(get_vol(buy_vol93, sell_vol93)/max_vol * length)
len94 := round(get_vol(buy_vol94, sell_vol94)/max_vol * length)
len95 := round(get_vol(buy_vol95, sell_vol95)/max_vol * length)
len96 := round(get_vol(buy_vol96, sell_vol96)/max_vol * length)
len97 := round(get_vol(buy_vol97, sell_vol97)/max_vol * length)
len98 := round(get_vol(buy_vol98, sell_vol98)/max_vol * length)
len99 := round(get_vol(buy_vol99, sell_vol99)/max_vol * length)
len100 := round(get_vol(buy_vol100, sell_vol100)/max_vol * length)
// Buy/Sell Levels
// levels are relative to pl with step h, shift compensates for width outline plotted from the center of each line instead of its bottom
// level can't be mutable/function because plot linewidth depends on it
level1 = pl + 0 * h + shift
level2 = pl + 1 * h + shift
level3 = pl + 2 * h + shift
level4 = pl + 3 * h + shift
level5 = pl + 4 * h + shift
level6 = pl + 5 * h + shift
level7 = pl + 6 * h + shift
level8 = pl + 7 * h + shift
level9 = pl + 8 * h + shift
level10 = pl + 9 * h + shift
level11 = pl + 10 * h + shift
level12 = pl + 11 * h + shift
level13 = pl + 12 * h + shift
level14 = pl + 13 * h + shift
level15 = pl + 14 * h + shift
level16 = pl + 15 * h + shift
level17 = pl + 16 * h + shift
level18 = pl + 17 * h + shift
level19 = pl + 18 * h + shift
level20 = pl + 19 * h + shift
level21 = pl + 20 * h + shift
level22 = pl + 21 * h + shift
level23 = pl + 22 * h + shift
level24 = pl + 23 * h + shift
level25 = pl + 24 * h + shift
level26 = pl + 25 * h + shift
level27 = pl + 26 * h + shift
level28 = pl + 27 * h + shift
level29 = pl + 28 * h + shift
level30 = pl + 29 * h + shift
level31 = pl + 30 * h + shift
level32 = pl + 31 * h + shift
level33 = pl + 32 * h + shift
level34 = pl + 33 * h + shift
level35 = pl + 34 * h + shift
level36 = pl + 35 * h + shift
level37 = pl + 36 * h + shift
level38 = pl + 37 * h + shift
level39 = pl + 38 * h + shift
level40 = pl + 39 * h + shift
level41 = pl + 40 * h + shift
level42 = pl + 41 * h + shift
level43 = pl + 42 * h + shift
level44 = pl + 43 * h + shift
level45 = pl + 44 * h + shift
level46 = pl + 45 * h + shift
level47 = pl + 46 * h + shift
level48 = pl + 47 * h + shift
level49 = pl + 48 * h + shift
level50 = pl + 49 * h + shift
level51 = pl + 50 * h + shift
level52 = pl + 51 * h + shift
level53 = pl + 52 * h + shift
level54 = pl + 53 * h + shift
level55 = pl + 54 * h + shift
level56 = pl + 55 * h + shift
level57 = pl + 56 * h + shift
level58 = pl + 57 * h + shift
level59 = pl + 58 * h + shift
level60 = pl + 59 * h + shift
level61 = pl + 60 * h + shift
level62 = pl + 61 * h + shift
level63 = pl + 62 * h + shift
level64 = pl + 63 * h + shift
level65 = pl + 64 * h + shift
level66 = pl + 65 * h + shift
level67 = pl + 66 * h + shift
level68 = pl + 67 * h + shift
level69 = pl + 68 * h + shift
level70 = pl + 69 * h + shift
level71 = pl + 70 * h + shift
level72 = pl + 71 * h + shift
level73 = pl + 72 * h + shift
level74 = pl + 73 * h + shift
level75 = pl + 74 * h + shift
level76 = pl + 75 * h + shift
level77 = pl + 76 * h + shift
level78 = pl + 77 * h + shift
level79 = pl + 78 * h + shift
level80 = pl + 79 * h + shift
level81 = pl + 80 * h + shift
level82 = pl + 81 * h + shift
level83 = pl + 82 * h + shift
level84 = pl + 83 * h + shift
level85 = pl + 84 * h + shift
level86 = pl + 85 * h + shift
level87 = pl + 86 * h + shift
level88 = pl + 87 * h + shift
level89 = pl + 88 * h + shift
level90 = pl + 89 * h + shift
level91 = pl + 90 * h + shift
level92 = pl + 91 * h + shift
level93 = pl + 92 * h + shift
level94 = pl + 93 * h + shift
level95 = pl + 94 * h + shift
level96 = pl + 95 * h + shift
level97 = pl + 96 * h + shift
level98 = pl + 97 * h + shift
level99 = pl + 98 * h + shift
level100 = pl + 99 * h + shift
level101 = pl + 100 * h + shift // required for line width calculation
// we don't need level tops in this version
// Level Offsets
dir = flip_levels ? 1 : -1
// both range and start_bar can be > n producing negative index vaes
// must be >= 0 for other offsets to work
// if range = 0 (All History) first_bar_offset is always the offset to the first bar n=0 on the chart regardless of start_bar it is applied to cur_bar not start_bar
first_bar_offset = range == 0 ? total_bars : range_start_bars // min(total_bars, start_bar + range - 1)
last_bar_offset = range_start_bars >= range_bars ? range_start_bars - range_bars + 1 : 0 // na(range_end_bars) ? first_bar_offset : range_end_bars
range_offset = anchor == "cur bar" ? 0 : anchor == "range start" ? last_bar_offset : first_bar_offset
// 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 - 1 : z_offset + length // - 1
// 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
// extend cover to the right to compensate for cover offset adjustment
cover_length = length + ext_length
c_offset = dir == 1 ? z_offset : z_offset + cover_length - 1
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
// offset can be a function
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
offset51 = l_offset + dir * len51
offset52 = l_offset + dir * len52
offset53 = l_offset + dir * len53
offset54 = l_offset + dir * len54
offset55 = l_offset + dir * len55
offset56 = l_offset + dir * len56
offset57 = l_offset + dir * len57
offset58 = l_offset + dir * len58
offset59 = l_offset + dir * len59
offset60 = l_offset + dir * len60
offset61 = l_offset + dir * len61
offset62 = l_offset + dir * len62
offset63 = l_offset + dir * len63
offset64 = l_offset + dir * len64
offset65 = l_offset + dir * len65
offset66 = l_offset + dir * len66
offset67 = l_offset + dir * len67
offset68 = l_offset + dir * len68
offset69 = l_offset + dir * len69
offset70 = l_offset + dir * len70
offset71 = l_offset + dir * len71
offset72 = l_offset + dir * len72
offset73 = l_offset + dir * len73
offset74 = l_offset + dir * len74
offset75 = l_offset + dir * len75
offset76 = l_offset + dir * len76
offset77 = l_offset + dir * len77
offset78 = l_offset + dir * len78
offset79 = l_offset + dir * len79
offset80 = l_offset + dir * len80
offset81 = l_offset + dir * len81
offset82 = l_offset + dir * len82
offset83 = l_offset + dir * len83
offset84 = l_offset + dir * len84
offset85 = l_offset + dir * len85
offset86 = l_offset + dir * len86
offset87 = l_offset + dir * len87
offset88 = l_offset + dir * len88
offset89 = l_offset + dir * len89
offset90 = l_offset + dir * len90
offset91 = l_offset + dir * len91
offset92 = l_offset + dir * len92
offset93 = l_offset + dir * len93
offset94 = l_offset + dir * len94
offset95 = l_offset + dir * len95
offset96 = l_offset + dir * len96
offset97 = l_offset + dir * len97
offset98 = l_offset + dir * len98
offset99 = l_offset + dir * len99
offset100 = l_offset + dir * len100
// Level Widths
// doesn't work - plot linewidth can't be mutable/function, can't be float, can only be a math/const expression => produces default tiny line, changes don't affect output
// adj_width(level1, level2) =>
// k = 1 - log(level1)/log(level2)
// w = line_width * width_multiplier
// res = adjust_width ? floor(k * w) : floor(w)
// use line_width for normal scale and line_width * width_multiplier for log scale
w = adjust_width ? line_width * width_multiplier : line_width
// Adjust Line Width for Log Scale mode:
// - produces smaller width for higher price values based on 1 - log ratio of adjacent levels
// - when h <= 1 or level = 0 (shift = 0) or level = 1 widths may not work due to log() limits
// - double abs is required for high precision small price charts with h < 0.01 => log(0.01), when width is negative
// - log(0) => NaN, log(1) = 0, division by zero => when h = 0.1, 0.2 and 0.5 widths of certain levels will be zero
// - when Adjust Line Width for Log Scale is false there are no width issues
// this ensures that width1 will be shown and within max_deviation from width2 (this doesn't fix other levels):
// - when level1 = 0 width1 is NaN (not shown)
// - when level1 = 1 width1 is extremely large value w
line_width1_ = adjust_width ? abs(floor((1 - abs(log10(level1)/log10(level2))) * w)) : floor(w)
line_width2 = adjust_width ? abs(floor((1 - abs(log10(level2)/log10(level3))) * w)) : floor(w)
line_width2_ = floor(line_width2 * max_deviation)
// na, nz, fixnan, float don't work as log(0) na check - can't cast to const
// line_width1 = line_width1_ ? line_width1_ : line_width2_
// line_width1 = not na(line_width1_) ? line_width1_ : line_width2_
// line_width1 = line_width1_ == log(0) ? line_width1_ : line_width2_
// works as log(0) na check for const expressions - nothing else works!
line_width1 = line_width1_ > 0 ? line_width1_ : line_width2_
// line_width1 = adjust_width ? abs(floor((1 - abs(log10(level1)/log10(level2))) * w)) : floor(w)
// line_width2 = adjust_width ? abs(floor((1 - abs(log10(level2)/log10(level3))) * w)) : floor(w)
line_width3 = adjust_width ? abs(floor((1 - abs(log10(level3)/log10(level4))) * w)) : floor(w)
line_width4 = adjust_width ? abs(floor((1 - abs(log10(level4)/log10(level5))) * w)) : floor(w)
line_width5 = adjust_width ? abs(floor((1 - abs(log10(level5)/log10(level6))) * w)) : floor(w)
line_width6 = adjust_width ? abs(floor((1 - abs(log10(level6)/log10(level7))) * w)) : floor(w)
line_width7 = adjust_width ? abs(floor((1 - abs(log10(level7)/log10(level8))) * w)) : floor(w)
line_width8 = adjust_width ? abs(floor((1 - abs(log10(level8)/log10(level9))) * w)) : floor(w)
line_width9 = adjust_width ? abs(floor((1 - abs(log10(level9)/log10(level10))) * w)) : floor(w)
line_width10 = adjust_width ? abs(floor((1 - abs(log10(level10)/log10(level11))) * w)) : floor(w)
line_width11 = adjust_width ? abs(floor((1 - abs(log10(level11)/log10(level12))) * w)) : floor(w)
line_width12 = adjust_width ? abs(floor((1 - abs(log10(level12)/log10(level13))) * w)) : floor(w)
line_width13 = adjust_width ? abs(floor((1 - abs(log10(level13)/log10(level14))) * w)) : floor(w)
line_width14 = adjust_width ? abs(floor((1 - abs(log10(level14)/log10(level15))) * w)) : floor(w)
line_width15 = adjust_width ? abs(floor((1 - abs(log10(level15)/log10(level16))) * w)) : floor(w)
line_width16 = adjust_width ? abs(floor((1 - abs(log10(level16)/log10(level17))) * w)) : floor(w)
line_width17 = adjust_width ? abs(floor((1 - abs(log10(level17)/log10(level18))) * w)) : floor(w)
line_width18 = adjust_width ? abs(floor((1 - abs(log10(level18)/log10(level19))) * w)) : floor(w)
line_width19 = adjust_width ? abs(floor((1 - abs(log10(level19)/log10(level20))) * w)) : floor(w)
line_width20 = adjust_width ? abs(floor((1 - abs(log10(level20)/log10(level21))) * w)) : floor(w)
line_width21 = adjust_width ? abs(floor((1 - abs(log10(level21)/log10(level22))) * w)) : floor(w)
line_width22 = adjust_width ? abs(floor((1 - abs(log10(level22)/log10(level23))) * w)) : floor(w)
line_width23 = adjust_width ? abs(floor((1 - abs(log10(level23)/log10(level24))) * w)) : floor(w)
line_width24 = adjust_width ? abs(floor((1 - abs(log10(level24)/log10(level25))) * w)) : floor(w)
line_width25 = adjust_width ? abs(floor((1 - abs(log10(level25)/log10(level26))) * w)) : floor(w)
line_width26 = adjust_width ? abs(floor((1 - abs(log10(level26)/log10(level27))) * w)) : floor(w)
line_width27 = adjust_width ? abs(floor((1 - abs(log10(level27)/log10(level28))) * w)) : floor(w)
line_width28 = adjust_width ? abs(floor((1 - abs(log10(level28)/log10(level29))) * w)) : floor(w)
line_width29 = adjust_width ? abs(floor((1 - abs(log10(level29)/log10(level30))) * w)) : floor(w)
line_width30 = adjust_width ? abs(floor((1 - abs(log10(level30)/log10(level31))) * w)) : floor(w)
line_width31 = adjust_width ? abs(floor((1 - abs(log10(level31)/log10(level32))) * w)) : floor(w)
line_width32 = adjust_width ? abs(floor((1 - abs(log10(level32)/log10(level33))) * w)) : floor(w)
line_width33 = adjust_width ? abs(floor((1 - abs(log10(level33)/log10(level34))) * w)) : floor(w)
line_width34 = adjust_width ? abs(floor((1 - abs(log10(level34)/log10(level35))) * w)) : floor(w)
line_width35 = adjust_width ? abs(floor((1 - abs(log10(level35)/log10(level36))) * w)) : floor(w)
line_width36 = adjust_width ? abs(floor((1 - abs(log10(level36)/log10(level37))) * w)) : floor(w)
line_width37 = adjust_width ? abs(floor((1 - abs(log10(level37)/log10(level38))) * w)) : floor(w)
line_width38 = adjust_width ? abs(floor((1 - abs(log10(level38)/log10(level39))) * w)) : floor(w)
line_width39 = adjust_width ? abs(floor((1 - abs(log10(level39)/log10(level40))) * w)) : floor(w)
line_width40 = adjust_width ? abs(floor((1 - abs(log10(level40)/log10(level41))) * w)) : floor(w)
line_width41 = adjust_width ? abs(floor((1 - abs(log10(level41)/log10(level42))) * w)) : floor(w)
line_width42 = adjust_width ? abs(floor((1 - abs(log10(level42)/log10(level43))) * w)) : floor(w)
line_width43 = adjust_width ? abs(floor((1 - abs(log10(level43)/log10(level44))) * w)) : floor(w)
line_width44 = adjust_width ? abs(floor((1 - abs(log10(level44)/log10(level45))) * w)) : floor(w)
line_width45 = adjust_width ? abs(floor((1 - abs(log10(level45)/log10(level46))) * w)) : floor(w)
line_width46 = adjust_width ? abs(floor((1 - abs(log10(level46)/log10(level47))) * w)) : floor(w)
line_width47 = adjust_width ? abs(floor((1 - abs(log10(level47)/log10(level48))) * w)) : floor(w)
line_width48 = adjust_width ? abs(floor((1 - abs(log10(level48)/log10(level49))) * w)) : floor(w)
line_width49 = adjust_width ? abs(floor((1 - abs(log10(level49)/log10(level50))) * w)) : floor(w)
line_width50 = adjust_width ? abs(floor((1 - abs(log10(level50)/log10(level51))) * w)) : floor(w)
line_width51 = adjust_width ? abs(floor((1 - abs(log10(level51)/log10(level52))) * w)) : floor(w)
line_width52 = adjust_width ? abs(floor((1 - abs(log10(level52)/log10(level53))) * w)) : floor(w)
line_width53 = adjust_width ? abs(floor((1 - abs(log10(level53)/log10(level54))) * w)) : floor(w)
line_width54 = adjust_width ? abs(floor((1 - abs(log10(level54)/log10(level55))) * w)) : floor(w)
line_width55 = adjust_width ? abs(floor((1 - abs(log10(level55)/log10(level56))) * w)) : floor(w)
line_width56 = adjust_width ? abs(floor((1 - abs(log10(level56)/log10(level57))) * w)) : floor(w)
line_width57 = adjust_width ? abs(floor((1 - abs(log10(level57)/log10(level58))) * w)) : floor(w)
line_width58 = adjust_width ? abs(floor((1 - abs(log10(level58)/log10(level59))) * w)) : floor(w)
line_width59 = adjust_width ? abs(floor((1 - abs(log10(level59)/log10(level60))) * w)) : floor(w)
line_width60 = adjust_width ? abs(floor((1 - abs(log10(level60)/log10(level61))) * w)) : floor(w)
line_width61 = adjust_width ? abs(floor((1 - abs(log10(level61)/log10(level62))) * w)) : floor(w)
line_width62 = adjust_width ? abs(floor((1 - abs(log10(level62)/log10(level63))) * w)) : floor(w)
line_width63 = adjust_width ? abs(floor((1 - abs(log10(level63)/log10(level64))) * w)) : floor(w)
line_width64 = adjust_width ? abs(floor((1 - abs(log10(level64)/log10(level65))) * w)) : floor(w)
line_width65 = adjust_width ? abs(floor((1 - abs(log10(level65)/log10(level66))) * w)) : floor(w)
line_width66 = adjust_width ? abs(floor((1 - abs(log10(level66)/log10(level67))) * w)) : floor(w)
line_width67 = adjust_width ? abs(floor((1 - abs(log10(level67)/log10(level68))) * w)) : floor(w)
line_width68 = adjust_width ? abs(floor((1 - abs(log10(level68)/log10(level69))) * w)) : floor(w)
line_width69 = adjust_width ? abs(floor((1 - abs(log10(level69)/log10(level70))) * w)) : floor(w)
line_width70 = adjust_width ? abs(floor((1 - abs(log10(level70)/log10(level71))) * w)) : floor(w)
line_width71 = adjust_width ? abs(floor((1 - abs(log10(level71)/log10(level72))) * w)) : floor(w)
line_width72 = adjust_width ? abs(floor((1 - abs(log10(level72)/log10(level73))) * w)) : floor(w)
line_width73 = adjust_width ? abs(floor((1 - abs(log10(level73)/log10(level74))) * w)) : floor(w)
line_width74 = adjust_width ? abs(floor((1 - abs(log10(level74)/log10(level75))) * w)) : floor(w)
line_width75 = adjust_width ? abs(floor((1 - abs(log10(level75)/log10(level76))) * w)) : floor(w)
line_width76 = adjust_width ? abs(floor((1 - abs(log10(level76)/log10(level77))) * w)) : floor(w)
line_width77 = adjust_width ? abs(floor((1 - abs(log10(level77)/log10(level78))) * w)) : floor(w)
line_width78 = adjust_width ? abs(floor((1 - abs(log10(level78)/log10(level79))) * w)) : floor(w)
line_width79 = adjust_width ? abs(floor((1 - abs(log10(level79)/log10(level80))) * w)) : floor(w)
line_width80 = adjust_width ? abs(floor((1 - abs(log10(level80)/log10(level81))) * w)) : floor(w)
line_width81 = adjust_width ? abs(floor((1 - abs(log10(level81)/log10(level82))) * w)) : floor(w)
line_width82 = adjust_width ? abs(floor((1 - abs(log10(level82)/log10(level83))) * w)) : floor(w)
line_width83 = adjust_width ? abs(floor((1 - abs(log10(level83)/log10(level84))) * w)) : floor(w)
line_width84 = adjust_width ? abs(floor((1 - abs(log10(level84)/log10(level85))) * w)) : floor(w)
line_width85 = adjust_width ? abs(floor((1 - abs(log10(level85)/log10(level86))) * w)) : floor(w)
line_width86 = adjust_width ? abs(floor((1 - abs(log10(level86)/log10(level87))) * w)) : floor(w)
line_width87 = adjust_width ? abs(floor((1 - abs(log10(level87)/log10(level88))) * w)) : floor(w)
line_width88 = adjust_width ? abs(floor((1 - abs(log10(level88)/log10(level89))) * w)) : floor(w)
line_width89 = adjust_width ? abs(floor((1 - abs(log10(level89)/log10(level90))) * w)) : floor(w)
line_width90 = adjust_width ? abs(floor((1 - abs(log10(level90)/log10(level91))) * w)) : floor(w)
line_width91 = adjust_width ? abs(floor((1 - abs(log10(level91)/log10(level92))) * w)) : floor(w)
line_width92 = adjust_width ? abs(floor((1 - abs(log10(level92)/log10(level93))) * w)) : floor(w)
line_width93 = adjust_width ? abs(floor((1 - abs(log10(level93)/log10(level94))) * w)) : floor(w)
line_width94 = adjust_width ? abs(floor((1 - abs(log10(level94)/log10(level95))) * w)) : floor(w)
line_width95 = adjust_width ? abs(floor((1 - abs(log10(level95)/log10(level96))) * w)) : floor(w)
line_width96 = adjust_width ? abs(floor((1 - abs(log10(level96)/log10(level97))) * w)) : floor(w)
line_width97 = adjust_width ? abs(floor((1 - abs(log10(level97)/log10(level98))) * w)) : floor(w)
line_width98 = adjust_width ? abs(floor((1 - abs(log10(level98)/log10(level99))) * w)) : floor(w)
line_width99 = adjust_width ? abs(floor((1 - abs(log10(level99)/log10(level100))) * w)) : floor(w)
line_width100 = adjust_width ? abs(floor((1 - abs(log10(level100)/log10(level101))) * w)) : floor(w)
// 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
// Script has too many local variables (1064) in "#f51": #loc_0, #loc_1, #loc_2, #loc_3, #loc_4... The limit is 1000 => reduced number of vars
// var count: 800 => 500
// - 100 buy_vol (required)
// - 100 sell_vol (required)
// - 50 levels (required) (-50)
// - 0 offsets (-100)
// - 0 vol (-100)
// - 100 len (required)
// - 50 width (required) (-50)
// - 50 lines (required)
// - 50 framework
//
// - 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
// - histbase can't be var/function/mutable (doesn't affect the output), can only be const expression, can be set from input
//
// 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$ : na, title="Volume $", style=level_style, linewidth=line_width$, color=level_color, transp=level_transp, offset=offset$, show_last=length)
// }*50
// you can only have 50 plot levels
plot(show_levels and (num_levels >= 1) ? level1 : na, title="Volume 1", style=level_style, linewidth=line_width1, color=level_color, transp=level_transp, offset=offset1, show_last=length)
plot(show_levels and (num_levels >= 2) ? level2 : na, title="Volume 2", style=level_style, linewidth=line_width2, color=level_color, transp=level_transp, offset=offset2, show_last=length)
plot(show_levels and (num_levels >= 3) ? level3 : na, title="Volume 3", style=level_style, linewidth=line_width3, color=level_color, transp=level_transp, offset=offset3, show_last=length)
plot(show_levels and (num_levels >= 4) ? level4 : na, title="Volume 4", style=level_style, linewidth=line_width4, color=level_color, transp=level_transp, offset=offset4, show_last=length)
plot(show_levels and (num_levels >= 5) ? level5 : na, title="Volume 5", style=level_style, linewidth=line_width5, color=level_color, transp=level_transp, offset=offset5, show_last=length)
plot(show_levels and (num_levels >= 6) ? level6 : na, title="Volume 6", style=level_style, linewidth=line_width6, color=level_color, transp=level_transp, offset=offset6, show_last=length)
plot(show_levels and (num_levels >= 7) ? level7 : na, title="Volume 7", style=level_style, linewidth=line_width7, color=level_color, transp=level_transp, offset=offset7, show_last=length)
plot(show_levels and (num_levels >= 8) ? level8 : na, title="Volume 8", style=level_style, linewidth=line_width8, color=level_color, transp=level_transp, offset=offset8, show_last=length)
plot(show_levels and (num_levels >= 9) ? level9 : na, title="Volume 9", style=level_style, linewidth=line_width9, color=level_color, transp=level_transp, offset=offset9, show_last=length)
plot(show_levels and (num_levels >= 10) ? level10 : na, title="Volume 10", style=level_style, linewidth=line_width10, color=level_color, transp=level_transp, offset=offset10, show_last=length)
plot(show_levels and (num_levels >= 11) ? level11 : na, title="Volume 11", style=level_style, linewidth=line_width11, color=level_color, transp=level_transp, offset=offset11, show_last=length)
plot(show_levels and (num_levels >= 12) ? level12 : na, title="Volume 12", style=level_style, linewidth=line_width12, color=level_color, transp=level_transp, offset=offset12, show_last=length)
plot(show_levels and (num_levels >= 13) ? level13 : na, title="Volume 13", style=level_style, linewidth=line_width13, color=level_color, transp=level_transp, offset=offset13, show_last=length)
plot(show_levels and (num_levels >= 14) ? level14 : na, title="Volume 14", style=level_style, linewidth=line_width14, color=level_color, transp=level_transp, offset=offset14, show_last=length)
plot(show_levels and (num_levels >= 15) ? level15 : na, title="Volume 15", style=level_style, linewidth=line_width15, color=level_color, transp=level_transp, offset=offset15, show_last=length)
plot(show_levels and (num_levels >= 16) ? level16 : na, title="Volume 16", style=level_style, linewidth=line_width16, color=level_color, transp=level_transp, offset=offset16, show_last=length)
plot(show_levels and (num_levels >= 17) ? level17 : na, title="Volume 17", style=level_style, linewidth=line_width17, color=level_color, transp=level_transp, offset=offset17, show_last=length)
plot(show_levels and (num_levels >= 18) ? level18 : na, title="Volume 18", style=level_style, linewidth=line_width18, color=level_color, transp=level_transp, offset=offset18, show_last=length)
plot(show_levels and (num_levels >= 19) ? level19 : na, title="Volume 19", style=level_style, linewidth=line_width19, color=level_color, transp=level_transp, offset=offset19, show_last=length)
plot(show_levels and (num_levels >= 20) ? level20 : na, title="Volume 20", style=level_style, linewidth=line_width20, color=level_color, transp=level_transp, offset=offset20, show_last=length)
plot(show_levels and (num_levels >= 21) ? level21 : na, title="Volume 21", style=level_style, linewidth=line_width21, color=level_color, transp=level_transp, offset=offset21, show_last=length)
plot(show_levels and (num_levels >= 22) ? level22 : na, title="Volume 22", style=level_style, linewidth=line_width22, color=level_color, transp=level_transp, offset=offset22, show_last=length)
plot(show_levels and (num_levels >= 23) ? level23 : na, title="Volume 23", style=level_style, linewidth=line_width23, color=level_color, transp=level_transp, offset=offset23, show_last=length)
plot(show_levels and (num_levels >= 24) ? level24 : na, title="Volume 24", style=level_style, linewidth=line_width24, color=level_color, transp=level_transp, offset=offset24, show_last=length)
plot(show_levels and (num_levels >= 25) ? level25 : na, title="Volume 25", style=level_style, linewidth=line_width25, color=level_color, transp=level_transp, offset=offset25, show_last=length)
plot(show_levels and (num_levels >= 26) ? level26 : na, title="Volume 26", style=level_style, linewidth=line_width26, color=level_color, transp=level_transp, offset=offset26, show_last=length)
plot(show_levels and (num_levels >= 27) ? level27 : na, title="Volume 27", style=level_style, linewidth=line_width27, color=level_color, transp=level_transp, offset=offset27, show_last=length)
plot(show_levels and (num_levels >= 28) ? level28 : na, title="Volume 28", style=level_style, linewidth=line_width28, color=level_color, transp=level_transp, offset=offset28, show_last=length)
plot(show_levels and (num_levels >= 29) ? level29 : na, title="Volume 29", style=level_style, linewidth=line_width29, color=level_color, transp=level_transp, offset=offset29, show_last=length)
plot(show_levels and (num_levels >= 30) ? level30 : na, title="Volume 30", style=level_style, linewidth=line_width30, color=level_color, transp=level_transp, offset=offset30, show_last=length)
plot(show_levels and (num_levels >= 31) ? level31 : na, title="Volume 31", style=level_style, linewidth=line_width31, color=level_color, transp=level_transp, offset=offset31, show_last=length)
plot(show_levels and (num_levels >= 32) ? level32 : na, title="Volume 32", style=level_style, linewidth=line_width32, color=level_color, transp=level_transp, offset=offset32, show_last=length)
plot(show_levels and (num_levels >= 33) ? level33 : na, title="Volume 33", style=level_style, linewidth=line_width33, color=level_color, transp=level_transp, offset=offset33, show_last=length)
plot(show_levels and (num_levels >= 34) ? level34 : na, title="Volume 34", style=level_style, linewidth=line_width34, color=level_color, transp=level_transp, offset=offset34, show_last=length)
plot(show_levels and (num_levels >= 35) ? level35 : na, title="Volume 35", style=level_style, linewidth=line_width35, color=level_color, transp=level_transp, offset=offset35, show_last=length)
plot(show_levels and (num_levels >= 36) ? level36 : na, title="Volume 36", style=level_style, linewidth=line_width36, color=level_color, transp=level_transp, offset=offset36, show_last=length)
plot(show_levels and (num_levels >= 37) ? level37 : na, title="Volume 37", style=level_style, linewidth=line_width37, color=level_color, transp=level_transp, offset=offset37, show_last=length)
plot(show_levels and (num_levels >= 38) ? level38 : na, title="Volume 38", style=level_style, linewidth=line_width38, color=level_color, transp=level_transp, offset=offset38, show_last=length)
plot(show_levels and (num_levels >= 39) ? level39 : na, title="Volume 39", style=level_style, linewidth=line_width39, color=level_color, transp=level_transp, offset=offset39, show_last=length)
plot(show_levels and (num_levels >= 40) ? level40 : na, title="Volume 40", style=level_style, linewidth=line_width40, color=level_color, transp=level_transp, offset=offset40, show_last=length)
plot(show_levels and (num_levels >= 41) ? level41 : na, title="Volume 41", style=level_style, linewidth=line_width41, color=level_color, transp=level_transp, offset=offset41, show_last=length)
plot(show_levels and (num_levels >= 42) ? level42 : na, title="Volume 42", style=level_style, linewidth=line_width42, color=level_color, transp=level_transp, offset=offset42, show_last=length)
plot(show_levels and (num_levels >= 43) ? level43 : na, title="Volume 43", style=level_style, linewidth=line_width43, color=level_color, transp=level_transp, offset=offset43, show_last=length)
plot(show_levels and (num_levels >= 44) ? level44 : na, title="Volume 44", style=level_style, linewidth=line_width44, color=level_color, transp=level_transp, offset=offset44, show_last=length)
plot(show_levels and (num_levels >= 45) ? level45 : na, title="Volume 45", style=level_style, linewidth=line_width45, color=level_color, transp=level_transp, offset=offset45, show_last=length)
plot(show_levels and (num_levels >= 46) ? level46 : na, title="Volume 46", style=level_style, linewidth=line_width46, color=level_color, transp=level_transp, offset=offset46, show_last=length)
plot(show_levels and (num_levels >= 47) ? level47 : na, title="Volume 47", style=level_style, linewidth=line_width47, color=level_color, transp=level_transp, offset=offset47, show_last=length)
plot(show_levels and (num_levels >= 48) ? level48 : na, title="Volume 48", style=level_style, linewidth=line_width48, color=level_color, transp=level_transp, offset=offset48, show_last=length)
plot(show_levels and (num_levels >= 49) ? level49 : na, title="Volume 49", style=level_style, linewidth=line_width49, color=level_color, transp=level_transp, offset=offset49, show_last=length)
plot(show_levels and (num_levels >= 50) ? level50 : na, title="Volume 50", style=level_style, linewidth=line_width50, color=level_color, transp=level_transp, offset=offset50, show_last=length)
// Pinescript v4 Lines
// Colors
// lines_col = lines_color
// lines_col = get_color(lines_col_str, total_color)
// lines_dim_col = color.new(total_color, dim_transp)
// doesn't work
// inside a function col, transp become vars, must be const
// fc(col) =>
// res = lines_transp == 0 ? color.new(col, 0) : lines_transp == 10 ? color.new(col, 10) : lines_transp == 20 ? color.new(col, 20) : lines_transp == 30 ? color.new(col, 30) : lines_transp == 40 ? color.new(col, 40) : lines_transp == 50 ? color.new(col, 50) :
// lines_transp == 60 ? color.new(col, 60) : lines_transp == 70 ? color.new(col, 70) : lines_transp == 80 ? color.new(col, 80) : lines_transp == 90 ? color.new(col, 90) : lines_transp == 100 ? color.new(col, 100) : col
// lines_col := fc(blue)
// set custom transparency for a color
// both color and color_transp in color.new must be constants, can't be integer or function - this is the only possible way of doing this
lines_col = lines_transp == 0 ? color.new(lines_color, 0) : lines_transp == 10 ? color.new(lines_color, 10) : lines_transp == 20 ? color.new(lines_color, 20) : lines_transp == 30 ? color.new(lines_color, 30) : lines_transp == 40 ? color.new(lines_color, 40) : lines_transp == 50 ? color.new(lines_color, 50) :
lines_transp == 60 ? color.new(lines_color, 60) : lines_transp == 70 ? color.new(lines_color, 70) : lines_transp == 80 ? color.new(lines_color, 80) : lines_transp == 90 ? color.new(lines_color, 90) : lines_transp == 100 ? color.new(lines_color, 100) : lines_color
// inverse transp correlation dim_transp = 100 - nva_transp creates the necessary illusion of "covered" line objects, although they are shown on top of the cover all the time
// however, only discrete values in 0..100 range are supported. If custom lines_transp is set the inverse effect will not render properly because transp range can't be skewed easily
lines_dim_col = nva_transp == 0 ? color.new(lines_color, 100) : nva_transp == 10 ? color.new(lines_color, 90) : nva_transp == 20 ? color.new(lines_color, 80) : nva_transp == 30 ? color.new(lines_color, 70) : nva_transp == 40 ? color.new(lines_color, 60) : nva_transp == 50 ? color.new(lines_color, 50) :
nva_transp == 60 ? color.new(lines_color, 40) : nva_transp == 70 ? color.new(lines_color, 30) : nva_transp == 80 ? color.new(lines_color, 20) : nva_transp == 90 ? color.new(lines_color, 10) : nva_transp == 100 ? color.new(lines_color, 0) : color.new(lines_color, dim_transp)
// Line Objects
// create/delete line objects
// uses va_high/low_level, lines_col, lines_dim_col - must remain after
new_level(index, line_obj, level, line_width, offset) =>
line_ = line_obj
line.delete(line_obj)
line_ := na
dir = flip_levels ? 1 : -1
m_offset = dir == 1 ? 1 : -length
// offset1 is buy/sell/total depending on volume_type
x1_offset = m_offset + offset
x2_offset = z_offset
x1 = time + x1_offset * bar_range
x2 = time + x2_offset * bar_range
y1 = level
y2 = level
// Line Color
// when side cover is shown:
// - for top nva zone dim the actual line object levels because they can't be displayed below the cover
// - both top/bottom zone covers are still needed in case only plot levels are used (num_levels <= 50)
nva_cond = ((va_high_level > 0) and (level >= va_high_level)) or ((va_low_level > 0) and (level <= va_low_level))
col = show_va and dim_nva_zones and nva_cond ? lines_dim_col : lines_col
// if na(line_) and not na(n[offset]) and show_lines and (index + half_levels <= num_levels)
if na(line_) and show_lines // and (index <= half_levels)
// line.style_solid, line.style_dotted, line.style_dashed, line.style_arrow_left, line.style_arrow_right, line.style_arrow_both
// x1, y1, x2, y2, xloc, color, style, width
line_ := line.new(x1, y1, x2, y2, style=line.style_solid, color=col, width=line_width, xloc=xloc.bar_time)
line_
var line line1 = na
var line line2 = na
var line line3 = na
var line line4 = na
var line line5 = na
var line line6 = na
var line line7 = na
var line line8 = na
var line line9 = na
var line line10 = na
var line line11 = na
var line line12 = na
var line line13 = na
var line line14 = na
var line line15 = na
var line line16 = na
var line line17 = na
var line line18 = na
var line line19 = na
var line line20 = na
var line line21 = na
var line line22 = na
var line line23 = na
var line line24 = na
var line line25 = na
var line line26 = na
var line line27 = na
var line line28 = na
var line line29 = na
var line line30 = na
var line line31 = na
var line line32 = na
var line line33 = na
var line line34 = na
var line line35 = na
var line line36 = na
var line line37 = na
var line line38 = na
var line line39 = na
var line line40 = na
var line line41 = na
var line line42 = na
var line line43 = na
var line line44 = na
var line line45 = na
var line line46 = na
var line line47 = na
var line line48 = na
var line line49 = na
var line line50 = na
// use 51..100 levels
line1 := new_level(1, line1, level51, line_width51, offset51)
line2 := new_level(2, line2, level52, line_width52, offset52)
line3 := new_level(3, line3, level53, line_width53, offset53)
line4 := new_level(4, line4, level54, line_width54, offset54)
line5 := new_level(5, line5, level55, line_width55, offset55)
line6 := new_level(6, line6, level56, line_width56, offset56)
line7 := new_level(7, line7, level57, line_width57, offset57)
line8 := new_level(8, line8, level58, line_width58, offset58)
line9 := new_level(9, line9, level59, line_width59, offset59)
line10 := new_level(10, line10, level60, line_width60, offset60)
line11 := new_level(11, line11, level61, line_width61, offset61)
line12 := new_level(12, line12, level62, line_width62, offset62)
line13 := new_level(13, line13, level63, line_width63, offset63)
line14 := new_level(14, line14, level64, line_width64, offset64)
line15 := new_level(15, line15, level65, line_width65, offset65)
line16 := new_level(16, line16, level66, line_width66, offset66)
line17 := new_level(17, line17, level67, line_width67, offset67)
line18 := new_level(18, line18, level68, line_width68, offset68)
line19 := new_level(19, line19, level69, line_width69, offset69)
line20 := new_level(20, line20, level70, line_width70, offset70)
line21 := new_level(21, line21, level71, line_width71, offset71)
line22 := new_level(22, line22, level72, line_width72, offset72)
line23 := new_level(23, line23, level73, line_width73, offset73)
line24 := new_level(24, line24, level74, line_width74, offset74)
line25 := new_level(25, line25, level75, line_width75, offset75)
line26 := new_level(26, line26, level76, line_width76, offset76)
line27 := new_level(27, line27, level77, line_width77, offset77)
line28 := new_level(28, line28, level78, line_width78, offset78)
line29 := new_level(29, line29, level79, line_width79, offset79)
line30 := new_level(30, line30, level80, line_width80, offset80)
line31 := new_level(31, line31, level81, line_width81, offset81)
line32 := new_level(32, line32, level82, line_width82, offset82)
line33 := new_level(33, line33, level83, line_width83, offset83)
line34 := new_level(34, line34, level84, line_width84, offset84)
line35 := new_level(35, line35, level85, line_width85, offset85)
line36 := new_level(36, line36, level86, line_width86, offset86)
line37 := new_level(37, line37, level87, line_width87, offset87)
line38 := new_level(38, line38, level88, line_width88, offset88)
line39 := new_level(39, line39, level89, line_width89, offset89)
line40 := new_level(40, line40, level90, line_width90, offset90)
line41 := new_level(41, line41, level91, line_width91, offset91)
line42 := new_level(42, line42, level92, line_width92, offset92)
line43 := new_level(43, line43, level93, line_width93, offset93)
line44 := new_level(44, line44, level94, line_width94, offset94)
line45 := new_level(45, line45, level95, line_width95, offset95)
line46 := new_level(46, line46, level96, line_width96, offset96)
line47 := new_level(47, line47, level97, line_width97, offset97)
line48 := new_level(48, line48, level98, line_width98, offset98)
line49 := new_level(49, line49, level99, line_width99, offset99)
line50 := new_level(50, line50, level100, line_width100, offset100)
// Zero line, Cover
// extend cover with cover_ext_height levels up/down to compensate for large level width
c_height = h * cover_ext_height
c_top = ph + c_height
c_base = pl - c_height
// can't assign show_last dynamically must use a set of 2 plots
plot(show_cover ? c_top : na, title="Side Cover", style=area, histbase=c_base, color=cover_color, transp=0, offset=c_offset, show_last=cover_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=nva_transp, 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=nva_transp, 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)