Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 20

//@version=5

indicator("Trading Hub 3 + signals GainzAlgo_Pro + Volume Profile (Maps) [LA]",


"Trading Hub 3 + signals GainzAlgo_Pro + Volume Profile (Maps) [LA]", true,
max_bars_back = 5000, max_labels_count = 500, max_lines_count = 500)

candle_stability_index_param = input.float(0.5, 'Candle Stability Index', 0, 1,


step=0.1, group='Technical', tooltip='Candle Stability Index measures the ratio
between the body and the wicks of a candle. Higher - more stable.')
rsi_index_param = input.int(50, 'RSI Index', 0, 100, group='Technical',
tooltip='RSI Index measures how overbought/oversold is the market. Higher - more
overbought/oversold.')
candle_delta_length_param = input.int(5, 'Candle Delta Length', 3,
group='Technical', tooltip='Candle Delta Length measures the period over how many
candles the price increased/decreased. Higher - longer period.')
disable_repeating_signals_param = input.bool(false, 'Disable Repeating Signals',
group='Technical', tooltip='Removes repeating signals. Useful for removing clusters
of signals and general clarity')

GREEN = color.rgb(29, 255, 40)


RED = color.rgb(255, 0, 0)
TRANSPARENT = color.rgb(0, 0, 0, 100)

label_size = input.string('normal', 'Label Size', options=['huge', 'large',


'normal', 'small', 'tiny'], group='Cosmetic')
label_style = input.string('text bubble', 'Label Style', ['text bubble',
'triangle', 'arrow'], group='Cosmetic')
buy_label_color = input(GREEN, 'BUY Label Color', inline='Highlight',
group='Cosmetic')
sell_label_color = input(RED, 'SELL Label Color', inline='Highlight',
group='Cosmetic')
label_text_color = input(color.white, 'Label Text Color', inline='Highlight',
group='Cosmetic')

stable_candle = math.abs(close - open) / ta.tr > candle_stability_index_param


rsi = ta.rsi(close, 14)

bull1ish_engulfing = close[1] < open[1] and close > open and close > open[1]
rsi_below = rsi < rsi_index_param
decrease_over = close < close[candle_delta_length_param]

bull1 = bull1ish_engulfing and stable_candle and rsi_below and decrease_over and


barstate.isconfirmed

bear1ish_engulfing = close[1] > open[1] and close < open and close < open[1]
rsi_above = rsi > 100 - rsi_index_param
increase_over = close > close[candle_delta_length_param]

bear1 = bear1ish_engulfing and stable_candle and rsi_above and increase_over and


barstate.isconfirmed

var last_signal = ''

if bull1 and (disable_repeating_signals_param ? (last_signal != 'buy' ? true :


na) : true)
if label_style == 'text bubble'
label.new(bull1 ? bar_index : na, low, 'BUY', color=buy_label_color,
style=label.style_label_up, textcolor=label_text_color, size=label_size)
else if label_style == 'triangle'
label.new(bull1 ? bar_index : na, low, 'BUY', yloc=yloc.belowbar,
color=buy_label_color, style=label.style_triangleup, textcolor=TRANSPARENT,
size=label_size)
else if label_style == 'arrow'
label.new(bull1 ? bar_index : na, low, 'BUY', yloc=yloc.belowbar,
color=buy_label_color, style=label.style_arrowup, textcolor=TRANSPARENT,
size=label_size)

last_signal := 'buy'
if bear1 and (disable_repeating_signals_param ? (last_signal != 'sell' ? true : na)
: true)
if label_style == 'text bubble'
label.new(bear1 ? bar_index : na, high, 'SELL', color=sell_label_color,
style=label.style_label_down, textcolor=label_text_color, size=label_size)
else if label_style == 'triangle'
label.new(bear1 ? bar_index : na, high, 'SELL', yloc=yloc.abovebar,
color=sell_label_color, style=label.style_triangledown, textcolor=TRANSPARENT,
size=label_size)
else if label_style == 'arrow'
label.new(bear1 ? bar_index : na, high, 'SELL', yloc=yloc.abovebar,
color=sell_label_color, style=label.style_arrowdown, textcolor=TRANSPARENT,
size=label_size)
last_signal := 'sell'

alertcondition(bull1, 'BUY Signals', 'New signal: BUY')


alertcondition(bear1, 'SELL Signals', 'New signal: SELL')

//drawing options
showPOI = input.bool(true, "Show POI", group="POI settings")
poi_type = input.string ("---",title='POI type', group="POI settings",
options=["---", "Mother Bar"])
mergeRatio = input.float(defval=0, minval=0, maxval=0.5, step=0.02, title="Merge
Ratio", group="POI settings" )
maxBarHistory = input.int(2000, title="Max IPA age", group="POI settings")

structure_type = input.string ("Choch without IDM",title='Structure type',


group="Structure", options=["Choch without IDM", "Choch with IDM"])
showHL = input.bool(true, "Mark H/L", inline = "HL", group = "Structure")
showCircleHL = input.bool(true, "Mark Circle",inline = "HL", group = "Structure")
showMn = input.bool(false, "Show internal structure", group = "Structure")
showBOS = input.bool(true, "Show B O S", group = "Structure")
showChoCh = input.bool(true, "Show CHoCH", group = "Structure")
showIDM = input.bool(true,"Show IDM", group = "Structure")
showPdh = input.bool(false,"Show PDH", inline = "PDH", group = "Structure")
lengPdh = input.int(40, title="", inline = "PDH", group="Structure")
showPdl = input.bool(false,"Show PDL", inline = "PDL", group = "Structure")
lengPdl = input.int(40, title="", inline = "PDL", group="Structure")
showMid = input.bool(true, "Show Equilibrium", inline = "mid", group = "Structure")
lengMid = input.int(40, title="", inline = "mid", group="Structure")
showSw = input.bool(true, "Show H/L sweeping lines", inline = "sweep", group =
"Structure")
markX = input.bool(false, 'Mark "X"', inline = "sweep", group = "Structure")
showTP = input.bool(false, 'Show Target profit',group = 'Structure')
showliveBOS = input.bool(true,"Show live BOS", inline = "liveB", group =
"Structure")
lengBos = input.int(40, title="", inline = "liveB", group="Structure")
showliveChoch = input.bool(true,"Show live ChoCh", inline = "liveCho", group =
"Structure")
lengChoch = input.int(40, title="", inline = "liveCho", group="Structure")
showliveIDM = input.bool(true,"Show live IDM", inline = "liveI", group =
"Structure")
lengIDM = input.int(15, title="", inline = "liveI", group="Structure")
showbarcolor = input.bool(true,"Bar color", inline = "Bar",group = "Structure")
showSCOB = input.bool(true, "Show SCOB", inline = "Bar", group = "Structure")
showISB = input.bool(false, 'Show ISB', inline = "Bar", group = "Structure")
showOSB = input.bool(false, 'Show OSB', inline = "Bar", group = "Structure")

colorHL = input.color(color.rgb(141, 59, 255), "High/Low", group = "Structure |


Color")
bull = input.color(color.green, "Bullish", group = "Structure | Color")
bear = input.color(color.red , "Bearish", group = "Structure | Color")
scobUp = input.color(#0bf982 , "Bullish SCOB", group = "Structure | Color")
scobDn = input.color(#62360e, "Bearish SCOB", group = "Structure | Color")
colorISB = input.color(#bb06f7,'Inside Bar', group = "Structure | Color")
colorOSB_up = input.color(#0b3ff9,'Bullish OSB', group = "Structure | Color")
colorOSB_down = input.color(#da781d,'Bearish OSB', group = "Structure | Color")
colorIDM = input.color(color.rgb(216, 49, 49, 20), "IDM", group = "Structure |
Color")
colorSweep = input.color(color.rgb(35, 39, 50), "Sweeping line", group =
"Structure | Color")
colorTP = input.color(color.purple, 'Target profit', group = 'Structure | Color')
colorDemand = input.color(color.rgb(47, 130, 96, 80), 'Demand', group = "Structure
| Color")
colorSupply = input.color(color.rgb(205, 92, 72, 80), 'Supply', group = "Structure
| Color")
colorMitigated = input.color(color.rgb(94, 87, 87, 77), 'Mitigated', group =
"Structure | Color")
puUpco = input.color(color.red , "High pivots", group = "Structure | Color")
puDnco = input.color(color.green, "Low pivots" , group = "Structure | Color")

//#region variable declaration


//Constant
const string IDM_TEXT = "I D M"
const string CHOCH_TEXT = "CHoCH"
const string BOS_TEXT = "B O S"
const string PDH_TEXT = "PDH"
const string PDL_TEXT = "PDL"
const string MID_TEXT = "0.5"

//line babel
var label idm_label = na
var line idm_line = na
var label choch_label = na
var line choch_line = na
var label bos_label = na
var line bos_line = na
var line pdh_line = na
var label pdh_label = na
var line pdl_line = na
var label pdl_label = na
var line mid_line = na
var label mid_label = na

//high low
var puHigh = high
var puLow = low
var L = low
var H = high
var idmLow = low
var idmHigh = high
var lastH = high
var lastL = low
var H_lastH = high
var L_lastHH = low
var H_lastLL = high
var L_lastL = low
var motherHigh = high[1]
var motherLow = low[1]
var puUp = high
var puDn = low
//bar indexes
var int motherBar = time[1]
var int puBar = na
var int puHBar = na
var int puLBar = na
var int idmLBar = na
var int idmHBar = na
var int HBar = time
var int LBar = time
var int lastHBar = time
var int lastLBar = time
var int puUpbar = na
var int puDnbar = na

//structure confirm
var bool mnStrc = na
var bool prevMnStrc = na
var bool isPrevBos = na
var bool findIDM = false
var bool isBosUp = false
var bool isBosDn = false
var bool isCocUp = true
var bool isCocDn = true

//poi
var bool isSweepOBS = false
var int current_OBS = na
var float high_MOBS = na
var float low_MOBS = na

var bool isSweepOBD = false


var int current_OBD = na
var float low_MOBD = na
var float high_MOBD = na

//Array
var arrTopBotBar = array.new_int(1, time)
var arrTop = array.new_float(1, high)
var arrBot = array.new_float(1, low)

var arrPbHBar= array.new_int(0)


var arrPbHigh = array.new_float(0)
var arrPbLBar = array.new_int(0)
var arrPbLow = array.new_float(0)
var demandZone = array.new_box(0)
var supplyZone = array.new_box(0)
var arrIdmHigh = array.new_float(0)
var arrIdmLow = array.new_float(0)
var arrIdmHBar = array.new_int(0)
var arrIdmLBar = array.new_int(0)
var arrLastH = array.new_float(0)
var arrLastHBar = array.new_int(0)
var arrLastL = array.new_float(0)
var arrLastLBar = array.new_int(0)
var arrIdmLine = array.new_line(0)
var arrIdmLabel = array.new_label(0)
var arrBCLine = array.new_line(0)
var arrBCLabel = array.new_label(0)
var arrHLLabel = array.new_label(0)
var arrHLCircle = array.new_label(0)

//color
color transp = color.new(color.gray,100)

//Caculate
curTf = timeframe.in_seconds(timeframe.period)
dayTf = timeframe.in_seconds("1D")
i_loop = 2*dayTf/curTf
[pdh, pdl] = request.security(syminfo.tickerid, 'D', [high[1], low[1]])
len = curTf*1000

//#endregion

//#region Inside Bar


isb = motherHigh > high and motherLow < low
if isb
motherHigh := motherHigh
motherLow := motherLow
motherBar := motherBar
else
motherHigh := high
motherLow := low
motherBar := time
//#region drawing functions
mnMark(bool UD) =>
if showMn
label.new(
x = UD ? puUpbar : puDnbar,
y = UD ? puUp : puDn,
yloc = UD ? yloc.abovebar : yloc.belowbar,
text = "",
color = UD ? puUpco : puDnco,
style = UD ? label.style_arrowdown : label.style_arrowup,
size = size.small
)
//Bar color
ba_color = if showSCOB
if low[1] == puDn and low >= low[1] and close > high[1] and close[1] > low[2]
scobUp
else if high[1] == puUp and high <= high[1] and close < low[1] and close[1] <
high[2]
scobDn
isCocUpValue = isCocUp
ba_color1 = if showbarcolor
isCocUpValue ? color.green : color.red
else
na

barcolor(ba_color1, -1)

//#region drawing function


isGreenBar(int bar) => close[bar] > open[bar]

textCenter(int left, int right) => int(math.avg(left,right))

getStyleLabel(bool style) => style ? label.style_label_down : label.style_label_up

getStyleArrow(bool style) => style ? label.style_arrowdown : label.style_arrowup

getYloc(bool style) => style ? yloc.abovebar : yloc.belowbar

getDirection(bool trend, int HBar, int LBar, float H, float L) =>


x = trend ? HBar : LBar
y = trend ? H : L
[x, y]

getTextLabel(float current, float last, string same, string diff) => current > last
? same : diff

getPdhlBar(float value) =>


int x = na
if value == pdh
for i = i_loop to 1 by 1
if (high[i] == pdh)
x := time[i]
break
else
for i = i_loop to 1 by 1
if (low[i] == pdl)
x := time[i]
break
x

updateTopBotValue() =>
array.push(arrTop, high)
array.push(arrBot, low)
array.push(arrTopBotBar, time)

updateLastHLValue() =>
array.push(arrLastH,lastH)
array.push(arrLastHBar,lastHBar)
array.push(arrLastL,lastL)
array.push(arrLastLBar,lastLBar)

updateIdmHigh() =>
array.push(arrIdmHigh,puHigh)
array.push(arrIdmHBar,puHBar)

updateIdmLow() =>
array.push(arrIdmLow,puLow)
array.push(arrIdmLBar,puLBar)
getNLastValue(arr, n) =>
if array.size(arr) > n - 1
array.get(arr, array.size(arr) - n)

removeNLastLabel(arr, n) =>
if array.size(arr) > n - 1
label.delete(array.get(arr, array.size(arr) - n))

removeNLastLine(arr, n) =>
if array.size(arr) > n - 1
line.delete(array.get(arr, array.size(arr) - n))

removeLastLabel(arr, n) =>
if array.size(arr) > n - 1
for i = 1 to n
label.delete(array.get(arr, array.size(arr) - i))

removeLastLine(arr, n) =>
if array.size(arr) > n - 1
for i = 1 to n
line.delete(array.get(arr, array.size(arr) - i))

fixStrcAfterBos() =>
removeLastLabel(arrBCLabel, 1)
removeLastLine(arrBCLine, 1)
removeLastLabel(arrIdmLabel, 1)
removeLastLine(arrIdmLine, 1)
removeLastLabel(arrHLLabel, 2)
removeLastLabel(arrHLCircle, 2)

fixStrcAfterChoch() =>
removeLastLabel(arrBCLabel, 2)
removeLastLine(arrBCLine, 2)
removeNLastLabel(arrHLLabel, 2)
removeNLastLabel(arrHLLabel, 3)
removeNLastLabel(arrHLCircle, 2)
removeNLastLabel(arrHLCircle, 3)
removeNLastLabel(arrIdmLabel, 2)
removeNLastLine(arrIdmLine, 2)

drawIDM(bool trend) =>


[x, y] = getDirection(trend, idmLBar, idmHBar, idmLow, idmHigh)
colorText = trend and H_lastH > L_lastHH or not trend and H_lastLL > L_lastL ?
color.rgb(255, 7, 7) : colorIDM
if showIDM
ln = line.new(x, y, time, y, xloc.bar_time, color = colorIDM, style =
line.style_dotted)
lbl = label.new(textCenter(time, x), y, IDM_TEXT, xloc.bar_time, color =
transp, textcolor = colorText, style = getStyleLabel(not trend), size = size.small)
array.push(arrIdmLine,ln)
array.push(arrIdmLabel,lbl)
array.clear(trend ? arrIdmLow : arrIdmHigh)
array.clear(trend ? arrIdmLBar : arrIdmHBar)

drawStructure(name, trend) =>


[x, y] = getDirection(trend, lastHBar, lastLBar, lastH, lastL)
color = trend ? bull : bear
if name == "BOS" and showBOS
ln = line.new(x, y, time, y, xloc.bar_time, color = color, style =
line.style_dashed)
lbl = label.new(textCenter(time, x), y, BOS_TEXT, xloc.bar_time, color =
transp, style = getStyleLabel(trend), textcolor = color, size = size.small)
array.push(arrBCLine,ln)
array.push(arrBCLabel,lbl)
if name == "ChoCh" and showChoCh
ln = line.new(x, y, time, y, xloc.bar_time, color = color, style =
line.style_dashed)
lbl = label.new(textCenter(time, x), y, CHOCH_TEXT, xloc.bar_time, color =
transp, style = getStyleLabel(trend), textcolor = color, size = size.small)
array.push(arrBCLine,ln)
array.push(arrBCLabel,lbl)

drawLiveStrc(bool condition, bool direction, color color1, color color2, string


txt, int length, label lbl, line ln) =>
var line _ln = ln
var label _lbl = lbl
if condition
colorText = direction ? color1 : color2
[x, y] = if txt == IDM_TEXT
getDirection(direction, idmHBar, idmLBar, idmHigh, idmLow)
else
getDirection(direction, lastHBar, lastLBar, lastH, lastL)
_txt = txt + " - " + str.tostring(y)
_ln := line.new(x, y, time + len*length, y, xloc.bar_time, color =
colorIDM, style = line.style_dotted),
_lbl := label.new(time + len*length, y, _txt, xloc.bar_time, color =
transp, textcolor = colorText, style = label.style_label_left, size = size.small)
line.delete(_ln[1])
label.delete(_lbl[1])

drawPrevStrc(bool condition, string txt, label lbl, line ln) =>


var line _ln = ln
var label _lbl = lbl
[x, y, color, x2, style] = switch
txt == PDH_TEXT => [getPdhlBar(pdh), pdh, bull, time + len*lengPdh,
line.style_solid]
txt == PDL_TEXT => [getPdhlBar(pdl), pdl, bear, time + len*lengPdl,
line.style_solid]
txt == MID_TEXT => [math.min(lastLBar, lastHBar), math.avg(lastL, lastH),
colorIDM, time + len*lengMid, line.style_dotted]
_txt = txt + " - " + str.tostring(y)
if condition
_ln := line.new(x, y, x2, y, xloc.bar_time, color = color, style = style)
_lbl := label.new(x2, y, _txt, xloc.bar_time, color = transp, textcolor =
color, style = label.style_label_left, size = size.small)
line.delete(_ln[1])
label.delete(_lbl[1])

labelMn(bool trend) =>


[x, y] = getDirection(trend, puHBar, puLBar, puHigh, puLow)
color = trend ? bear : bull
if showMn
label.new(x, y, "", xloc.bar_time, getYloc(trend), color,
getStyleArrow(trend), size = size.tiny )

labelHL(bool trend) =>


[x, y] = getDirection(trend, HBar, LBar, H, L)
txt = trend ? getTextLabel(H, getNLastValue(arrLastH, 1), "HH", "LH") :
getTextLabel(L, getNLastValue(arrLastL, 1), "HL", "LL")
if showHL
lbl = label.new(x, y, txt, xloc.bar_time, color = transp, textcolor =
colorHL, style = getStyleLabel(trend))
array.push(arrHLLabel, lbl)
if showCircleHL
lbl2 = label.new(x, y, '', xloc.bar_time, getYloc(trend), color = trend ?
bull : bear, style = label.style_circle, size = size.tiny)
array.push(arrHLCircle, lbl2)

sweepHL(bool trend) =>


[x, y] = getDirection(trend, lastHBar, lastLBar, lastH, lastL)
if showSw
line.new(x, y, time, y, xloc.bar_time, color = colorSweep, style =
line.style_dotted)
if markX
label.new(textCenter(time, x), y, "X", xloc.bar_time, color = transp,
textcolor = colorSweep, style = getStyleLabel(trend), size = size.small)

TP(H, L) =>
target = isCocUp ? high + math.abs(H - L) : low - math.abs(H - L)
target := target < 0 ? 0 : target
if showTP
line.new(bar_index, isCocUp ? high : low, bar_index, target, color =
colorTP, style = line.style_arrow_right)

createBox(left, right, top, bottom, color) =>


box.new(left=left, right=right, top=top, bottom=bottom, xloc = xloc.bar_time,
bgcolor=color, border_color=color, extend = extend.right)

removeZone(zoneArray, box zone) =>


index = array.indexof(zoneArray, zone)
box.delete(zone)
array.remove(zoneArray, index)

marginZone(zone) => [box.get_top(zone), box.get_bottom(zone), box.get_left(zone)]

handleZone(zoneArray, left, top, bot, color) =>


_top = top
_bot = bot
_left = left

zone = getNLastValue(zoneArray, 1)

[topZone, botZone, leftZone] = marginZone(zone)


rangeTop = math.abs(_top-topZone)/(topZone-botZone) < mergeRatio
rangeBot = math.abs(_bot-botZone)/(topZone-botZone) < mergeRatio

//Merge zone
if _top >= topZone and _bot <= botZone or rangeTop or rangeBot
_top := math.max(_top,topZone)
_bot := math.min(_bot,botZone)
_left := leftZone
removeZone(zoneArray, zone)

if not (_top <= topZone and _bot >= botZone)


array.push(zoneArray, createBox(_left, time, _top, _bot, color))
processZones(zones, isSupply) =>
if array.size(zones) > 0
for i = array.size(zones) - 1 to 0 by 1
zone = array.get(zones, i)
[topZone, botZone, leftZone] = marginZone(zone)

//Breaker block zones


if isSupply and low < botZone and close > topZone
array.push(demandZone, createBox(leftZone, time, topZone, botZone,
colorDemand))
else if not isSupply and high > topZone and close < botZone
array.push(supplyZone, createBox(leftZone, time, topZone, botZone,
colorSupply))
//Mitigated zones
else if (isSupply and high >= botZone and high < topZone) or (not
isSupply and low <= topZone and low > botZone)
box.set_right(zone, time)
box.set_extend(zone,extend.none)
box.set_bgcolor(zone, colorMitigated)
box.set_border_color(zone, colorMitigated)

//Delete sweep zones


if (time - leftZone > len*maxBarHistory) or (isSupply and high >=
topZone) or (not isSupply and low <= botZone)
removeZone(zones, zone)

scob(zones, isSupply) =>


[topZone, botZone, leftZone] = marginZone(getNLastValue(zones, 1))

if not isb[1]
if not isSupply and low[1] < low[2] and low[1] < low and close > high[1]
and low[1] < topZone and low[1] > botZone
scobUp
else if isSupply and high[1] > high[2] and high[1] > high and close <
low[1] and high[1] < topZone and high[1] > botZone
scobDn
else
na
//#endregion

//#region get value from array


top = getNLastValue(arrTop, 1)
bot = getNLastValue(arrBot, 1)
topBotBar = getNLastValue(arrTopBotBar, 1)

top1 = getNLastValue(arrTop, 2)
bot1 = getNLastValue(arrBot, 2)
topBotBar1 = getNLastValue(arrTopBotBar, 2)
//#endregion

//#region Outside Bar


osb = high > top and low < bot

//#endregion

//#region Minor Structure


if high >= top and low <= bot //notrend
if not na(mnStrc)
prevMnStrc := mnStrc ? true : false
else
if prevMnStrc and isGreenBar(0) and not isGreenBar(1)
puHigh := top
puHBar := topBotBar
labelMn(true)
labelMn(false)
if high > H
updateIdmLow()

if not prevMnStrc and not isGreenBar(0) and isGreenBar(1)


puLow := bot
puLBar := topBotBar
labelMn(true)
labelMn(false)
if low < L
updateIdmHigh()

if low < L and isGreenBar(0)


updateIdmHigh()

if high > H and not isGreenBar(0)


updateIdmLow()

updateTopBotValue()
puHigh := high
puLow := low
puHBar := time
puLBar := time
mnStrc := na

if high >= top and low > bot //uptrend


if prevMnStrc and na(mnStrc)
puHigh := top1
puHBar := topBotBar1
labelMn(true)
labelMn(false)
else if (not prevMnStrc and na(mnStrc)) or not mnStrc
labelMn(false)

if high > H
updateIdmLow()

updateTopBotValue()
puHigh := high
puHBar := time
prevMnStrc := na
mnStrc := true

if high < top and low <= bot //downtrend


if not prevMnStrc and na(mnStrc)
puLow := bot1
puLBar := topBotBar1
labelMn(false)
labelMn(true)
else if (prevMnStrc and na(mnStrc)) or mnStrc
labelMn(true)

if low < L
updateIdmHigh()

updateTopBotValue()
puLow := low
puLBar := time
prevMnStrc := na
mnStrc := false
//#endregion

//#region update IDM


if high >= H
H := high
HBar := time
L_lastHH := low
idmLow := getNLastValue(arrIdmLow, 1)
idmLBar := getNLastValue(arrIdmLBar, 1)

if low <= L
L := low
LBar := time
H_lastLL := high
idmHigh := getNLastValue(arrIdmHigh, 1)
idmHBar := getNLastValue(arrIdmHBar, 1)

//#endregion

// #region structure mapping


// Check for IDM
if findIDM and isCocUp and isCocUp
if low < idmLow
if structure_type == "Choch with IDM" and idmLow == lastL
if isPrevBos
fixStrcAfterBos()
lastL := getNLastValue(arrLastL, 1)
lastLBar := getNLastValue(arrLastLBar, 1)
else
fixStrcAfterChoch()
findIDM := false
isBosUp := false
lastH := H
lastHBar := HBar
drawIDM(true)
labelHL(true) //Confirm HH
updateLastHLValue()
H_lastH := getNLastValue(arrLastH, 1)
L := low
LBar := time

if findIDM and isCocDn and isBosDn


if high > idmHigh
if structure_type == "Choch with IDM" and idmHigh == lastH
if isPrevBos
fixStrcAfterBos()
lastH := getNLastValue(arrLastH, 1)
lastHBar := getNLastValue(arrLastHBar, 1)
else
fixStrcAfterChoch()
findIDM := false
isBosDn := false
lastL := L
lastLBar := LBar
drawIDM(false)
labelHL(false) //Confirm LL
updateLastHLValue()
L_lastL := getNLastValue(arrLastL, 1)
H := high
HBar := time

//Check for ChoCh


if isCocDn and high > lastH
if structure_type == "Choch without IDM" and idmHigh == lastH and close >
idmHigh
removeLastLabel(arrIdmLabel, 1)
removeLastLine(arrIdmLine, 1)
if close > lastH
drawStructure("ChoCh", true) //Confirm CocUp
findIDM := true
isBosUp := true
isCocUp := true
isBosDn := false
isCocDn := false
isPrevBos := false
L_lastL := getNLastValue(arrLastL, 1)
TP(lastH,lastL)
else
if idmHigh == lastH
removeLastLine(arrIdmLine, 1)
sweepHL(true)

if isCocUp and low < lastL


if structure_type == "Choch without IDM" and idmLow == lastL and close < idmLow
removeLastLabel(arrIdmLabel, 1)
removeLastLine(arrIdmLine, 1)
if close < lastL
drawStructure("ChoCh", false) //Confirm CocDn
findIDM := true
isBosUp := false
isCocUp := false
isBosDn := true
isCocDn := true
isPrevBos := false
H_lastH := getNLastValue(arrLastH, 1)
TP(lastH,lastL)
else
if idmLow == lastL
removeLastLine(arrIdmLine, 1)
sweepHL(false)

//Check for BoS


if not findIDM and not isBosUp and isCocUp
if high > lastH
if close > lastH
drawStructure("BOS", true) //Confirm BosUp
findIDM := true
isBosUp := true
isCocUp := true
isBosDn := false
isCocDn := false
isPrevBos := true
labelHL(false) //Confirm HL
lastL := L
lastLBar := LBar
L_lastL := L
TP(lastH,lastL)
else
sweepHL(true)

if not findIDM and not isBosDn and isCocDn


if low < lastL
if close < lastL
drawStructure("BOS", false) //Confirm BosDn
findIDM := true
isBosUp := false
isCocUp := false
isBosDn := true
isCocDn := true
isPrevBos := true
labelHL(true) //Confirm LH
lastH := H
lastHBar := HBar
H_lastH := H
TP(lastH,lastL)
else
sweepHL(false)
//#endregion

//#trigger update High and Low


if high > lastH
lastH := high
lastHBar := time

if low < lastL


lastL := low
lastLBar := time

//#endregion
if showPOI
if not isSweepOBS
high_MOBS := high[3]
low_MOBS := low[3]
current_OBS := time[3]
if high_MOBS > high[4] and high_MOBS > high[2]
isSweepOBS := true
else
if low_MOBS > high[1]
handleZone(supplyZone, current_OBS, high_MOBS, low_MOBS, colorSupply)
isSweepOBS := false
else
if poi_type == "Mother Bar" and isb[2]
high_MOBS := math.max(high_MOBS,motherHigh[2])
low_MOBS := math.min(low_MOBS,motherLow[2])
current_OBS := math.min(current_OBS,motherBar)
else
high_MOBS := high[2]
low_MOBS := low[2]
current_OBS := time[2]
if not isSweepOBD
low_MOBD := low[3]
high_MOBD := high[3]
current_OBD := time[3]
if low_MOBD < low[4] and low_MOBD < low[2]
isSweepOBD := true
else
if high_MOBD < low[1]
handleZone(demandZone, current_OBD, high_MOBD, low_MOBD, colorDemand)
isSweepOBD := false
else
if poi_type == "Mother Bar" and isb[2]
high_MOBD := math.max(high_MOBD,motherHigh[2])
low_MOBD := math.min(low_MOBD,motherLow[2])
current_OBD := math.min(current_OBD,motherBar)
else
high_MOBD := high[2]
low_MOBD := low[2]
current_OBD := time[2]
//#endregion

//#region run function


barcolor(showSCOB ? scob(supplyZone, true) : na, -1)
barcolor(showSCOB ? scob(demandZone, false) : na, -1)
barcolor(showISB and isb ? colorISB : na, 0,title="InSide Bar")
barcolor(osb and isGreenBar(0) and showOSB ? colorOSB_up : na)
barcolor(osb and not isGreenBar(0) and showOSB ? colorOSB_down : na)
processZones(supplyZone, true)
processZones(demandZone, false)
drawLiveStrc(showliveIDM and findIDM, not isCocUp, colorIDM, colorIDM, IDM_TEXT,
lengIDM, idm_label, idm_line)
drawLiveStrc(showliveChoch, not isCocUp, bull, bear, CHOCH_TEXT, lengChoch,
choch_label, choch_line)
drawLiveStrc(showliveBOS and not findIDM, isCocUp, bull, bear, BOS_TEXT, lengBos,
bos_label, bos_line)
drawPrevStrc(showPdh, PDH_TEXT, pdh_label, pdh_line)
drawPrevStrc(showPdl, PDL_TEXT, pdl_label, pdl_line)
drawPrevStrc(showMid, MID_TEXT, mid_label, mid_line)
//#endregion

//#Alerts

alertcondition(isBosUp, title="Bullish BoS Confirmed", message="Bullish BoS


structure has been confirmed")

alertcondition(isBosDn, title="Bearish BoS Confirmed", message="Bearish BoS


structure has been confirmed")

alertcondition((isCocUp or isCocDn) and not findIDM, title="ChoCh Confirmed",


message="ChoCh structure has been confirmed")

alertcondition(findIDM, title="IDM Confirmed", message="IDM structure has been


confirmed")

alertcondition(showSw, title="High/Low Sweep", message="High/Low Sweep structure


detected")

alertcondition(showTP, title="Target Profit", message="Target Profit structure


detected")

alertcondition(showliveBOS or showliveChoch or showliveIDM, title="Live


Structures", message="Live Structures detected")

alertcondition(condition=showCircleHL, title="Show Circle HL", message="Circle HL


condition met!")

if (isBosUp)
alert("Bullish BoS structure has been confirmed",
alert.freq_once_per_bar_close)

if (isBosDn)
alert("Bearish BoS structure has been confirmed",
alert.freq_once_per_bar_close)

if ((isCocUp or isCocDn) and not findIDM)


alert("ChoCh structure has been confirmed", alert.freq_once_per_bar_close)

if (findIDM)
alert("IDM structure has been confirmed", alert.freq_once_per_bar_close)

if (showSw)
alert("High/Low Sweep structure detected", alert.freq_once_per_bar_close)

if (showTP)
alert("Target Profit structure detected", alert.freq_once_per_bar_close)

if (showliveBOS or showliveChoch or showliveIDM)


alert("Live Structures detected", alert.freq_once_per_bar_close)

if (showCircleHL)
alert("Circle HL is marked on the chart",alert.freq_once_per_bar_close)

//------------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------{
sp1 =' ' , sp2 =
' '
src = input.source( close , 'source'
)
mtV = input.bool ( false , sp2 + 'Volume * currency'

,tooltip= 'Example BTCUSD -> volume in


USD' )
barsBack = input.int ( 5000 , 'Amount of bars'
, maxval=50000 )
maxLines = input.int ( 500 , 'Max lines'
, minval= 100 , maxval= 1000
,tooltip= 'max 1000'
)
iStep = input.string( 'Round' , ''
, group ='Round', options=['Round', 'Step'])
mlt = input.int ( 0 , 'Round'
, group ='Round', minval= -8 , maxval= 4
,tooltip= 'Example: 123456.789 \n 0->123456.789\n 1->123456.79\
n 2->123456.8\n 3->123457\n-1->123460\n-2->123500' )
step = input.float ( 1
, group ='Round' )
offset = input.int ( 200 , 'Offset'
, group ='display Volume Profile', maxval=500 )
width = input.int ( 205 , 'Max width Volume
Profile' , group ='display Volume Profile' )
cReg = input.color(color.rgb(178, 181, 190, 50), sp1
, group ='display Volume Profile', inline='c' )
cH_1 = input.color(color.rgb(255, 0, 0, 25), ''
, group ='display Volume Profile', inline='c' )
cH_2 = input.color(color.rgb(255, 153, 0, 25), ''
, group ='display Volume Profile', inline='c' )
sTab = input.bool ( false , sp1 + ' Show table'
, group ='display Volume Profile' )

m = mlt > 0 ? math.pow (10, mlt) :


1
src := iStep == 'Step' ? math.round(src / step) * step : mlt > 0 ?
math.round(src / m) * m : math.round(src,
math.round(math.abs(math.log10(syminfo.mintick)) +mlt))

//------------------------------------------------------------------------------
// Methods
//-----------------------------------------------------------------------------{
method set (line ln, int x, float y, int o) =>
ln .set_xy1 (math.max(0, bar_index + o ), y)
ln .set_xy2 (math.max(0, bar_index + o - nz(x)), y)

method set (box bx, int x, float y, int o) =>


bx .set_lefttop (math.max(0, bar_index + o ), y)
bx .set_rightbottom(math.max(0, bar_index + o - nz(x)), y)

method inOut(int [] a, int val) => a.unshift(val), a.pop()


method inOut(float[] a, float val) => a.unshift(val), a.pop()

//------------------------------------------------------------------------------
// Variables
//-----------------------------------------------------------------------------{
var originalMap = map.new <float, float>() //
key: close, value: volume
var lines = array.new < line >() //
array of lines
var boxes = array.new < box >() //
array of boxes
var tab = table.new(position.top_right, 2, 7, chart.bg_color,
chart.bg_color, 1, chart.bg_color, 1)

//------------------------------------------------------------------------------
// Execution
//-----------------------------------------------------------------------------{
n = bar_index
barsBack := math.min (barsBack , last_bar_index) //
minimum of ['Amount of bars' - total available bars]
mxLines2 = math.round(maxLines / 2)

if barstate.isfirst
for i = 0 to math.min(500, maxLines ) //
fill line array till "maxLines" or "500" reached
lines.unshift(line.new(na, na, na, na, width=2))
for i = 0 to math.min(500, math.max(0, maxLines - 500)) //
fill box array till "maxLines" or "500" reached (only after line array is filled)
boxes.unshift(box .new(na, na, na, na, border_width=1))

if last_bar_index - n == barsBack
line.new(n, close, n, close+ syminfo.mintick, extend=extend.both)

if last_bar_index - n <= barsBack


if originalMap.contains(src)
originalMap.put(src, originalMap.get(src) + (volume * (mtV ? src : 1))) //
if originalMap already contains the close value, add volume on that same key level
(instead of replace)
else
originalMap.put(src, (volume * (mtV ? src : 1))) //
key (close) :value (volume)

if barstate.islast
maxVol = 0.
for ln in lines
ln.set_color(cReg) //
set colour of all lines to default
for bx in boxes
bx.set_border_color(color.new(cReg, 70)) //
set colour of all boxes to default

if originalMap.size() > 1
copyK = originalMap.keys().copy() //
make a copy of the keys -> array
copyK.sort() //
sort (ascending)
idx = copyK.binary_search_leftmost(src) //
look for position of 'current' src in copyK
szL = idx, szR = copyK.size() -1 - idx //
check how many left (lower) and right (higher) of idx (size: left - idx - right)
sml = math.min(szL, szR) //
smallest side
if szR == sml
szL := math.min(maxLines - math.min(mxLines2, szR), szL) //
if R side has 'unused' lines -> give them to L side
szR := math.min(mxLines2, szR)
else
szL := math.min(mxLines2, szL)
szR := math.min(maxLines - math.min(mxLines2, szL), szR) //
if L side has 'unused' lines -> give them to R side

sliceK = copyK.slice(idx - szL, idx + szR) //


grab (max. 500) keys around 'current' close

newMap = map.new<float, float>() //


new map
for i = 0 to sliceK.size() -1 //
all keys from sliceK : values from originalMap
getKey = sliceK.get(i) //
key from sliceK
getVal = originalMap.get(getKey) //
values from originalMap
if getVal > maxVol //
get max volume of the set
maxVol := getVal
newMap.put(getKey, getVal) //
put in 'newMap'

w = width / maxVol //
make sure lines don't exceed 'max width Volume Profile'

aMaxI = array.from(0 , 0 ) //
index of largest and second largest volume
aMaxV = array.from(0., 0.) //
value of largest and second largest volume

max = 0., keys = newMap.keys(), vals = newMap.values()

for i = 0 to keys.size()-1
clo = keys.get(i)
vol = vals.get(i)
if vol > max //
when largest volume is found -> set index so line can be coloured later
max := vol
aMaxI.inOut( i )
aMaxV.inOut(vol)
else if vol > aMaxV.get(1) //
when second largest volume is found -> set index so line can be coloured later
aMaxI.set(1, i )
aMaxV.set(1,vol)
if i < 500
lines.get(i ).set(math.round(vol * w), clo, offset) //
update 'lines' array
else
boxes.get(i - 500).set(math.round(vol * w), clo, offset) //
update 'boxes' array (line array is full -> box array)

uno = aMaxI.first( ), duo = aMaxI.get (1)


if uno < 500
lines .get(uno) .set_color(cH_1) //
colour line with largest volume
else
boxes .get(uno - 500) .set_border_color(cH_1) //
colour line (box) with largest volume
if duo < 500
lines .get(duo) .set_color(cH_2) //
colour line with second largest volume
else
boxes .get(duo - 500) .set_border_color(cH_2) //
colour line (box) with second largest volume

// map.put(originalMap, price, volume)


// or
// originalMap.put(price, volume)

// if originalMap.contains(price)
// originalMap.put(price, originalMap.get(price) + volume)
// copyK = originalMap.keys().copy()
// copyK.sort()
// idx = copyK.binary_search_leftmost(src)

// newMap = map.new<float, float>()

//------------------------------------------------------------------------------
// Table
//-----------------------------------------------------------------------------{
if sTab
tab.cell(0, 0, text='size originalMap' ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(1, 0, text=str.tostring(originalMap.size()) ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(0, 1, text= '# higher' ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(1, 1, text=str.tostring(originalMap.size() - idx),
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(0, 2, text= 'index "close"' ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(1, 2, text=str.tostring( idx ) ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(0, 3, text= ' ' ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(0, 4, text= 'size newMap' ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(1, 4, text=str.tostring( newMap.size() ) ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(0, 5, text= '# higher' ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(1, 5, text=str.tostring( szR ) ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(0, 6, text= '# lower' ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)
tab.cell(1, 6, text=str.tostring( szL ) ,
text_font_family=font.family_monospace, text_color=chart.fg_color, height=2)

//-----------------------------------------------------------------------------}

You might also like