Volume Profile
Volume Profile
0 at
https://mozilla.org/MPL/2.0/
// © LeviathanCapital
//@version=5
indicator("Range Analysis - By Leviathan", shorttitle='Range Analysis - By
Leviathan', overlay=true, max_boxes_count=500, max_bars_back = 500)
//
bool inZone = time >= startTime and time <= endTime
bool newSession = inZone and not inZone[1]
bool endSession = not inZone and inZone[1]
if newSession
zoneStartIndex := bar_index
if endSession
zoneEndIndex := bar_index
int lookback = bar_index - zoneStart
var activeZone = false
//
highest = rangemax=='Range Max: Wick' ? high : rangemax=='Range Max: Close' ?
close : rangemax=='Range Max: HLC3' ? hlc3 : ohlc4
lowest = rangemax=='Range Max: Wick' ? low : rangemax=='Range Max: Close' ?
close : rangemax=='Range Max: HLC3' ? hlc3 : ohlc4
profHigh = ta.highest(highest, barsInSession+1)[1]
profLow = ta.lowest(lowest, barsInSession+1)[1]
resolution = res
//
var vpGreen = array.new_float(resolution, 0)
var vpRed = array.new_float(resolution, 0)
var zoneBounds = array.new_float(resolution, 0)
//
var float[] ltfOpen = array.new_float(0)
var float[] ltfClose = array.new_float(0)
var float[] ltfHigh = array.new_float(0)
var float[] ltfLow = array.new_float(0)
var float[] ltfVolume = array.new_float(0)
//
string userSymbol = 'BINANCE' + ":" + string(syminfo.basecurrency) +
'USDT.P'
string openInterestTicker = str.format("{0}_OI", userSymbol)
string timeframe = syminfo.type == "futures" and timeframe.isintraday ?
"1D" : timeframe.period
deltaOi = request.security(openInterestTicker, timeframe, close-
close[1], ignore_invalid_symbol = true)
oi = request.security(openInterestTicker, timeframe.period,
close, ignore_invalid_symbol = true)
pldeltaoi = deltaOi
//
vol() =>
out = smoothVol ? ta.ema(volume, 5) : volume
if voltype == 'Open Interest'
out := deltaOi
out
//
float dO = open
float dC = close
float dH = high
float dL = low
float dV = vol()
//
switchLineStyle(x) =>
switch x
'────' => line.style_solid
'--------' => line.style_dashed
'┈┈┈┈' => line.style_dotted
switchPos(x) =>
switch x
'Left' => text.align_left
'Right' => text.align_right
'Center' => text.align_center
switchPlotStyle(x) =>
switch x
'•••••••••' => plot.style_circles
'────' => plot.style_linebr
switchsize(x) =>
switch x
'Tiny' => size.tiny
'Small' => size.small
'Normal' => size.normal
'Large' => size.large
'Auto' => size.auto
//
resetProfile(enable) =>
if enable
array.fill(vpGreen, 0)
array.fill(vpRed, 0)
array.clear(ltfOpen)
array.clear(ltfHigh)
array.clear(ltfLow)
array.clear(ltfClose)
array.clear(ltfVolume)
tr = ta.atr(1)
atr = ta.atr(14)
profileAdd(o, h, l, c, v, g, w) =>
for i = 0 to array.size(vpGreen) - 1
zoneTop = array.get(zoneBounds, i)
zoneBot = zoneTop - g
body_top = math.max(c, o)
body_bot = math.min(c, o)
itsgreen = c >= o
topwick = h - body_top
bottomwick = body_bot - l
body = body_top - body_bot
bodyvol = body * v / (2 * topwick + 2 * bottomwick + body)
topwickvol = 2 * topwick * v / (2 * topwick + 2 * bottomwick + body)
bottomwickvol = 2 * bottomwick * v / (2 * topwick + 2 * bottomwick + body)
if voltype == 'Volume'
array.set(vpGreen, i, array.get(vpGreen, i) + (itsgreen ?
get_vol(zoneBot, zoneTop, body_bot, body_top, body, bodyvol) : 0) +
get_vol(zoneBot, zoneTop, body_top, h, topwick, topwickvol) / 2 + get_vol(zoneBot,
zoneTop, body_bot, l, bottomwick, bottomwickvol) / 2)
array.set(vpRed, i, array.get(vpRed, i) + (itsgreen ? 0 :
get_vol(zoneBot, zoneTop, body_bot, body_top, body, bodyvol)) + get_vol(zoneBot,
zoneTop, body_top, h, topwick, topwickvol) / 2 + get_vol(zoneBot, zoneTop,
body_bot, l, bottomwick, bottomwickvol) / 2)
else if voltype == 'Open Interest'
if v > 0
array.set(vpGreen, i, array.get(vpGreen, i) + get_vol(zoneBot,
zoneTop, body_bot, body_top, body, v))// + get_vol(zoneBot, zoneTop, body_top, h,
topwick, topwickvol) / 2 + get_vol(zoneBot, zoneTop, body_bot, l, bottomwick,
bottomwickvol) / 2)
if v < 0
array.set(vpRed, i, array.get(vpRed, i) + get_vol(zoneBot, zoneTop,
body_bot, body_top, body, -v))// + get_vol(zoneBot, zoneTop, body_top, h, topwick,
topwickvol) / 2 + get_vol(zoneBot, zoneTop, body_bot, l, bottomwick, bottomwickvol)
/ 2)
calcSession(update) =>
array.fill(vpGreen, 0)
array.fill(vpRed, 0)
if bar_index > lookback and update and (showPoc or showProf or showVAbox or
showVAH or showVAL or hvolhm)
gap = (profHigh - profLow) / resolution
for i = 0 to resolution - 1
array.set(zoneBounds, i, profHigh - gap * i)
if array.size(ltfOpen) > 0
for j = 0 to array.size(ltfOpen) - 1
profileAdd(array.get(ltfOpen, j), array.get(ltfHigh, j),
array.get(ltfLow, j), array.get(ltfClose, j), array.get(ltfVolume, j), gap, 1)
pocLevel() =>
float maxVol = 0
int levelInd = 0
for i = 0 to array.size(vpRed) - 1
if array.get(vpRed, i) + array.get(vpGreen, i) > maxVol
maxVol := array.get(vpRed, i) + array.get(vpGreen, i)
levelInd := i
float outLevel = na
if levelInd != array.size(vpRed) - 1
outLevel := array.get(zoneBounds, levelInd) - (array.get(zoneBounds,
levelInd) - array.get(zoneBounds, levelInd+1)) / 2
outLevel
valueLevels(poc) =>
float gap = (profHigh - profLow) / resolution
float volSum = array.sum(vpRed) + array.sum(vpGreen)
float volCnt = 0
float vah = profHigh
float val = profLow
int pocInd = 0
for i = 0 to array.size(zoneBounds)-2
if array.get(zoneBounds, i) >= poc and array.get(zoneBounds, i + 1) < poc
pocInd := i
[val, vah]
//
half = (profHigh+profLow) / 2
l75 = (half + profHigh) / 2
l25 = (half + profLow) / 2
l125 = (profLow+l25) / 2
l375 = (half + l25) / 2
l625 = (half + l75) / 2
l875 = (l75 + profHigh) / 2
//
f_newLine(condition,x, y, c, w, s) =>
condition ? line.new(x, y, extendb ? bar_index+extnmb : bar_index, y, color=c,
width=w, style=switchLineStyle(s), extend = extend ? extend.right : extend.none) :
na
f_newLabel(condition, x, y, txt, txtcl) =>
condition ? label.new(extend ? x : (lblpos=='Right' ? (extendb ?
bar_index+extnmb+1 : bar_index+1) : x), y, text=txt, color=color.rgb(255, 255, 255,
100), textcolor = txtcl, style = extend or lblpos=='Left' ? label.style_label_right
: label.style_label_left, size=switchsize(lblsize)) : na
f_newNode(condition, x, top, right, bott, col, txt) =>
condition ? box.new(x, top, right, bott, bgcolor=col, border_width=0, text=
volval ? txt : na,xloc=xloc.bar_index, text_size = switchsize(ndsize), text_color =
chart.fg_color, text_halign = switchPos(ndpos)) : na
f_newHeatmap(condition, x, top, right, bott, col, txt) =>
condition ? box.new(x, top, right, bott, bgcolor=col, border_width=0, text=
hmval ? txt : na,xloc=xloc.bar_index, text_size = switchsize(hmsize), text_color =
chart.fg_color, text_halign = switchPos(hmpos)) : na
drawNewZone(update) =>
var box [] profileBoxesArray = array.new_box(0)
var line [] levelsLinesArray = array.new_line(0)
var box [] boxes = array.new_box(0)
var line [] RangeLinesArray = array.new_line(0)
var label[] levelLabels = array.new_label(0)
for i = 0 to array.size(vpRed) - 1
vpct = array.percentrank(vpGreen, i)/100
netcol = color.from_gradient(vpct, 0, 1, netcol1, netcol2)
hmcol = color.from_gradient(vpct, 0, 1, hhmcol1, hhmcol2)
gleft = profilepos=='Left' ? leftMax : bar_index[0]
greenEnd = int(leftMax + (rightMax - leftMax) *
(array.get(vpGreen, i) / rightMaxVol))
greenEndD = int(gleft - (rightMax - leftMax) * (array.get(vpGreen,
i) / rightMaxVol))
greenEnd2 = int(bar_index[0] + (rightMax - leftMax) *
(array.get(vpGreen, i) / rightMaxVol))
redEnd = int(greenEnd + (rightMax - leftMax) * (array.get(vpRed,
i) / rightMaxVol))
redEndD = int(greenEndD - (rightMax - leftMax) *
(array.get(vpRed, i) / rightMaxVol))
redEnd2 = int(greenEnd2 + (rightMax - leftMax) *
(array.get(vpRed, i) / rightMaxVol))
redEnd3 = int(int(leftMax) - (rightMax - leftMax) *
(array.get(vpRed, i) / rightMaxVol))
redEnd4 = int(bar_index[0] - (rightMax - leftMax) *
(array.get(vpRed, i) / rightMaxVol))
total = int(leftMax + ((rightMax - leftMax) *
(array.get(vpGreen, i) / rightMaxVol)) + (rightMax - leftMax) * (array.get(vpRed,
i) / rightMaxVol))
totalD = int(gleft - ((rightMax - leftMax) * (array.get(vpGreen,
i) / rightMaxVol)) - (rightMax - leftMax) * (array.get(vpRed, i) / rightMaxVol))
total2 = int(bar_index[0] + ((rightMax - leftMax) *
(array.get(vpGreen, i) / rightMaxVol)) + (rightMax - leftMax) * (array.get(vpRed,
i) / rightMaxVol))
delta = array.get(vpGreen, i)-array.get(vpRed, i)
deltap = (int(gleft + (rightMax - leftMax) *
(math.abs(array.get(vpGreen, i)-array.get(vpRed, i)) / rightMaxVol)))
deltap2 = (int(gleft - (rightMax - leftMax) *
(math.abs(array.get(vpGreen, i)-array.get(vpRed, i)) / rightMaxVol)))
totvol = str.tostring(array.get(vpGreen, i) + (voltype=='Volume'
? array.get(vpRed, i) : 0), format.volume)
hmvoloi = str.tostring(array.get(vpGreen, i) - array.get(vpRed,
i) , format.volume)
gvol = str.tostring(array.get(vpGreen, i), format.volume)
rvol = str.tostring(array.get(vpRed, i), format.volume)
dvol = str.tostring(delta, format.volume)
if profilepos=='Left' and showProf
array.push(profileBoxesArray, f_newNode(volnodes=='Up/Down',
int(leftMax), array.get(zoneBounds, i) - buffer, profiledir=='Right' ? greenEnd :
greenEndD, array.get(zoneBounds, i) - gap + buffer, bullCol, gvol))
array.push(profileBoxesArray, f_newNode(volnodes=='Up/Down' and
profiletype=='Type 1', profiledir=='Right' ? greenEnd : greenEndD,
array.get(zoneBounds, i) - buffer, profiledir=='Right' ? redEnd : redEndD,
array.get(zoneBounds, i) - gap + buffer, bearCol, rvol))
array.push(profileBoxesArray, f_newNode(volnodes=='Up/Down' and
profiletype=='Type 2', int(leftMax), array.get(zoneBounds, i) - buffer, redEnd3,
array.get(zoneBounds, i) - gap + buffer, bearCol, rvol))
array.push(profileBoxesArray, f_newNode(volnodes=='Total',
int(leftMax), array.get(zoneBounds, i) - buffer, profiledir=='Right' ? total :
totalD, array.get(zoneBounds, i) - gap + buffer, netcol, totvol))
array.push(profileBoxesArray, f_newNode(volnodes=='Delta' and
profiletype=='Type 1', int(leftMax), array.get(zoneBounds, i) - buffer, deltap,
array.get(zoneBounds, i) - gap + buffer, delta>0 ? bullCol : bearCol, dvol))
array.push(profileBoxesArray, f_newNode(volnodes=='Delta' and
profiletype=='Type 2', int(leftMax), array.get(zoneBounds, i) - buffer, delta>0 ?
deltap : deltap2, array.get(zoneBounds, i) - gap + buffer, delta>0 ? bullCol :
bearCol, dvol))
if showHL
line.new(int(leftMax), profHigh, extendb ? bar_index+extnmb :
bar_index, profHigh, color=hlCol, width=1, style=line.style_solid, extend =
extend ? extend.right : extend.none)
line.new(int(leftMax), profLow, extendb ? bar_index+extnmb :
bar_index, profLow, color=hlCol, width=1, style=line.style_solid, extend = extend ?
extend.right : extend.none)
if lvl05 or quarters or eighths
f_newLine(true,int(leftMax), half, lvl05Col, 1, lvl05Style)
if quarters or eighths
f_newLine(true,int(leftMax), l75, quartersCol, 1, quartersStyle)
f_newLine(true,int(leftMax), l25, quartersCol, 1, quartersStyle)
if eighths
f_newLine(true,int(leftMax), l125, eighthsCol, 1, eighthsStyle)
f_newLine(true,int(leftMax), l375, eighthsCol, 1, eighthsStyle)
f_newLine(true,int(leftMax), l625, eighthsCol, 1, eighthsStyle)
f_newLine(true,int(leftMax), l875, eighthsCol, 1, eighthsStyle)
if outer
f_newLine(quarters or eighths,int(leftMax), profLow - (l25-profLow),
outerCol, 1, outerStyle)
f_newLine(quarters or eighths,int(leftMax), profLow - (half-profLow),
outerCol, 1, outerStyle)
f_newLine(quarters or eighths,int(leftMax), profHigh + (l25-profLow),
outerCol, 1, outerStyle)
f_newLine(quarters or eighths,int(leftMax), profHigh + (half-profLow),
outerCol, 1, outerStyle)
f_newLine(eighths,int(leftMax), profHigh + (l125-profLow), outerCol, 1,
outerStyle)
f_newLine(eighths,int(leftMax), profHigh + (l375-profLow), outerCol, 1,
outerStyle)
f_newLine(eighths,int(leftMax), profLow - (l125-profLow), outerCol, 1,
outerStyle)
f_newLine(eighths,int(leftMax), profLow - (l375-profLow), outerCol, 1,
outerStyle)
f_newLine(fib,int(leftMax), f161, fibCol, 1, fibStyle)
f_newLine(fib,int(leftMax), f261, fibCol, 1, fibStyle)
if fib
f_newLine(true,int(leftMax), f618, fibCol, 1, fibStyle)
f_newLine(true,int(leftMax), f236, fibCol, 1, fibStyle)
f_newLine(true,int(leftMax), f382, fibCol, 1, fibStyle)
f_newLine(true,int(leftMax), f786, fibCol, 1, fibStyle)
if dirline
line.new(int(leftMax), dir=='UP' ? profLow : profHigh, bar_index,
dir=='UP' ? profHigh : profLow, color=fibCol, width = 1,
style=switchLineStyle(fibStyle), extend = extend ? extend.right : extend.none)
if labels
f_newLabel(lvl05, int(leftMax), half, '0.5', hlCol)
f_newLabel(fib, int(leftMax), f618, '0.618', fibCol)
f_newLabel(fib, int(leftMax), f236, '0.236', fibCol)
f_newLabel(fib, int(leftMax), f382, '0.382', fibCol)
f_newLabel(fib, int(leftMax), f786, '0.786', fibCol)
f_newLabel(showHL, int(leftMax), profHigh, dir=='UP' ? '0' : '1',
hlCol)
f_newLabel(showHL, int(leftMax), profLow, dir=='UP' ? '1' : '0',
hlCol)
f_newLabel(quarters, int(leftMax), l75, dir=='UP' ? '0.25' : '0.75',
hlCol)
f_newLabel(quarters, int(leftMax), l25, dir=='UP' ? '0.75' : '0.25',
hlCol)
poc = pocLevel()
[val, vah] = valueLevels(poc)
if showPoc or showVAbox or showVAL or showVAH
size = array.size(levelsLinesArray)
if size > 0
for j = 0 to size - 1
line.delete(array.get(levelsLinesArray, size - 1 - j))
array.remove(levelsLinesArray, size - 1 - j)
if showPoc
array.push(levelsLinesArray, line.new(int(leftMax), poc, extendb ?
bar_index+extnmb : bar_index, poc, color=pocCol, width=1, xloc=xloc.bar_index,
extend = extend ? extend.right : extend.none, style = switchLineStyle(pocStyle)))
if showVAH
array.push(levelsLinesArray, line.new(int(leftMax), vah, extendb ?
bar_index+extnmb : bar_index, vah, color=vahCol, width=1, xloc=xloc.bar_index,
extend = extend ? extend.right : extend.none, style = switchLineStyle(vahStyle)))
if showVAL
array.push(levelsLinesArray, line.new(int(leftMax), val, extendb ?
bar_index+extnmb : bar_index, val, color=valCol, width=1, xloc=xloc.bar_index,
extend = extend ? extend.right : extend.none, style = switchLineStyle(valStyle)))
if showVAbox
array.push(boxes, box.new(int(leftMax), vah, extendb ? bar_index+extnmb
: bar_index, val, bgcolor=VAboxCol,border_color = na, xloc=xloc.bar_index, extend =
extend ? extend.right : extend.none))
//
combArray(arr1, arr2) =>
out = array.copy(arr1)
if array.size(arr2) > 0
for i = 0 to array.size(arr2) - 1
array.push(out, array.get(arr2, i))
out
//
updateIntra(o, h, l, c, v) =>
array.push(ltfOpen, o)
array.push(ltfHigh, h)
array.push(ltfLow, l)
array.push(ltfClose, c)
array.push(ltfVolume, v)
//
calcSession(endSession or (barstate.islast and inZone))
drawNewZone(endSession or (barstate.islast and inZone))
resetProfile(newSession)
//
if inZone
updateIntra(dO, dH, dL, dC, dV)
if endSession
activeZone := false
if newSession
zoneStart := bar_index
activeZone := true
//
startCalculationDate = startTime
vwap_calc() =>
var srcVolArray = array.new_float(na)
var volArray = array.new_float(na)
if startCalculationDate <= time
array.push(srcVolArray, hlc3*volume)
array.push(volArray, volume)
else
array.clear(srcVolArray), array.clear(volArray)
array.sum(srcVolArray)/array.sum(volArray)
anchoredVwap = vwap_calc()
//
vhmsrc = voltype=='Volume' ? volume : deltaOi
hvol = ta.highest(vhmsrc, 50)
lvol = ta.lowest(vhmsrc, 50)
color1 = color.from_gradient(vhmsrc, 0, hvol, vhmcol1, vhmcol2)
ph = plot((extend ? true : inZone) and volhm ? profHigh : na, color=
color.rgb(54, 58, 69, 100), style=plot.style_linebr)
pl = plot((extend ? true : inZone) and volhm ? profLow : na, color=
color.rgb(54, 58, 69, 100), style=plot.style_linebr)
fill(ph, pl, color1)