//@version=5
indicator("LEOALGO", "LEOALGO", true, max_bars_back = 1500, max_boxes_count = 500,
max_labels_count = 500, max_lines_count = 500)
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0
International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
//---------------------------------------------------------------------------------
------------------------------------}
//---------------------------------------------------------------------------------
------------------------------------}
// Settings
//---------------------------------------------------------------------------------
------------------------------------{
disp = display.all - display.status_line
rpGR = 'Profile Generic Settings'
rpLN = input.int(200, ' Lookback Length / Fixed Range', minval = 10, maxval =
1500, step = 10 , group = rpGR, display = disp)
rpLN := last_bar_index > rpLN ? rpLN - 1 : last_bar_index
vpSRC = input.string('Volume', ' Profile Source', options = ['Volume', 'Money
Flow'], group = rpGR, display = disp)
vpGR = 'Profile Presentation Settings'
vpTP = 'displays total trading activity/money flow (common interest, both buying
and selling trading activity/money flow) over a specified time period at specific
price levels\n\n' +
' - high traded node rows : high trading activity/money flow price levels
- usually represents consolidation levels (value areas)\n' +
' - average traded node rows : average trading activity/money flow price
levels\n' +
' - low traded node rows : low trading activity/money flow price levels -
usually represents supply & demand levels or liquidity levels\n\n' +
'row lengths, indicates the amount of the traded activity/money flow at
specific price levels'
vpSH = input.bool(true, 'Volume/Money Flow Profile', group = vpGR, tooltip =
vpTP, display = disp)
vpHVC = input.color(color.new(#ffeb3b, 50), ' High Traded Nodes', inline =
'VP1', group = vpGR)
vpHVT = input.int(53, 'Threshold %' , minval = 50, maxval = 99 , step = 1,inline =
'VP1', group = vpGR, tooltip = 'option range [50-99]', display = disp) / 100
vpAVC = input.color(color.new(#2962ff, 50), ' Average Traded Nodes', group =
vpGR)
vpLVC = input.color(color.new(#f23645, 50), ' Low Traded Nodes', inline =
'VP2', group = vpGR)
vpLVT = input.int(37, 'Threshold %' , minval = 10, maxval = 40 , step = 1,inline =
'VP2', group = vpGR, tooltip = 'option range [10-40]', display = disp) / 100
spTP = 'displays the sentiment, the dominat party over a specified time period at
the specific price levels\n\n' +
' - bullish node rows : buying trading activity/money flow is higher\n'
+
' - barish node rows : selling trading activity/money flow is higher\n\n'
+
'row lengths, indicates the strength of the buyers/sellers at the
specific price levels'
spSH = input.bool(true, 'Sentiment Profile', group = vpGR, tooltip = spTP)
spPTT = 'conditions used to calculate the up/down volume/money flow\n\n' +
'* bar polarity\n up => if close > open\n down => if close <= open\n\
n' +
'* bar buying/selling pressure\n up => if (close - low) > (high -
close)\n down => if (close - low) <= (high - close)'
spPT1 = 'Bar Polarity'
spPT2 = 'Bar Buying/Selling Pressure'
spPTY = input.string(spPT1, ' Sentiment Polarity Method', options = [spPT1,
spPT2], group = vpGR, tooltip = spPTT, display = disp)
spBLC = input.color(color.new(#26a69a, 50), ' Bullish Nodes', inline = 'SP',
group = vpGR)
spBRC = input.color(color.new(#ef5350, 50), 'Bearish Nodes', inline = 'SP', group
= vpGR)
hmSH = input.bool(false, 'Profile Heatmap', group = vpGR, tooltip = 'tip : higher
number of rows results with a better visuals')
hmSO1 = 'Volume/Money Flow Profile'
hmSRC = input.string(hmSO1, ' Heatmap Source', options = [hmSO1, 'Sentiment
Profile'], group = vpGR, display = disp)
hmTR = input.int(73, ' Heatmap Transparency' , minval = 0, maxval = 100 ,
group = vpGR, display = disp)
othGR = 'Other Presentation Settings'
pcTP = 'displays the price level of the highest traded activity/money flow or the
changes of the price levels with the highest traded activity/money flow'
rpPC = input.string('Last(Zone)', ' Level of Significance', options =
['Developing', 'Last(Line)', 'Last(Zone)', 'None'], inline='PoC', group = othGR,
tooltip = pcTP, display = disp)
vaSH = input.bool(false, 'Consolidation Zones', group = othGR, display = disp)
vaTH = input.int(25, ' Consolidation Threshold %' , minval = 0, maxval = 100,
inline = 'va', group = othGR, display = disp) / 100
vaC = input.color(color.new(#2962ff, 73), '', inline = 'va', group = othGR)
spTT = 'displays the price zone of the highest bullish or bearish sentiment zone'
spPC = input.bool(false, 'Highest Sentiment Zone', inline = 'spP', group = othGR,
tooltip = spTT)
rpPL = input.bool(false, 'Profile Price Levels', inline = 'BBe', group = othGR)
rpPLC = input.color(color.new(#00bcd4, 0), '', inline = 'BBe', group = othGR)
rpLS = input.string('Small', "", options=['Tiny', 'Small', 'Normal'], inline =
'BBe', group = othGR, display = disp)
rpBG = input.bool(false, 'Profile Range Background Fill', inline = 'BG', group =
othGR)
rpBGC = input.color(color.new(#00bcd4, 95), '', inline = 'BG', group = othGR)
otGR = 'Other Profile Settings'
rpNR = input.int(25, ' Number of Rows' , minval = 10, maxval = 100 ,step = 5,
group = otGR, tooltip = 'option range [10-100]', display = disp)
rpW = input.int(13, ' Profile Width %', minval = 10, maxval = 50, group =
otGR, tooltip = 'option range [10-50]', display = disp) / 100
vpLS = input.string('Auto', " Profile Text Size", options=['Auto', 'Tiny',
'Small'], group = otGR, display = disp)
vpHO = input.int(13, ' Profile Horizontal Offset', group = otGR, tooltip =
'option allows negative numbers as well, in case of a use the profiles will overlap
with the price chart', display = disp)
//---------------------------------------------------------------------------------
------------------------------------}
// User Defined Types
//---------------------------------------------------------------------------------
------------------------------------{
// @type bar properties with their values
//
// @field o (float) open price of the bar
// @field h (float) high price of the bar
// @field l (float) low price of the bar
// @field c (float) close price of the bar
// @field v (float) volume of the bar
// @field i (int) index of the bar
type bar
float o = open
float h = high
float l = low
float c = close
float v = volume
int i = bar_index
//---------------------------------------------------------------------------------
------------------------------------}
// Variables
//---------------------------------------------------------------------------------
------------------------------------{
bar b = bar.new()
rpVST = array.new_float(rpNR, 0.)
rpVSB = array.new_float(rpNR, 0.)
rpVSD = array.new_float(rpNR, 0.)
var dRP = array.new_box()
var pocPoints = array.new<chart.point>()
var polyline pocPolyline = na
var polyline spPolyline = na
var color llC = na
var color lsC = na
//---------------------------------------------------------------------------------
------------------------------------}
// Functions/Methods
//---------------------------------------------------------------------------------
------------------------------------{
// @function creates new label object and updates existing label objects
//
// @param details in Pine Script™ language reference manual
//
// @returns none, updated visual objects (labels)
f_drawLabelX(_x, _y, _text, _style, _textcolor, _size, _tooltip) =>
var lb = label.new(_x, _y, _text, xloc.bar_index, yloc.price, color(na),
_style, _textcolor, _size, text.align_left, _tooltip)
lb.set_xy(_x, _y)
lb.set_text(_text)
lb.set_tooltip(_tooltip)
lb.set_textcolor(_textcolor)
// @function This function converts string to enumerated size
//
// @param _t [string] custom string
//
// @returns [string] enumerated size
f_gTS(_t) =>
switch _t
'Tiny' => size.tiny
'Small' => size.small
'Normal' => size.normal
'Auto' => size.auto
//---------------------------------------------------------------------------------
------------------------------------}
// Calculations
//---------------------------------------------------------------------------------
------------------------------------{
bull = spPTY == spPT1 ? b.c > b.o : (b.c - b.l) > (b.h - b.c)
nzV = nz(b.v)
rpS = f_gTS(rpLS)
vpS = f_gTS(vpLS)
var float pLST = na
var float pHST = na
if b.i == last_bar_index - rpLN
pLST := b.l
pHST := b.h
else if b.i > last_bar_index - rpLN
pLST := math.min(b.l, pLST)
pHST := math.max(b.h, pHST)
pSTP = (pHST - pLST) / rpNR
if barstate.islast and not na(nzV) and not timeframe.isseconds and rpLN > 0 and
pSTP > 0 and nzV > 0
if dRP.size() > 0
for i = 0 to dRP.size() - 1
box.delete(dRP.shift())
if pocPoints.size() > 0
pocPoints.clear()
a_allPolylines = polyline.all
if array.size(a_allPolylines) > 0
for i = 0 to array.size(a_allPolylines) - 1
polyline.delete(a_allPolylines.get(i))
for bI = rpLN to 0
l = 0
for pLL = pLST to pHST - pSTP by pSTP
if b.h[bI] >= pLL and b.l[bI] < pLL + pSTP
vPOR = if b.l[bI] >= pLL and b.h[bI] > pLL + pSTP
(pLL + pSTP - b.l[bI]) / (b.h[bI] - b.l[bI])
else if b.h[bI] <= pLL + pSTP and b.l[bI] < pLL
(b.h[bI] - pLL) / (b.h[bI] - b.l[bI])
else if (b.l[bI] >= pLL and b.h[bI] <= pLL + pSTP)
1
else
pSTP / (b.h[bI] - b.l[bI])
if vpSRC == 'Money Flow'
rpVST.set(l, rpVST.get(l) + nzV[bI] * vPOR * (pLST + (l + .5) *
pSTP) )
else
rpVST.set(l, rpVST.get(l) + nzV[bI] * vPOR )
if bull[bI] and spSH
if vpSRC == 'Money Flow'
rpVSB.set(l, rpVSB.get(l) + nzV[bI] * vPOR * (pLST + (l
+ .5) * pSTP))
else
rpVSB.set(l, rpVSB.get(l) + nzV[bI] * vPOR )
l += 1
if rpPC == 'Developing'
if bI == rpLN
pocPoints.push(chart.point.from_index(b.i[bI], pLST +
(rpVST.indexof(rpVST.max()) + .5) * pSTP))
else
pocPoints.push(chart.point.from_index(b.i[bI], pLST +
(rpVST.indexof(rpVST.max()) + .5) * pSTP))
if rpPC == 'Developing'
pocPolyline := polyline.new(pocPoints, false, false, xloc.bar_index, vpHVC,
color(na), line.style_solid, 2)
if rpPC == 'Last(Zone)' or rpPC == 'Last(Line)'
pocPoints.push(chart.point.from_index(b.i[rpLN], pLST +
(rpVST.indexof(rpVST.max()) + .5) * pSTP))
pocPoints.push(chart.point.from_index(b.i, pLST +
(rpVST.indexof(rpVST.max()) + .5) * pSTP))
pocPolyline := polyline.new(pocPoints, false, false, xloc.bar_index, vpHVC,
color(na), rpPC == 'Last(Line)' ? line.style_solid : line.style_dotted, rpPC ==
'Last(Line)' ? 2 : 1)
for l = 0 to rpNR - 1
bbp = 2 * rpVSB.get(l) - rpVST.get(l)
rpVSD.set(l, rpVSD.get(l) + bbp * (bbp > 0 ? 1 : -1) )
if vpSH or spSH
sBI = b.i + (spSH ? rpLN * rpW : 7) + int(rpLN * rpW / 3)
dRP.push(box.new(sBI - 1 + vpHO, pLST + (l + .1) * pSTP, sBI - int(rpLN
* rpW / 3) + 1 + vpHO, pLST + (l + .9) * pSTP, #2962ff80, bgcolor = #2962ff10,
text = str.tostring(pLST + (l + .5) * pSTP,
format.mintick), text_color = chart.fg_color, text_size = vpS ))
if rpBG
dRP.push(box.new(b.i - rpLN, pLST, b.i, pHST, rpBGC, bgcolor = rpBGC ))
if rpPL
f_drawLabelX(b.i, pHST, str.tostring(pHST, format.mintick),
label.style_label_down, rpPLC, rpS,
'Profile High - ' + str.tostring(pHST, format.mintick) + '\n
%' + str.tostring((pHST - pLST) / pLST * 100, '#.##') + ' higher than the Profile
Low\n\n' +
'Total ' + (vpSRC == 'Volume' ? 'Volume : ' : 'Money Flow (' +
syminfo.currency + ') : ') + str.tostring(rpVST.sum(), format.volume) +
'\nNumber of bars : ' + str.tostring(rpLN + 1))
f_drawLabelX(b.i, pLST, str.tostring(pLST, format.mintick),
label.style_label_up , rpPLC, rpS,
'Profile Low - ' + str.tostring(pLST, format.mintick) + '\n
%' + str.tostring((pHST - pLST) / pHST * 100, '#.##') + ' lower than the Profile
High\n\n' +
'Total ' + (vpSRC == 'Volume' ? 'Volume : ' : 'Money Flow (' +
syminfo.currency + ') : ') + str.tostring(rpVST.sum(), format.volume) +
'\nNumber of bars : ' + str.tostring(rpLN + 1))
for l = 0 to rpNR - 1
if dRP.size() < 500
vtLV = rpVST.get(l)
vtMX = rpVST.max()
LpM = vtLV / vtMX
vdMX = rpVSD.max()
DpM = rpVSD.get(l) / vdMX
llC := LpM > vpHVT ? color.from_gradient(LpM, vpHVT, 1, vpAVC, vpHVC) :
color.from_gradient(LpM, 0, vpLVT, vpLVC, vpAVC)
bbp = 2 * rpVSB.get(l) - vtLV
lsC := bbp > 0 ? color.from_gradient(DpM, 0, .7, color.new(spBLC, 70 +
int(hmTR / 4)), color.new(spBLC, 30 + int(hmTR / 4))) :
color.from_gradient(DpM, 0, .7, color.new(spBRC, 70 +
int(hmTR / 4)), color.new(spBRC, 30 + int(hmTR / 4)))
if rpPC == 'Last(Zone)' and LpM == 1
dRP.push(box.new(b.i[rpLN], pLST + (rpVST.indexof(vtMX) + .0) *
pSTP, b.i, pLST + (rpVST.indexof(vtMX) + 1.) * pSTP, vpHVC, bgcolor =
color.new(vpHVC, 73) ))
if vaSH and LpM > vaTH and LpM < 1
dRP.push(box.new(b.i[rpLN], pLST + (l + .0) * pSTP, b.i, pLST + (l
+ 1.) * pSTP, color(na), bgcolor = vaC ))
if vaSH and rpPC != 'Last(Zone)' and LpM == 1
dRP.push(box.new(b.i[rpLN], pLST + (l + .0) * pSTP, b.i, pLST + (l
+ 1.) * pSTP, color(na), bgcolor = vaC ))
if spPC and DpM == 1
spPolyline :=
polyline.new(array.from(chart.point.from_index(b.i[rpLN], pLST +
(rpVSD.indexof(vdMX) + .5) * pSTP), chart.point.from_index(b.i, pLST +
(rpVSD.indexof(vdMX) + .5) * pSTP)), false, false, xloc.bar_index, lsC, color(na),
line.style_dotted, 1)
dRP.push(box.new(b.i[rpLN], pLST + (rpVSD.indexof(vdMX) + .0) *
pSTP, b.i, pLST + (rpVSD.indexof(vdMX) + 1.) * pSTP, lsC, bgcolor = color.new(lsC,
73) ))
if vpSH
sBI = b.i + (spSH ? rpLN * rpW : 7) + int(rpLN * rpW / 3)
eBI = sBI + int(LpM * rpLN * rpW)
dRP.push(box.new(sBI + vpHO, pLST + (l + .1) * pSTP, eBI + vpHO,
pLST + (l + .9) * pSTP, llC, bgcolor = llC,
text = str.tostring(vpSRC == 'Money Flow' ?
array.get(rpVST, l) : array.get(rpVST, l) * (pLST + (l + .5) * pSTP),
format.volume) + ' ' +
syminfo.currency + ' (' +
str.tostring(math.abs(vtLV / rpVST.sum() * 100), '#.##') + '%)',
text_halign = text.align_left, text_color =
chart.fg_color, text_size = vpS ))
if spSH
sBI = b.i + rpLN * rpW
eBI = sBI - int(DpM * rpLN * rpW)
dRP.push(box.new(sBI + vpHO, pLST + (l + .1) * pSTP, eBI + vpHO,
pLST + (l + .9) * pSTP, lsC, bgcolor = lsC,
text = str.tostring(bbp, format.volume ) + (vpSRC
== 'Money Flow' ? ' ' + syminfo.currency : '') +
' (' + str.tostring(math.abs(bbp / vtLV * 100),
'#.##') + '%)',
text_halign = text.align_right, text_color =
chart.fg_color, text_size = vpS ))
if hmSH
dRP.push(box.new(b.i[rpLN], pLST + (l + .0) * pSTP, b.i, pLST + (l
+ 1.) * pSTP, hmSRC == hmSO1 ? color.new(llC, hmTR) : lsC, bgcolor = hmSRC == hmSO1
? color.new(llC, hmTR) : lsC))
//---------------------------------------------------------------------------------
------------------------------------}//
//
//
//
///////////////////////////////////
// Input parameters
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 the market is. 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.')
// Colors
GREEN = color.rgb(29, 255, 40)
RED = color.rgb(255, 0, 0)
TRANSPARENT = color.rgb(0, 0, 0, 100)
// Cosmetic inputs
label_size = input.string('normal', 'Label Size', options=['huge', 'large',
'normal', 'small', 'tiny'], group='Cosmetic')
label_style = input.string('text bubble', 'Label Style', options=['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')
// Calculation of technical indicators
stable_candle = math.abs(close - open) / ta.tr(true) > candle_stability_index_param
rsi = ta.rsi(close, 14)
bullish_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]
bulla = bullish_engulfing and stable_candle and rsi_below and decrease_over and
barstate.isconfirmed
bearish_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]
beara = bearish_engulfing and stable_candle and rsi_above and increase_over and
barstate.isconfirmed
var last_signal = ''
if bulla and (disable_repeating_signals_param ? (last_signal != 'buy' ? true :
na) : true)
if label_style == 'text bubble'
label.new(bar_index, 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(bar_index, 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(bar_index, low, 'BUY', yloc=yloc.belowbar, color=buy_label_color,
style=label.style_arrowup, textcolor=TRANSPARENT, size=label_size)
last_signal := 'buy'
if beara and (disable_repeating_signals_param ? (last_signal != 'sell' ? true : na)
: true)
if label_style == 'text bubble'
label.new(bar_index, 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(bar_index, 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(bar_index, high, 'SELL', yloc=yloc.abovebar,
color=sell_label_color, style=label.style_arrowdown, textcolor=TRANSPARENT,
size=label_size)
last_signal := 'sell'
// Alert conditions
alertcondition(bulla, 'BUY Signals', 'New signal: BUY')
alertcondition(beara, 'SELL Signals', 'New signal: SELL')
/////////////////////////////////////////
n=bar_index
//------------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------{
tick = input.string ('LTF' , 'Data from: ', options= [ 'Ticks' , 'LTF'
] )
res = input.timeframe( '1'
, tooltip= "Data from: 'LTF'\nAuto: 'Disabled'" )
auto = input.bool ( true , '' , inline='auto'
)
mlt = input.int ( 1500 , ' Auto ' , inline='auto'
, tooltip="current TF divided by x\n\nData from: 'LTF'\nAuto: 'Enabled'")
prem = input.bool ( false , 'Premium' , tooltip= 'Premium Plan or
higher')
colUp = input.color (#089981 , 'Up ' , inline='u', group='Intrabar
Delta')
colUp_ = input.color (#f23645 , 'Up - ' , inline='u', group='Intrabar
Delta', tooltip= 'Up -\n-> bullish candle and - Delta' )
colDn = input.color (#f23645 , 'Down' , inline='d', group='Intrabar
Delta')
colDn_ = input.color (#089981 , 'Down +' , inline='d', group='Intrabar
Delta', tooltip='Down +\n-> bearish candle and + Delta')
option = input.string ('full bar', 'Display' , options= ['half bar', 'full
bar'] )
dot = input.bool ( false , 'Show Previous Max Volume
Price' )
showTab= input.bool ( true , 'Show TF' , group= 'Table'
)
tabCol = input.color (#b2b5beaa , 'Text Color' , group= 'Table'
)
sizeT = input.string (size.tiny , 'Size Table' , group= 'Table'
, options = [size.tiny, size.small, size.normal, size.large])
showD = input.bool ( false ,'Show details', group= 'Details'
)
INV = color.new(na,na)
CFG = chart.fg_color
isTick = tick =='Ticks'
isLTF = tick =='LTF'
//-----------------------------------------------------------------------------}
//UDT
//-----------------------------------------------------------------------------{
type bin
varip float p
varip float v
//-----------------------------------------------------------------------------}
//Variables
//-----------------------------------------------------------------------------{
varip float volBl = na
varip float volBr = na
varip float volNt = na
varip bin maxBl = bin.new(na, 0)
varip bin maxBr = bin.new(na, 0)
varip float vl = na
varip float cl = na
varip float dfP = na
varip float dfV = na
varip float TdfV = na
varip bool ticksAvailable = false
var table tab = na
//-----------------------------------------------------------------------------}
//Execution
//-----------------------------------------------------------------------------{
//Ticks
if isTick
if barstate.isnew
maxBl.v := 0, maxBr.v := 0
cl := open , dfP := 0 // "open"
vl := volume, dfV := 0, TdfV := 0 // "volume" at first tick
volBl := 0 , volBr := 0, volNt := 0 // dfV
else
dfP := close - cl
dfV := volume - vl
switch
dfP > 0 =>
volBl += dfV, TdfV += dfV
if dfV > maxBl.v
maxBl.v := dfV, maxBl.p := close
dfP < 0 =>
volBr += dfV, TdfV += dfV
if dfV > maxBr.v
maxBr.v := dfV, maxBr.p := close
cl := close
vl := volume
//LTF
tfS = timeframe.in_seconds( res )
tfC = timeframe.in_seconds(timeframe.period)
rs = auto ? tfC / mlt : tfS
rs := prem ? rs : math.max(60, rs)
res := timeframe.from_seconds(math.min(tfC, rs))
[bV, sV, nV, tV, aCl] = request.security_lower_tf(
syminfo.tickerid, res ,
[
close > open ? volume : 0
, close < open ? volume : 0
, close == open ? volume : 0
, volume
, close
] )
vSize = tV.size()
//Highest volume when price movement (neutral volume not included)
float maxV = na, float bVmax = na , float sVmax = na
if isLTF
bVmax := bV.max()
sVmax := sV.max()
indices = (bVmax > sVmax ? bV : sV).sort_indices(order.descending)
maxV := indices.size() > 0 ? aCl.get(indices.first()) : na
else
if maxBl.v != 0 or maxBr.v != 0
maxV := maxBl.v > maxBr.v ? maxBl.p : maxBr.p
// start Tick data
if not ticksAvailable and volBl > 0
ticksAvailable := true
isAllowed = isTick ? ticksAvailable : tV.size() > 0
if isAllowed and not isAllowed[1]
line.new(n, close, n, close + syminfo.mintick, color=color.silver,
style=line.style_dotted, extend=extend.both)
ltf_Vup = bV.sum()
ltf_Vdn = sV.sum()
bullaV = isTick ? volBl : ltf_Vup
bearaV = isTick ? volBr : ltf_Vdn
abs = math.abs(open - close)
min = math.min(open , close)
max = math.max(open , close)
avg = math.avg(open , close)
vol = bullaV + bearaV
delta = bullaV - bearaV
norm = delta / volume
aNorm = math.abs(norm)
pos = norm >= 0
float base = na
float value = na
value := option == 'half bar' ? avg + norm*abs/2 : pos ? min + aNorm*abs : max -
aNorm*abs
base := option == 'half bar' ? avg : pos ? min : max
css = close > open ? colUp : close < open ? colDn : CFG
cssD = color.new(norm > 0 ? close > open ? colUp : colDn_ : close < open ? colDn
: colUp_, 50)
//-----------------------------------------------------------------------------}
//Plot
//-----------------------------------------------------------------------------{
barcolor(INV) // use 'Bar's style' "Bars"
plotcandle(base, base, value, value, color = cssD, wickcolor = na , bordercolor =
na , display = display.all - display.status_line)
plotcandle(open, high, low , close, color = na , wickcolor = css, bordercolor =
css , display = display.all - display.status_line)
plotcandle(maxV, maxV, maxV , maxV , color = CFG , wickcolor = na , bordercolor =
CFG , display = display.all - display.status_line)
plot (dot ? maxV : na , color = CFG , style=plot.style_circles ,
offset=1, display = display.all - display.status_line)
plot (bullaV ,
display = display.data_window)
plot (bearaV ,
display = display.data_window)
//-----------------------------------------------------------------------------}
//Details
//-----------------------------------------------------------------------------{
volu = str.tostring(vol , format.volume )
delt = str.tostring(delta , format.volume )
perc = str.tostring(norm * 100, format.percent)
if isAllowed and showD
label.new(
n
, high
, color=INV
, textcolor=CFG
, size=size.small
, text=str.format(
"Volume: {0}\nDelta: {1}\n%: {2}"
, volu , delt, perc)
)
//-----------------------------------------------------------------------------}
//Table
//-----------------------------------------------------------------------------{
if showTab and isLTF
if barstate.isfirst
tab := table.new(position.top_right, 1, 1
, bgcolor=INV
)
if barstate.islast
tab.cell(0, 0, res, text_color=tabCol)
//-----------------------------------------------------------------------------}
//------------------------------------------------------------------------------
//Settings
//-----------------------------------------------------------------------------{
length = input(21)
//Style
swinghCss = input(color.red, 'Swing High', group = 'Style')
swinglCss = input(color.teal, 'Swing Low', group = 'Style')
//-----------------------------------------------------------------------------}
//Descriptions
//-----------------------------------------------------------------------------{
hammer_ = "The hammer candlestick pattern is formed of a short body with a long
lower wick, and is found at the bottom of a downward trend."
+ "\n" + "\n A hammer shows that although there were selling pressures during the
day, ultimately a strong buying pressure drove the price back up."
ihammer_ = "The inverted hammer is a similar pattern than the hammer pattern. The
only difference being that the upper wick is long, while the lower wick is short."
+ "\n" + "\n It indicates a buying pressure, followed by a selling pressure that
was not strong enough to drive the market price down. The inverse hammer suggests
that buyers will soon have control of the market."
bulleng_ = "The bullish engulfing pattern is formed of two candlesticks. The first
candle is a short red body that is completely engulfed by a larger green candle"
+ "\n" + "\n Though the second day opens lower than the first, the bullish market
pushes the price up, culminating in an obvious win for buyers"
hanging_ = "The hanging man is the bearish equivalent of a hammer; it has the same
shape but forms at the end of an uptrend."
+ "\n" + "It indicates that there was a significant sell-off during the day, but
that buyers were able to push the price up again. The large sell-off is often seen
as an indication that the bulls are losing control of the market."
shooting_ = "The shooting star is the same shape as the inverted hammer, but is
formed in an uptrend: it has a small lower body, and a long upper wick."
+ "\n" + "Usually, the market will gap slightly higher on opening and rally to an
intra-day high before closing at a price just above the open like a star falling to
the ground."
beareng_ = "A bearish engulfing pattern occurs at the end of an uptrend. The first
candle has a small green body that is engulfed by a subsequent long red candle."
+ "\n" + "It signifies a peak or slowdown of price movement, and is a sign of an
impending market downturn. The lower the second candle goes, the more significant
the trend is likely to be."
//-----------------------------------------------------------------------------
overlay = true
max_lines_count = 500
max_labels_count = 500
max_boxes_count = 500
//------------------------------------------------------------------------------
//Settings
//-----------------------------------------------------------------------------{
length1 = input(14, 'Pivot Lookback')
area = input.string('Wick Extremity', 'Swing Area', options = ['Wick Extremity',
'Full Range'])
intraPrecision = input(false, 'Intrabar Precision', inline = 'intrabar')
intrabarTf = input.timeframe('1', '' , inline = 'intrabar')
filterOptions = input.string('Count', 'Filter Areas By', options = ['Count',
'Volume'], inline = 'filter')
filterValue = input.float(0, '' ,
inline = 'filter')
//Style
showTop = input(true, 'Swing High' , inline = 'top', group =
'Style')
topCss = input(color.red, '' , inline = 'top', group =
'Style')
topAreaCss = input(color.new(color.red, 50), 'Area', inline = 'top', group =
'Style')
showBtm = input(true, 'Swing Low' , inline = 'btm', group =
'Style')
btmCss = input(color.teal, '' , inline = 'btm', group =
'Style')
btmAreaCss = input(color.new(color.teal, 50), 'Area', inline = 'btm', group =
'Style')
labelSize = input.string('Tiny', 'Labels Size', options = ['Tiny', 'Small',
'Normal'], group = 'Style')
//-----------------------------------------------------------------------------}
//Functions
//-----------------------------------------------------------------------------{
get_data()=> [high, low, volume]
[h, l, v] = request.security_lower_tf(syminfo.tickerid, intrabarTf, get_data())
get_counts(condition, top, btm)=>
var count = 0
var vol = 0.
if condition
count := 0
vol := 0.
else
if intraPrecision
if n > length1
if array.size(v[length1]) > 0
for [index, element] in v[length1]
vol += array.get(l[length1], index) < top and
array.get(h[length1], index) > btm ? element : 0
else
vol += low[length1] < top and high[length1] > btm ? volume[length1] : 0
count += low[length1] < top and high[length1] > btm ? 1 : 0
[count, vol]
set_label(count, vol, x, y, css, lbl_style)=>
var label lbl = na
var label_size = switch labelSize
'Tiny' => size.tiny
'Small' => size.small
'Normal' => size.normal
target = switch filterOptions
'Count' => count
'Volume' => vol
if ta.crossover(target, filterValue)
lbl := label.new(x, y, str.tostring(vol, format.volume)
, style = lbl_style
, size = label_size
, color = #00000000
, textcolor = css)
if target > filterValue
label.set_text(lbl, str.tostring(vol, format.volume))
set_level(condition, crossed, value, count, vol, css)=>
var line lvl = na
target = switch filterOptions
'Count' => count
'Volume' => vol
if condition
if target[1] < filterValue[1]
line.delete(lvl[1])
else if not crossed[1]
line.set_x2(lvl, n - length1)
lvl := line.new(n - length1, value, n, value
, color = na)
if not crossed[1]
line.set_x2(lvl, n+3)
if crossed and not crossed[1]
line.set_x2(lvl, n)
line.set_style(lvl, line.style_dashed)
if target > filterValue
line.set_color(lvl, css)
set_zone(condition, x, top, btm, count, vol, css)=>
var box bx = na
target = switch filterOptions
'Count' => count
'Volume' => vol
if ta.crossover(target, filterValue)
bx := box.new(x, top, x + count, btm
, border_color = na
, bgcolor = css)
if target > filterValue
box.set_right(bx, x + count)
//-----------------------------------------------------------------------------}
//Global variables
//-----------------------------------------------------------------------------{
//Pivot high
var float ph_top = na
var float ph_btm = na
var bool ph_crossed = na
var ph_x1 = 0
var box ph_bx = box.new(na,na,na,na
, bgcolor = color.new(topAreaCss, 80)
, border_color = na)
//Pivot low
var float pl_top = na
var float pl_btm = na
var bool pl_crossed = na
var pl_x1 = 0
var box pl_bx = box.new(na,na,na,na
, bgcolor = color.new(btmAreaCss, 80)
, border_color = na)
//-----------------------------------------------------------------------------}
//Display pivot high levels/blocks
//-----------------------------------------------------------------------------{
ph = ta.pivothigh(length1, length1)
//Get ph counts
[ph_count, ph_vol] = get_counts(ph, ph_top, ph_btm)
//Set ph area and level
if ph and showTop
ph_top := high[length1]
ph_btm := switch area
'Wick Extremity' => math.max(close[length1], open[length1])
'Full Range' => low[length1]
ph_x1 := n - length1
ph_crossed := false
box.set_lefttop(ph_bx, ph_x1, ph_top)
box.set_rightbottom(ph_bx, ph_x1, ph_btm)
else
ph_crossed := close > ph_top ? true : ph_crossed
if ph_crossed
box.set_right(ph_bx, ph_x1)
else
box.set_right(ph_bx, n+3)
if showTop
//Set ph zone
set_zone(ph, ph_x1, ph_top, ph_btm, ph_count, ph_vol, topAreaCss)
//Set ph level
set_level(ph, ph_crossed, ph_top, ph_count, ph_vol, topCss)
//Set ph label
set_label(ph_count, ph_vol, ph_x1, ph_top, topCss, label.style_label_down)
//-----------------------------------------------------------------------------}
//Display pivot low levels/blocks
//-----------------------------------------------------------------------------{
pl = ta.pivotlow(length1, length1)
//Get pl counts
[pl_count, pl_vol] = get_counts(pl, pl_top, pl_btm)
//Set pl area and level
if pl and showBtm
pl_top := switch area
'Wick Extremity' => math.min(close[length1], open[length1])
'Full Range' => high[length1]
pl_btm := low[length1]
pl_x1 := n - length1
pl_crossed := false
box.set_lefttop(pl_bx, pl_x1, pl_top)
box.set_rightbottom(pl_bx, pl_x1, pl_btm)
else
pl_crossed := close < pl_btm ? true : pl_crossed
if pl_crossed
box.set_right(pl_bx, pl_x1)
else
box.set_right(pl_bx, n+3)
if showBtm
//Set pl zone
set_zone(pl, pl_x1, pl_top, pl_btm, pl_count, pl_vol, btmAreaCss)
//Set pl level
set_level(pl, pl_crossed, pl_btm, pl_count, pl_vol, btmCss)
//Set pl labels
set_label(pl_count, pl_vol, pl_x1, pl_btm, btmCss, label.style_label_up)
//-----------------------------------------------------------------------------}
//////////
//CONSTANTS & STRINGS & INPUTS
//---------------------------------------------------------------------------------
------------------------------------{
BULLISH_LEG = 1
BEARISH_LEG = 0
BULLISH = +1
BEARISH = -1
BLUE = #2157f3
GRAY = #878b94
MONO_BULLISH = #b2b5be
MONO_BEARISH = #5d606b
HISTORICAL = 'Historical'
PRESENT = 'Present'
COLORED = 'Colored'
MONOCHROME = 'Monochrome'
ALL = 'All'
BOS = 'BOS'
CHOCH = 'CHoCH'
TINY = size.tiny
SMALL = size.small
NORMAL = size.normal
ATR = 'Atr'
RANGE = 'Cumulative Mean Range'
CLOSE = 'Close'
HIGHLOW = 'High/Low'
SOLID = '⎯⎯⎯'
DASHED = '----'
DOTTED = '····'
SMART_GROUP = 'Smart Money Concepts'
INTERNAL_GROUP = 'Real Time Internal Structure'
SWING_GROUP = 'Real Time Swing Structure'
BLOCKS_GROUP = 'Order Blocks'
EQUAL_GROUP = 'EQH/EQL'
GAPS_GROUP = 'Fair Value Gaps'
LEVELS_GROUP = 'Highs & Lows MTF'
ZONES_GROUP = 'Premium & Discount Zones'
modeTooltip = 'Allows to display historical Structure or only
the recent ones'
styleTooltip = 'Indicator color theme'
showTrendTooltip = 'Display additional candles with a color
reflecting the current trend detected by structure'
showInternalsTooltip = 'Display internal market structure'
internalFilterConfluenceTooltip = 'Filter non significant internal structure
breakouts'
showStructureTooltip = 'Display swing market Structure'
showSwingsTooltip = 'Display swing point as labels on the chart'
showHighLowSwingsTooltip = 'Highlight most recent strong and weak high/low
points on the chart'
showInternalOrderBlocksTooltip = 'Display internal order blocks on the chart\n\
nNumber of internal order blocks to display on the chart'
showSwingOrderBlocksTooltip = 'Display swing order blocks on the chart\n\
nNumber of internal swing blocks to display on the chart'
orderBlockFilterTooltip = 'Method used to filter out volatile order
blocks \n\nIt is recommended to use the cumulative mean range method when a low
amount of data is available'
orderBlockMitigationTooltip = 'Select what values to use for order block
mitigation'
showEqualHighsLowsTooltip = 'Display equal highs and equal lows on the chart'
equalHighsLowsLengthTooltip = 'Number of bars used to confirm equal highs and
equal lows'
equalHighsLowsThresholdTooltip = 'Sensitivity threshold in a range (0, 1) used for
the detection of equal highs & lows\n\nLower values will return fewer but more
pertinent results'
showFairValueGapsTooltip = 'Display fair values gaps on the chart'
fairValueGapsThresholdTooltip = 'Filter out non significant fair value gaps'
fairValueGapsTimeframeTooltip = 'Fair value gaps timeframe'
fairValueGapsExtendTooltip = 'Determine how many bars to extend the Fair Value
Gap boxes on chart'
showPremiumDiscountZonesTooltip = 'Display premium, discount, and equilibrium zones
on chart'
modeInput = input.string( HISTORICAL, 'Mode',
group = SMART_GROUP, tooltip = modeTooltip, options = [HISTORICAL, PRESENT])
styleInput = input.string( COLORED, 'Style',
group = SMART_GROUP, tooltip = styleTooltip,options = [COLORED, MONOCHROME])
showTrendInput = input( false, 'Color Candles',
group = SMART_GROUP, tooltip = showTrendTooltip)
showInternalsInput = input( true, 'Show Internal
Structure', group = INTERNAL_GROUP, tooltip = showInternalsTooltip)
showInternalBullInput = input.string( ALL, 'Bullish Structure',
group = INTERNAL_GROUP, inline = 'ibull', options = [ALL,BOS,CHOCH])
internalBullColorInput = input( GREEN, '',
group = INTERNAL_GROUP, inline = 'ibull')
showInternalBearInput = input.string( ALL, 'Bearish Structure' ,
group = INTERNAL_GROUP, inline = 'ibear', options = [ALL,BOS,CHOCH])
internalBearColorInput = input( RED, '',
group = INTERNAL_GROUP, inline = 'ibear')
internalFilterConfluenceInput = input( false, 'Confluence Filter',
group = INTERNAL_GROUP, tooltip = internalFilterConfluenceTooltip)
internalStructureSize = input.string( TINY, 'Internal Label Size',
group = INTERNAL_GROUP, options = [TINY,SMALL,NORMAL])
showStructureInput = input( true, 'Show Swing Structure',
group = SWING_GROUP, tooltip = showStructureTooltip)
showSwingBullInput = input.string( ALL, 'Bullish Structure',
group = SWING_GROUP, inline = 'bull', options = [ALL,BOS,CHOCH])
swingBullColorInput = input( GREEN, '',
group = SWING_GROUP, inline = 'bull')
showSwingBearInput = input.string( ALL, 'Bearish Structure',
group = SWING_GROUP, inline = 'bear', options = [ALL,BOS,CHOCH])
swingBearColorInput = input( RED, '',
group = SWING_GROUP, inline = 'bear')
swingStructureSize = input.string( SMALL, 'Swing Label Size',
group = SWING_GROUP, options = [TINY,SMALL,NORMAL])
showSwingsInput = input( false, 'Show Swings Points',
group = SWING_GROUP, tooltip = showSwingsTooltip,inline = 'swings')
swingsLengthInput = input.int( 50, '',
group = SWING_GROUP, minval = 10, inline = 'swings')
showHighLowSwingsInput = input( true, 'Show Strong/Weak
High/Low',group = SWING_GROUP, tooltip = showHighLowSwingsTooltip)
showInternalOrderBlocksInput = input( true, 'Internal Order Blocks'
, group = BLOCKS_GROUP, tooltip = showInternalOrderBlocksTooltip, inline =
'iob')
internalOrderBlocksSizeInput = input.int( 5, '',
group = BLOCKS_GROUP, minval = 1, maxval = 20, inline = 'iob')
showSwingOrderBlocksInput = input( false, 'Swing Order Blocks',
group = BLOCKS_GROUP, tooltip = showSwingOrderBlocksTooltip, inline = 'ob')
swingOrderBlocksSizeInput = input.int( 5, '',
group = BLOCKS_GROUP, minval = 1, maxval = 20, inline = 'ob')
orderBlockFilterInput = input.string( 'Atr', 'Order Block Filter',
group = BLOCKS_GROUP, tooltip = orderBlockFilterTooltip, options = [ATR,
RANGE])
orderBlockMitigationInput = input.string( HIGHLOW, 'Order Block
Mitigation', group = BLOCKS_GROUP, tooltip = orderBlockMitigationTooltip,
options = [CLOSE,HIGHLOW])
internalBullishOrderBlockColor = input.color(color.new(#3179f5, 80), 'Internal
Bullish OB', group = BLOCKS_GROUP)
internalBearishOrderBlockColor = input.color(color.new(#f77c80, 80), 'Internal
Bearish OB', group = BLOCKS_GROUP)
swingBullishOrderBlockColor = input.color(color.new(#1848cc, 80), 'Bullish OB',
group = BLOCKS_GROUP)
swingBearishOrderBlockColor = input.color(color.new(#b22833, 80), 'Bearish OB',
group = BLOCKS_GROUP)
showEqualHighsLowsInput = input( true, 'Equal High/Low',
group = EQUAL_GROUP, tooltip = showEqualHighsLowsTooltip)
equalHighsLowsLengthInput = input.int( 3, 'Bars Confirmation',
group = EQUAL_GROUP, tooltip = equalHighsLowsLengthTooltip, minval = 1)
equalHighsLowsThresholdInput = input.float( 0.1, 'Threshold',
group = EQUAL_GROUP, tooltip = equalHighsLowsThresholdTooltip, minval = 0,
maxval = 0.5, step = 0.1)
equalHighsLowsSizeInput = input.string( TINY, 'Label Size',
group = EQUAL_GROUP, options = [TINY,SMALL,NORMAL])
showFairValueGapsInput = input( false, 'Fair Value Gaps',
group = GAPS_GROUP, tooltip = showFairValueGapsTooltip)
fairValueGapsThresholdInput = input( true, 'Auto Threshold',
group = GAPS_GROUP, tooltip = fairValueGapsThresholdTooltip)
fairValueGapsTimeframeInput = input.timeframe('', 'Timeframe',
group = GAPS_GROUP, tooltip = fairValueGapsTimeframeTooltip)
fairValueGapsBullColorInput = input.color(color.new(#00ff68, 70), 'Bullish FVG'
, group = GAPS_GROUP)
fairValueGapsBearColorInput = input.color(color.new(#ff0008, 70), 'Bearish FVG'
, group = GAPS_GROUP)
fairValueGapsExtendInput = input.int( 1, 'Extend FVG',
group = GAPS_GROUP, tooltip = fairValueGapsExtendTooltip, minval = 0)
showDailyLevelsInput = input( false, 'Daily', group =
LEVELS_GROUP, inline = 'daily')
dailyLevelsStyleInput = input.string( SOLID, '', group =
LEVELS_GROUP, inline = 'daily', options = [SOLID,DASHED,DOTTED])
dailyLevelsColorInput = input( BLUE, '', group =
LEVELS_GROUP, inline = 'daily')
showWeeklyLevelsInput = input( false, 'Weekly', group =
LEVELS_GROUP, inline = 'weekly')
weeklyLevelsStyleInput = input.string( SOLID, '', group =
LEVELS_GROUP, inline = 'weekly', options = [SOLID,DASHED,DOTTED])
weeklyLevelsColorInput = input( BLUE, '', group =
LEVELS_GROUP, inline = 'weekly')
showMonthlyLevelsInput = input( false, 'Monthly', group =
LEVELS_GROUP, inline = 'monthly')
monthlyLevelsStyleInput = input.string( SOLID, '', group =
LEVELS_GROUP, inline = 'monthly', options = [SOLID,DASHED,DOTTED])
monthlyLevelsColorInput = input( BLUE, '', group =
LEVELS_GROUP, inline = 'monthly')
showPremiumDiscountZonesInput = input( false, 'Premium/Discount
Zones', group = ZONES_GROUP , tooltip = showPremiumDiscountZonesTooltip)
premiumZoneColorInput = input.color( RED, 'Premium Zone',
group = ZONES_GROUP)
equilibriumZoneColorInput = input.color( GRAY, 'Equilibrium Zone',
group = ZONES_GROUP)
discountZoneColorInput = input.color( GREEN, 'Discount Zone',
group = ZONES_GROUP)
//---------------------------------------------------------------------------------
------------------------------------}
//DATA STRUCTURES & VARIABLES
//---------------------------------------------------------------------------------
------------------------------------{
// @type UDT representing alerts as bool fields
// @field internalBullishBOS internal structure custom alert
// @field internalBearishBOS internal structure custom alert
// @field internalBullishCHoCH internal structure custom alert
// @field internalBearishCHoCH internal structure custom alert
// @field swingBullishBOS swing structure custom alert
// @field swingBearishBOS swing structure custom alert
// @field swingBullishCHoCH swing structure custom alert
// @field swingBearishCHoCH swing structure custom alert
// @field internalBullishOrderBlock internal order block custom alert
// @field internalBearishOrderBlock internal order block custom alert
// @field swingBullishOrderBlock swing order block custom alert
// @field swingBearishOrderBlock swing order block custom alert
// @field equalHighs equal high low custom alert
// @field equalLows equal high low custom alert
// @field bullishFairValueGap fair value gap custom alert
// @field bearishFairValueGap fair value gap custom alert
type alerts
bool internalBullishBOS = false
bool internalBearishBOS = false
bool internalBullishCHoCH = false
bool internalBearishCHoCH = false
bool swingBullishBOS = false
bool swingBearishBOS = false
bool swingBullishCHoCH = false
bool swingBearishCHoCH = false
bool internalBullishOrderBlock = false
bool internalBearishOrderBlock = false
bool swingBullishOrderBlock = false
bool swingBearishOrderBlock = false
bool equalHighs = false
bool equalLows = false
bool bullishFairValueGap = false
bool bearishFairValueGap = false
// @type UDT representing last swing extremes (top &
bottom)
// @field top last top swing price
// @field bottom last bottom swing price
// @field barTime last swing bar time
// @field barIndex last swing bar index
// @field lastTopTime last top swing time
// @field lastBottomTime last bottom swing time
type trailingExtremes
float top
float bottom
int barTime
int barIndex
int lastTopTime
int lastBottomTime
// @type UDT representing Fair Value Gaps
// @field top top price
// @field bottom bottom price
// @field bias bias (BULLISH or BEARISH)
// @field topBox top box
// @field bottomBox bottom box
type fairValueGap
float top
float bottom
int bias
box topBox
box bottomBox
// @type UDT representing trend bias
// @field bias BULLISH or BEARISH
type trend
int bias
// @type UDT representing Equal Highs Lows display
// @field l_ine displayed line
// @field l_abel displayed label
type equalDisplay
line l_ine = na
label l_abel = na
// @type UDT representing a pivot point (swing point)
// @field currentLevel current price level
// @field lastLevel last price level
// @field crossed true if price level is crossed
// @field barTime bar time
// @field barIndex bar index
type pivot
float currentLevel
float lastLevel
bool crossed
int barTime = time
int barIndex = bar_index
// @type UDT representing an order block
// @field barHigh bar high
// @field barLow bar low
// @field barTime bar time
// @field bias BULLISH or BEARISH
type orderBlock
float barHigh
float barLow
int barTime
int bias
// @variable current swing pivot high
var pivot swingHigh = pivot.new(na,na,false)
// @variable current swing pivot low
var pivot swingLow = pivot.new(na,na,false)
// @variable current internal pivot high
var pivot internalHigh = pivot.new(na,na,false)
// @variable current internal pivot low
var pivot internalLow = pivot.new(na,na,false)
// @variable current equal high pivot
var pivot equalHigh = pivot.new(na,na,false)
// @variable current equal low pivot
var pivot equalLow = pivot.new(na,na,false)
// @variable swing trend bias
var trend swingTrend = trend.new(0)
// @variable internal trend bias
var trend internalTrend = trend.new(0)
// @variable equal high display
var equalDisplay equalHighDisplay = equalDisplay.new()
// @variable equal low display
var equalDisplay equalLowDisplay = equalDisplay.new()
// @variable storage for fairValueGap UDTs
var array<fairValueGap> fairValueGaps = array.new<fairValueGap>()
// @variable storage for parsed highs
var array<float> parsedHighs = array.new<float>()
// @variable storage for parsed lows
var array<float> parsedLows = array.new<float>()
// @variable storage for raw highs
var array<float> highs = array.new<float>()
// @variable storage for raw lows
var array<float> lows = array.new<float>()
// @variable storage for bar time values
var array<int> times = array.new<int>()
// @variable last trailing swing high and low
var trailingExtremes trailing = trailingExtremes.new()
// @variable storage for orderBlock UDTs (swing
order blocks)
var array<orderBlock> swingOrderBlocks = array.new<orderBlock>()
// @variable storage for orderBlock UDTs (internal
order blocks)
var array<orderBlock> internalOrderBlocks = array.new<orderBlock>()
// @variable storage for swing order blocks boxes
var array<box> swingOrderBlocksBoxes = array.new<box>()
// @variable storage for internal order blocks boxes
var array<box> internalOrderBlocksBoxes = array.new<box>()
// @variable color for swing bullish structures
var swingBullishColor = styleInput == MONOCHROME ? MONO_BULLISH :
swingBullColorInput
// @variable color for swing bearish structures
var swingBearishColor = styleInput == MONOCHROME ? MONO_BEARISH :
swingBearColorInput
// @variable color for bullish fair value gaps
var fairValueGapBullishColor = styleInput == MONOCHROME ?
color.new(MONO_BULLISH,70) : fairValueGapsBullColorInput
// @variable color for bearish fair value gaps
var fairValueGapBearishColor = styleInput == MONOCHROME ?
color.new(MONO_BEARISH,70) : fairValueGapsBearColorInput
// @variable color for premium zone
var premiumZoneColor = styleInput == MONOCHROME ? MONO_BEARISH :
premiumZoneColorInput
// @variable color for discount zone
var discountZoneColor = styleInput == MONOCHROME ? MONO_BULLISH :
discountZoneColorInput
// @variable bar index on current script iteration
varip int currentBarIndex = bar_index
// @variable bar index on last script iteration
varip int lastBarIndex = bar_index
// @variable alerts in current bar
alerts currentAlerts = alerts.new()
// @variable time at start of chart
var initialTime = time
// we create the needed boxes for displaying order blocks at the first execution
if barstate.isfirst
if showSwingOrderBlocksInput
for index = 1 to swingOrderBlocksSizeInput
swingOrderBlocksBoxes.push(box.new(na,na,na,na,xloc =
xloc.bar_time,extend = extend.right))
if showInternalOrderBlocksInput
for index = 1 to internalOrderBlocksSizeInput
internalOrderBlocksBoxes.push(box.new(na,na,na,na,xloc =
xloc.bar_time,extend = extend.right))
// @variable source to use in bearish order blocks
mitigation
bearishOrderBlockMitigationSource = orderBlockMitigationInput == CLOSE ? close :
high
// @variable source to use in bullish order blocks
mitigation
bullishOrderBlockMitigationSource = orderBlockMitigationInput == CLOSE ? close :
low
// @variable default volatility measure
atrMeasure = ta.atr(200)
// @variable parsed volatility measure by user settings
volatilityMeasure = orderBlockFilterInput == ATR ? atrMeasure :
ta.cum(ta.tr)/bar_index
// @variable true if current bar is a high volatility bar
highVolatilityBar = (high - low) >= (2 * volatilityMeasure)
// @variable parsed high
parsedHigh = highVolatilityBar ? low : high
// @variable parsed low
parsedLow = highVolatilityBar ? high : low
// we store current values into the arrays at each bar
parsedHighs.push(parsedHigh)
parsedLows.push(parsedLow)
highs.push(high)
lows.push(low)
times.push(time)
//---------------------------------------------------------------------------------
------------------------------------}
//USER-DEFINED FUNCTIONS
//---------------------------------------------------------------------------------
------------------------------------{
// @function Get the value of the current leg, it can be 0 (bearish) or
1 (bullish)
// @returns int
leg(int size) =>
var leg = 0
newLegHigh = high[size] > ta.highest( size)
newLegLow = low[size] < ta.lowest( size)
if newLegHigh
leg := BEARISH_LEG
else if newLegLow
leg := BULLISH_LEG
leg
// @function Identify whether the current value is the start of a new
leg (swing)
// @param leg (int) Current leg value
// @returns bool
startOfNewLeg(int leg) => ta.change(leg) != 0
// @function Identify whether the current level is the start of a new
bearish leg (swing)
// @param leg (int) Current leg value
// @returns bool
startOfBearishLeg(int leg) => ta.change(leg) == -1
// @function Identify whether the current level is the start of a new
bullish leg (swing)
// @param leg (int) Current leg value
// @returns bool
startOfBullishLeg(int leg) => ta.change(leg) == +1
// @function create a new label
// @param labelTime bar time coordinate
// @param labelPrice price coordinate
// @param tag text to display
// @param labelColor text color
// @param labelStyle label style
// @returns label ID
drawLabel(int labelTime, float labelPrice, string tag, color labelColor, string
labelStyle) =>
var label l_abel = na
if modeInput == PRESENT
l_abel.delete()
l_abel :=
label.new(chart.point.new(labelTime,na,labelPrice),tag,xloc.bar_time,color=color(na
),textcolor=labelColor,style = labelStyle,size = size.small)
// @function create a new line and label representing an EQH or EQL
// @param p_ivot starting pivot
// @param level price level of current pivot
// @param size how many bars ago was the current pivot detected
// @param equalHigh true for EQH, false for EQL
// @returns label ID
drawEqualHighLow(pivot p_ivot, float level, int size, bool equalHigh) =>
equalDisplay e_qualDisplay = equalHigh ? equalHighDisplay : equalLowDisplay
string tag = 'EQL'
color equalColor = swingBullishColor
string labelStyle = label.style_label_up
if equalHigh
tag := 'EQH'
equalColor := swingBearishColor
labelStyle := label.style_label_down
if modeInput == PRESENT
line.delete( e_qualDisplay.l_ine)
label.delete( e_qualDisplay.l_abel)
e_qualDisplay.l_ine :=
line.new(chart.point.new(p_ivot.barTime,na,p_ivot.currentLevel),
chart.point.new(time[size],na,level), xloc = xloc.bar_time, color = equalColor,
style = line.style_dotted)
labelPosition = math.round(0.5*(p_ivot.barIndex + bar_index - size))
e_qualDisplay.l_abel := label.new(chart.point.new(na,labelPosition,level),
tag, xloc.bar_index, color = color(na), textcolor = equalColor, style = labelStyle,
size = equalHighsLowsSizeInput)
// @function store current structure and trailing swing points, and also
display swing points and equal highs/lows
// @param size (int) structure size
// @param equalHighLow (bool) true for displaying current highs/lows
// @param internal (bool) true for getting internal structures
// @returns label ID
getCurrentStructure(int size,bool equalHighLow = false, bool internal = false) =>
currentLeg = leg(size)
newPivot = startOfNewLeg(currentLeg)
pivotLow = startOfBullishLeg(currentLeg)
pivotHigh = startOfBearishLeg(currentLeg)
if newPivot
if pivotLow
pivot p_ivot = equalHighLow ? equalLow : internal ? internalLow :
swingLow
if equalHighLow and math.abs(p_ivot.currentLevel - low[size]) <
equalHighsLowsThresholdInput * atrMeasure
drawEqualHighLow(p_ivot, low[size], size, false)
p_ivot.lastLevel := p_ivot.currentLevel
p_ivot.currentLevel := low[size]
p_ivot.crossed := false
p_ivot.barTime := time[size]
p_ivot.barIndex := bar_index[size]
if not equalHighLow and not internal
trailing.bottom := p_ivot.currentLevel
trailing.barTime := p_ivot.barTime
trailing.barIndex := p_ivot.barIndex
trailing.lastBottomTime := p_ivot.barTime
if showSwingsInput and not internal and not equalHighLow
drawLabel(time[size], p_ivot.currentLevel, p_ivot.currentLevel <
p_ivot.lastLevel ? 'LL' : 'HL', swingBullishColor, label.style_label_up)
else
pivot p_ivot = equalHighLow ? equalHigh : internal ? internalHigh :
swingHigh
if equalHighLow and math.abs(p_ivot.currentLevel - high[size]) <
equalHighsLowsThresholdInput * atrMeasure
drawEqualHighLow(p_ivot,high[size],size,true)
p_ivot.lastLevel := p_ivot.currentLevel
p_ivot.currentLevel := high[size]
p_ivot.crossed := false
p_ivot.barTime := time[size]
p_ivot.barIndex := bar_index[size]
if not equalHighLow and not internal
trailing.top := p_ivot.currentLevel
trailing.barTime := p_ivot.barTime
trailing.barIndex := p_ivot.barIndex
trailing.lastTopTime := p_ivot.barTime
if showSwingsInput and not internal and not equalHighLow
drawLabel(time[size], p_ivot.currentLevel, p_ivot.currentLevel >
p_ivot.lastLevel ? 'HH' : 'LH', swingBearishColor, label.style_label_down)
// @function draw line and label representing a structure
// @param p_ivot base pivot point
// @param tag test to display
// @param structureColor base color
// @param lineStyle line style
// @param labelStyle label style
// @param labelSize text size
// @returns label ID
drawStructure(pivot p_ivot, string tag, color structureColor, string lineStyle,
string labelStyle, string labelSize) =>
var line l_ine = line.new(na,na,na,na,xloc = xloc.bar_time)
var label l_abel = label.new(na,na)
if modeInput == PRESENT
l_ine.delete()
l_abel.delete()
l_ine := line.new(chart.point.new(p_ivot.barTime,na,p_ivot.currentLevel),
chart.point.new(time,na,p_ivot.currentLevel), xloc.bar_time, color=structureColor,
style=lineStyle)
l_abel :=
label.new(chart.point.new(na,math.round(0.5*(p_ivot.barIndex+bar_index)),p_ivot.cur
rentLevel), tag, xloc.bar_index, color=color(na), textcolor=structureColor,
style=labelStyle, size = labelSize)
// @function delete order blocks
// @param internal true for internal order blocks
// @returns orderBlock ID
deleteOrderBlocks(bool internal = false) =>
array<orderBlock> orderBlocks = internal ? internalOrderBlocks :
swingOrderBlocks
for [index,eachOrderBlock] in orderBlocks
bool crossedOderBlock = false
if bearishOrderBlockMitigationSource > eachOrderBlock.barHigh and
eachOrderBlock.bias == BEARISH
crossedOderBlock := true
if internal
currentAlerts.internalBearishOrderBlock := true
else
currentAlerts.swingBearishOrderBlock := true
else if bullishOrderBlockMitigationSource < eachOrderBlock.barLow and
eachOrderBlock.bias == BULLISH
crossedOderBlock := true
if internal
currentAlerts.internalBullishOrderBlock := true
else
currentAlerts.swingBullishOrderBlock := true
if crossedOderBlock
orderBlocks.remove(index)
// @function fetch and store order blocks
// @param p_ivot base pivot point
// @param internal true for internal order blocks
// @param bias BULLISH or BEARISH
// @returns void
storeOrdeBlock(pivot p_ivot,bool internal = false,int bias) =>
if (not internal and showSwingOrderBlocksInput) or (internal and
showInternalOrderBlocksInput)
array<float> a_rray = na
int parsedIndex = na
if bias == BEARISH
a_rray := parsedHighs.slice(p_ivot.barIndex,bar_index)
parsedIndex := p_ivot.barIndex + a_rray.indexof(a_rray.max())
else
a_rray := parsedLows.slice(p_ivot.barIndex,bar_index)
parsedIndex := p_ivot.barIndex + a_rray.indexof(a_rray.min())
orderBlock o_rderBlock =
orderBlock.new(parsedHighs.get(parsedIndex), parsedLows.get(parsedIndex),
times.get(parsedIndex),bias)
array<orderBlock> orderBlocks = internal ? internalOrderBlocks :
swingOrderBlocks
if orderBlocks.size() >= 100
orderBlocks.pop()
orderBlocks.unshift(o_rderBlock)
// @function draw order blocks as boxes
// @param internal true for internal order blocks
// @returns void
drawOrderBlocks(bool internal = false) =>
array<orderBlock> orderBlocks = internal ? internalOrderBlocks :
swingOrderBlocks
orderBlocksSize = orderBlocks.size()
if orderBlocksSize > 0
maxOrderBlocks = internal ?
internalOrderBlocksSizeInput : swingOrderBlocksSizeInput
array<orderBlock> parsedOrdeBlocks = orderBlocks.slice(0,
math.min(maxOrderBlocks,orderBlocksSize))
array<box> b_oxes = internal ? internalOrderBlocksBoxes :
swingOrderBlocksBoxes
for [index,eachOrderBlock] in parsedOrdeBlocks
orderBlockColor = styleInput == MONOCHROME ? (eachOrderBlock.bias ==
BEARISH ? color.new(MONO_BEARISH,80) : color.new(MONO_BULLISH,80)) : internal ?
(eachOrderBlock.bias == BEARISH ? internalBearishOrderBlockColor :
internalBullishOrderBlockColor) : (eachOrderBlock.bias == BEARISH ?
swingBearishOrderBlockColor : swingBullishOrderBlockColor)
box b_ox = b_oxes.get(index)
b_ox.set_top_left_point( chart.point.new(eachOrderBlock.barTime,na,eachOrderBloc
k.barHigh))
b_ox.set_bottom_right_point(chart.point.new(last_bar_time,na,eachOrderBlock.barLow)
)
b_ox.set_border_color( internal ? na : orderBlockColor)
b_ox.set_bgcolor( orderBlockColor)
// @function detect and draw structures, also detect and store order
blocks
// @param internal true for internal structures or order blocks
// @returns void
displayStructure(bool internal = false) =>
var bullishBar = true
var bearishBar = true
if internalFilterConfluenceInput
bullishBar := high - math.max(close, open) > math.min(close, open - low)
bearishBar := high - math.max(close, open) < math.min(close, open - low)
pivot p_ivot = internal ? internalHigh : swingHigh
trend t_rend = internal ? internalTrend : swingTrend
lineStyle = internal ? line.style_dashed : line.style_solid
labelSize = internal ? internalStructureSize : swingStructureSize
extraCondition = internal ? internalHigh.currentLevel !=
swingHigh.currentLevel and bullishBar : true
bullishColor = styleInput == MONOCHROME ? MONO_BULLISH : internal ?
internalBullColorInput : swingBullColorInput
if ta.crossover(close,p_ivot.currentLevel) and not p_ivot.crossed and
extraCondition
string tag = t_rend.bias == BEARISH ? CHOCH : BOS
if internal
currentAlerts.internalBullishCHoCH := tag == CHOCH
currentAlerts.internalBullishBOS := tag == BOS
else
currentAlerts.swingBullishCHoCH := tag == CHOCH
currentAlerts.swingBullishBOS := tag == BOS
p_ivot.crossed := true
t_rend.bias := BULLISH
displayCondition = internal ? showInternalsInput and (showInternalBullInput
== ALL or (showInternalBullInput == BOS and tag != CHOCH) or (showInternalBullInput
== CHOCH and tag == CHOCH)) : showStructureInput and (showSwingBullInput == ALL or
(showSwingBullInput == BOS and tag != CHOCH) or (showSwingBullInput == CHOCH and
tag == CHOCH))
if displayCondition
drawStructure(p_ivot,tag,bullishColor,lineStyle,label.style_label_down,labelSize)
if (internal and showInternalOrderBlocksInput) or (not internal and
showSwingOrderBlocksInput)
storeOrdeBlock(p_ivot,internal,BULLISH)
p_ivot := internal ? internalLow : swingLow
extraCondition := internal ? internalLow.currentLevel != swingLow.currentLevel
and bearishBar : true
bearishColor = styleInput == MONOCHROME ? MONO_BEARISH : internal ?
internalBearColorInput : swingBearColorInput
if ta.crossunder(close,p_ivot.currentLevel) and not p_ivot.crossed and
extraCondition
string tag = t_rend.bias == BULLISH ? CHOCH : BOS
if internal
currentAlerts.internalBearishCHoCH := tag == CHOCH
currentAlerts.internalBearishBOS := tag == BOS
else
currentAlerts.swingBearishCHoCH := tag == CHOCH
currentAlerts.swingBearishBOS := tag == BOS
p_ivot.crossed := true
t_rend.bias := BEARISH
displayCondition = internal ? showInternalsInput and (showInternalBearInput
== ALL or (showInternalBearInput == BOS and tag != CHOCH) or (showInternalBearInput
== CHOCH and tag == CHOCH)) : showStructureInput and (showSwingBearInput == ALL or
(showSwingBearInput == BOS and tag != CHOCH) or (showSwingBearInput == CHOCH and
tag == CHOCH))
if displayCondition
drawStructure(p_ivot,tag,bearishColor,lineStyle,label.style_label_up,labelSize)
if (internal and showInternalOrderBlocksInput) or (not internal and
showSwingOrderBlocksInput)
storeOrdeBlock(p_ivot,internal,BEARISH)
// @function draw one fair value gap box (each fair value gap has two
boxes)
// @param leftTime left time coordinate
// @param rightTime right time coordinate
// @param topPrice top price level
// @param bottomPrice bottom price level
// @param boxColor box color
// @returns box ID
fairValueGapBox(leftTime,rightTime,topPrice,bottomPrice,boxColor) =>
box.new(chart.point.new(leftTime,na,topPrice),chart.point.new(rightTime +
fairValueGapsExtendInput * (time-time[1]),na,bottomPrice), xloc=xloc.bar_time,
border_color = boxColor, bgcolor = boxColor)
// @function delete fair value gaps
// @returns fairValueGap ID
deleteFairValueGaps() =>
for [index,eachFairValueGap] in fairValueGaps
if (low < eachFairValueGap.bottom and eachFairValueGap.bias == BULLISH) or
(high > eachFairValueGap.top and eachFairValueGap.bias == BEARISH)
eachFairValueGap.topBox.delete()
eachFairValueGap.bottomBox.delete()
fairValueGaps.remove(index)
// @function draw fair value gaps
// @returns fairValueGap ID
drawFairValueGaps() =>
[lastClose, lastOpen, lastTime, currentHigh, currentLow, currentTime,
last2High, last2Low] = request.security(syminfo.tickerid,
fairValueGapsTimeframeInput, [close[1], open[1], time[1], high[0], low[0], time[0],
high[2], low[2]],lookahead = barmerge.lookahead_on)
barDeltaPercent = (lastClose - lastOpen) / (lastOpen * 100)
newTimeframe = timeframe.change(fairValueGapsTimeframeInput)
threshold = fairValueGapsThresholdInput ?
ta.cum(math.abs(newTimeframe ? barDeltaPercent : 0)) / bar_index * 2 : 0
bullishFairValueGap = currentLow > last2High and lastClose > last2High and
barDeltaPercent > threshold and newTimeframe
bearishFairValueGap = currentHigh < last2Low and lastClose < last2Low and -
barDeltaPercent > threshold and newTimeframe
if bullishFairValueGap
currentAlerts.bullishFairValueGap := true
fairValueGaps.unshift(fairValueGap.new(currentLow,last2High,BULLISH,fairValueGapBox
(lastTime,currentTime,currentLow,math.avg(currentLow,last2High),fairValueGapBullish
Color),fairValueGapBox(lastTime,currentTime,math.avg(currentLow,last2High),last2Hig
h,fairValueGapBullishColor)))
if bearishFairValueGap
currentAlerts.bearishFairValueGap := true
fairValueGaps.unshift(fairValueGap.new(currentHigh,last2Low,BEARISH,fairValueGapBox
(lastTime,currentTime,currentHigh,math.avg(currentHigh,last2Low),fairValueGapBearis
hColor),fairValueGapBox(lastTime,currentTime,math.avg(currentHigh,last2Low),last2Lo
w,fairValueGapBearishColor)))
// @function get line style from string
// @param style line style
// @returns string
getStyle(string style) =>
switch style
SOLID => line.style_solid
DASHED => line.style_dashed
DOTTED => line.style_dotted
// @function draw MultiTimeFrame levels
// @param timeframe base timeframe
// @param sameTimeframe true if chart timeframe is same as base timeframe
// @param style line style
// @param levelColor line and text color
// @returns void
drawLevels(string timeframe, bool sameTimeframe, string style, color levelColor) =>
[topLevel, bottomLevel, leftTime, rightTime] =
request.security(syminfo.tickerid, timeframe, [high[1], low[1], time[1],
time],lookahead = barmerge.lookahead_on)
float parsedTop = sameTimeframe ? high : topLevel
float parsedBottom = sameTimeframe ? low : bottomLevel
int parsedLeftTime = sameTimeframe ? time : leftTime
int parsedRightTime = sameTimeframe ? time : rightTime
int parsedTopTime = time
int parsedBottomTime = time
if not sameTimeframe
int leftIndex = times.binary_search_rightmost(parsedLeftTime)
int rightIndex =
times.binary_search_rightmost(parsedRightTime)
array<int> timeArray = times.slice(leftIndex,rightIndex)
array<float> topArray = highs.slice(leftIndex,rightIndex)
array<float> bottomArray = lows.slice(leftIndex,rightIndex)
parsedTopTime := timeArray.size() > 0 ?
timeArray.get(topArray.indexof(topArray.max())) : initialTime
parsedBottomTime := timeArray.size() > 0 ?
timeArray.get(bottomArray.indexof(bottomArray.min())) : initialTime
var line topLine = line.new(na, na, na, na, xloc = xloc.bar_time, color
= levelColor, style = getStyle(style))
var line bottomLine = line.new(na, na, na, na, xloc = xloc.bar_time, color
= levelColor, style = getStyle(style))
var label topLabel = label.new(na, na, xloc = xloc.bar_time, text =
str.format('P{0}H',timeframe), color=color(na), textcolor = levelColor, size =
size.small, style = label.style_label_left)
var label bottomLabel = label.new(na, na, xloc = xloc.bar_time, text =
str.format('P{0}L',timeframe), color=color(na), textcolor = levelColor, size =
size.small, style = label.style_label_left)
topLine.set_first_point( chart.point.new(parsedTopTime,na,parsedTop))
topLine.set_second_point( chart.point.new(last_bar_time + 20 * (time-
time[1]),na,parsedTop))
topLabel.set_point( chart.point.new(last_bar_time + 20 * (time-
time[1]),na,parsedTop))
bottomLine.set_first_point( chart.point.new(parsedBottomTime,na,parsedBottom))
bottomLine.set_second_point(chart.point.new(last_bar_time + 20 * (time-
time[1]),na,parsedBottom))
bottomLabel.set_point( chart.point.new(last_bar_time + 20 * (time-
time[1]),na,parsedBottom))
// @function true if chart timeframe is higher than provided timeframe
// @param timeframe timeframe to check
// @returns bool
higherTimeframe(string timeframe) => timeframe.in_seconds() >
timeframe.in_seconds(timeframe)
// @function update trailing swing points
// @returns int
updateTrailingExtremes() =>
trailing.top := math.max(high,trailing.top)
trailing.lastTopTime := trailing.top == high ? time : trailing.lastTopTime
trailing.bottom := math.min(low,trailing.bottom)
trailing.lastBottomTime := trailing.bottom == low ? time :
trailing.lastBottomTime
// @function draw trailing swing points
// @returns void
drawHighLowSwings() =>
var line topLine = line.new(na, na, na, na, color = swingBearishColor,
xloc = xloc.bar_time)
var line bottomLine = line.new(na, na, na, na, color = swingBullishColor,
xloc = xloc.bar_time)
var label topLabel = label.new(na, na, color=color(na), textcolor =
swingBearishColor, xloc = xloc.bar_time, style = label.style_label_down, size =
size.tiny)
var label bottomLabel = label.new(na, na, color=color(na), textcolor =
swingBullishColor, xloc = xloc.bar_time, style = label.style_label_up, size =
size.tiny)
rightTimeBar = last_bar_time + 20 * (time - time[1])
topLine.set_first_point( chart.point.new(trailing.lastTopTime, na,
trailing.top))
topLine.set_second_point( chart.point.new(rightTimeBar, na, trailing.top))
topLabel.set_point( chart.point.new(rightTimeBar, na, trailing.top))
topLabel.set_text( swingTrend.bias == BEARISH ? 'Strong High' : 'Weak
High')
bottomLine.set_first_point( chart.point.new(trailing.lastBottomTime, na,
trailing.bottom))
bottomLine.set_second_point(chart.point.new(rightTimeBar, na, trailing.bottom))
bottomLabel.set_point( chart.point.new(rightTimeBar, na, trailing.bottom))
bottomLabel.set_text( swingTrend.bias == BULLISH ? 'Strong Low' : 'Weak
Low')
// @function draw a zone with a label and a box
// @param labelLevel price level for label
// @param labelIndex bar index for label
// @param top top price level for box
// @param bottom bottom price level for box
// @param tag text to display
// @param zoneColor base color
// @param style label style
// @returns void
drawZone(float labelLevel, int labelIndex, float top, float bottom, string tag,
color zoneColor, string style) =>
var label l_abel = label.new(na,na,text = tag, color=color(na),textcolor =
zoneColor, style = style, size = size.small)
var box b_ox = box.new(na,na,na,na,bgcolor =
color.new(zoneColor,80),border_color = color(na), xloc = xloc.bar_time)
b_ox.set_top_left_point( chart.point.new(trailing.barTime,na,top))
b_ox.set_bottom_right_point(chart.point.new(last_bar_time,na,bottom))
l_abel.set_point( chart.point.new(na,labelIndex,labelLevel))
// @function draw premium/discount zones
// @returns void
drawPremiumDiscountZones() =>
drawZone(trailing.top, math.round(0.5*(trailing.barIndex + last_bar_index)),
trailing.top, 0.95*trailing.top + 0.05*trailing.bottom, 'Premium',
premiumZoneColor, label.style_label_down)
equilibriumLevel = math.avg(trailing.top, trailing.bottom)
drawZone(equilibriumLevel, last_bar_index, 0.525*trailing.top +
0.475*trailing.bottom, 0.525*trailing.bottom + 0.475*trailing.top, 'Equilibrium',
equilibriumZoneColorInput, label.style_label_left)
drawZone(trailing.bottom, math.round(0.5*(trailing.barIndex + last_bar_index)),
0.95*trailing.bottom + 0.05*trailing.top, trailing.bottom, 'Discount',
discountZoneColor, label.style_label_up)
//---------------------------------------------------------------------------------
------------------------------------}
//MUTABLE VARIABLES & EXECUTION
//---------------------------------------------------------------------------------
------------------------------------{
parsedOpen = showTrendInput ? open : na
candleColor = internalTrend.bias == BULLISH ? swingBullishColor : swingBearishColor
plotcandle(parsedOpen,high,low,close,color = candleColor, wickcolor = candleColor,
bordercolor = candleColor)
if showHighLowSwingsInput or showPremiumDiscountZonesInput
updateTrailingExtremes()
if showHighLowSwingsInput
drawHighLowSwings()
if showPremiumDiscountZonesInput
drawPremiumDiscountZones()
if showFairValueGapsInput
deleteFairValueGaps()
getCurrentStructure(swingsLengthInput,false)
getCurrentStructure(5,false,true)
if showEqualHighsLowsInput
getCurrentStructure(equalHighsLowsLengthInput,true)
if showInternalsInput or showInternalOrderBlocksInput or showTrendInput
displayStructure(true)
if showStructureInput or showSwingOrderBlocksInput or showHighLowSwingsInput
displayStructure()
if showInternalOrderBlocksInput
deleteOrderBlocks(true)
if showSwingOrderBlocksInput
deleteOrderBlocks()
if showFairValueGapsInput
drawFairValueGaps()
if barstate.islastconfirmedhistory or barstate.islast
if showInternalOrderBlocksInput
drawOrderBlocks(true)
if showSwingOrderBlocksInput
drawOrderBlocks()
lastBarIndex := currentBarIndex
currentBarIndex := bar_index
newBar = currentBarIndex != lastBarIndex
if barstate.islastconfirmedhistory or (barstate.isrealtime and newBar)
if showDailyLevelsInput and not higherTimeframe('D')
drawLevels('D',timeframe.isdaily,dailyLevelsStyleInput,dailyLevelsColorInput)
if showWeeklyLevelsInput and not higherTimeframe('W')
drawLevels('W',timeframe.isweekly,weeklyLevelsStyleInput,weeklyLevelsColorInput)
if showMonthlyLevelsInput and not higherTimeframe('M')
drawLevels('M',timeframe.ismonthly,monthlyLevelsStyleInput,monthlyLevelsColorInput)
//---------------------------------------------------------------------------------
------------------------------------}
//ALERTS
//---------------------------------------------------------------------------------
------------------------------------{
alertcondition(currentAlerts.internalBullishBOS, 'Internal Bullish BOS',
'Internal Bullish BOS formed')
alertcondition(currentAlerts.internalBullishCHoCH, 'Internal Bullish CHoCH',
'Internal Bullish CHoCH formed')
alertcondition(currentAlerts.internalBearishBOS, 'Internal Bearish BOS',
'Internal Bearish BOS formed')
alertcondition(currentAlerts.internalBearishCHoCH, 'Internal Bearish CHoCH',
'Internal Bearish CHoCH formed')
alertcondition(currentAlerts.swingBullishBOS, 'Bullish BOS',
'Internal Bullish BOS formed')
alertcondition(currentAlerts.swingBullishCHoCH, 'Bullish CHoCH',
'Internal Bullish CHoCH formed')
alertcondition(currentAlerts.swingBearishBOS, 'Bearish BOS',
'Bearish BOS formed')
alertcondition(currentAlerts.swingBearishCHoCH, 'Bearish CHoCH',
'Bearish CHoCH formed')
alertcondition(currentAlerts.internalBullishOrderBlock, 'Bullish Internal OB
Breakout', 'Price broke bullish internal OB')
alertcondition(currentAlerts.internalBearishOrderBlock, 'Bearish Internal OB
Breakout', 'Price broke bearish internal OB')
alertcondition(currentAlerts.swingBullishOrderBlock, 'Bullish Swing OB
Breakout', 'Price broke bullish swing OB')
alertcondition(currentAlerts.swingBearishOrderBlock, 'Bearish Swing OB
Breakout', 'Price broke bearish swing OB')
alertcondition(currentAlerts.equalHighs, 'Equal Highs',
'Equal highs detected')
alertcondition(currentAlerts.equalLows, 'Equal Lows',
'Equal lows detected')
alertcondition(currentAlerts.bullishFairValueGap, 'Bullish FVG',
'Bullish FVG formed')
alertcondition(currentAlerts.bearishFairValueGap, 'Bearish FVG',
'Bearish FVG formed')
//---------------------------------------------------------------------------------
------------------------------------}
//==========================
//volume profile
//==========================
sessionType = input.string('Daily', 'Session Type', options=['Tokyo','London','New
York','Daily','Weekly', 'Monthly', 'Quarterly', 'Yearly'])
showProf = input.bool(true, 'Show Volume Profile', group='Display')
showSbox = input.bool(true, 'Show Session Box', group='Display')
showPoc = input.bool(true, 'Show POC', group='Display')
showVA = input.bool(true, 'Show VAH and VAL', group='Display')
showVAb = input.bool(false, 'Show Value Area Box', group='Display')
showCur = input.bool(true, 'Show Live Zone', group='Display')
showLabels = input.bool(true, 'Show Session Lables', group='Display')
showFx = input.bool(false, 'Show Forex Sessions (no profile)', group='Display')
resolution = input.int(30, 'Resolution', minval=5, tooltip='The higher the value,
the more refined of a profile, but less profiles shown on chart', group='Volume
Profile Settings')
VAwid = input.int(70, 'Value Area Volume %', minval=1, maxval=100, group='Volume
Profile Settings')
dispMode = input.string('Mode 2', 'Bar Mode', ['Mode 1', 'Mode 2', 'Mode 3'],
group='Volume Profile Settings')
volType = input.string('Volume', 'Profile Data Type', options=['Volume', 'Open
Interest'], group='Volume Profile Settings')
smoothVol = input.bool(false, 'Smooth Volume Data', tooltip='Useful for assets that
have very large spikes in volume over large bars - helps create better profiles',
group='Volume Profile Settings')
dataTf = ''
bullCol = input.color(color.rgb(76, 175, 79, 50), 'Up Volume', group='Appearance')
bearCol = input.color(color.rgb(255, 82, 82, 50), 'Down Volume',
group='Appearance')
VAbCol = input.color(color.rgb(107, 159, 255, 90), 'Value Area Box',
group='Appearance' )
pocCol = input.color(color.red, 'POC', inline='p', group='Appearance')
pocWid = input.int(1, 'Thickness', inline='p', group='Appearance')
vahCol = input.color(color.aqua, 'VAH', inline='h', group='Appearance')
vahWid = input.int(1, 'Thickness', inline='h', group='Appearance')
valCol = input.color(color.aqua, 'VAL', inline='l', group='Appearance')
valWid = input.int(1, 'Thickness', inline='l', group='Appearance')
boxBg = input.color(color.rgb(255, 153, 0, 100), 'Box', inline='m',
group='Appearance')
boxWid = input.int(1, 'Thickness', inline='m', group='Appearance')
//==========================
//Constants / Variable Declaration
//==========================
var int zoneStart = 0
var int tokyoStart = 0
var int londonStart = 0
var int nyStart = 0
int lookback = bar_index - zoneStart
var activeZone = false
// Defining arrays that store the information
var vpGreen = array.new_float(resolution, 0) // Sum of volume on long bars
var vpRed = array.new_float(resolution, 0) // Same thing but with red bars
var zoneBounds = array.new_float(resolution, 0) // array that stores the highest
value that can be in a zone
//Values to store current intra bar data
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)
//Getting OI Data
string userSymbol = syminfo.prefix + ":" + syminfo.ticker
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)
//Selecting what vol type to use
vol() =>
out = smoothVol ? ta.ema(volume, 5) : volume
if volType == 'Open Interest'
out := deltaOi
out
//Getting intrabar intial data
[dO, dC, dH, dL, dV] = request.security_lower_tf(syminfo.tickerid, dataTf, [open,
close, high, low, vol()])
//==========================
//Functions
//==========================
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)
profHigh = ta.highest(high, lookback+1)[1]
profLow = ta.lowest(low, lookback+1)[1]
tr = ta.atr(1)
atr = ta.atr(14)
get_vol(y11, y12, y21, y22, height, vol) =>
nz(math.max(math.min(math.max(y11, y12), math.max(y21, y22)) -
math.max(math.min(y11, y12), math.min(y21, y22)), 0) * vol / height)
profileAdd(o, h, l, c, v, g, w) =>
//Array to store how much to distribute in each zone, on scale of 1 for full
gap size to 0
zoneDist = array.new_float(resolution, 0)
distSum = 0.0
// Going over each zone
for i = 0 to array.size(vpGreen) - 1
// Checking to see if cur bar is in zone
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
gap = (profHigh - profLow) / resolution
// Defining profile bounds
for i = 0 to resolution - 1
array.set(zoneBounds, i, profHigh - gap * i)
// Putting each bar inside zone into the volume profile array
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
//Finding poc index
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
volCnt += (array.get(vpRed, pocInd) + array.get(vpGreen, pocInd))
for i = 1 to array.size(vpRed)
if pocInd + i >= 0 and pocInd + i < array.size(vpRed)
volCnt += (array.get(vpRed, pocInd + i) + array.get(vpGreen, pocInd +
i))
if volCnt >= volSum * (VAwid/100)
break
else
val := array.get(zoneBounds, pocInd + i) - gap
if pocInd - i >= 0 and pocInd - i < array.size(vpRed)
volCnt += (array.get(vpRed, pocInd - i) + array.get(vpGreen, pocInd -
i))
if volCnt >= volSum * (VAwid/100)
break
else
vah := array.get(zoneBounds, pocInd - i)
[val, vah]
drawNewZone(update) =>
if bar_index > lookback and update and array.sum(vpGreen) + array.sum(vpRed) >
0
gap = (profHigh - profLow) / resolution
float leftMax = bar_index[lookback]
float rightMax = bar_index[int(lookback / 1.4)]
float rightMaxVol = array.max(vpGreen)+array.max(vpRed)
float buffer = gap / 10
if showLabels
label.new((bar_index - 1 + int(leftMax))/2, profHigh, sessionType,
color=color.rgb(0,0,0,100), textcolor=chart.fg_color)
if showProf
for i = 0 to array.size(vpRed) - 1
greenEnd = int(leftMax + (rightMax - leftMax) * (array.get(vpGreen,
i) / rightMaxVol))
redEnd = int(greenEnd + (rightMax - leftMax) * (array.get(vpRed, i)
/ rightMaxVol))
if dispMode == 'Mode 2'
box.new(int(leftMax), array.get(zoneBounds, i) - buffer,
greenEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bullCol, border_width=0)
box.new(greenEnd, array.get(zoneBounds, i) - buffer, redEnd,
array.get(zoneBounds, i) - gap + buffer, bgcolor=bearCol, border_width=0)
else if dispMode == 'Mode 1'
box.new(int(leftMax), array.get(zoneBounds, i) - buffer,
greenEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bullCol, border_width=0)
else
box.new(int(leftMax), array.get(zoneBounds, i) - buffer,
greenEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bullCol, border_width=0)
box.new(int(leftMax)-redEnd+greenEnd, array.get(zoneBounds, i)
- buffer, int(leftMax), array.get(zoneBounds, i) - gap + buffer, bgcolor=bearCol,
border_width=0)
box.new(int(leftMax), profHigh, bar_index-1, profLow, chart.fg_color,
boxWid, line.style_dashed, bgcolor=boxBg)
poc = pocLevel()
[val, vah] = valueLevels(poc)
if showPoc
line.new(int(leftMax), poc, bar_index-1, poc, color=pocCol,
width=pocWid)
if showVA
line.new(int(leftMax), vah, bar_index-1, vah, color=vahCol,
width=vahWid)
line.new(int(leftMax), val, bar_index-1, val, color=valCol,
width=valWid)
if showVAb
box.new(int(leftMax), vah, bar_index-1, val, border_color=color.rgb(54,
58, 69, 100), bgcolor=VAbCol)
//if update
// resetProfile(true)
drawCurZone(update, delete) =>
var line pocLine = na
var line vahLine = na
var line valLine = na
var box outBox = na
var label sessionLab = na
var redBoxes = array.new_box(array.size(vpRed), na)
var greenBoxes = array.new_box(array.size(vpRed), na)
if bar_index > lookback and update and array.sum(vpGreen) + array.sum(vpRed) >
0
//Clearing the previous boxes and array
if not na(pocLine)
line.delete(pocLine)
if not na(vahLine)
line.delete(vahLine)
if not na(valLine)
line.delete(valLine)
if not na(outBox)
box.delete(outBox)
if not na(sessionLab)
label.delete(sessionLab)
for i = 0 to array.size(redBoxes) - 1
if not na(array.get(redBoxes, i))
box.delete(array.get(redBoxes, i))
box.delete(array.get(greenBoxes, i))
gap = (profHigh - profLow) / resolution
float leftMax = bar_index[lookback]
float rightMax = bar_index[int(lookback / 1.4)]
float rightMaxVol = array.max(vpGreen)+array.max(vpRed)
float buffer = gap / 10
if showLabels
sessionLab := label.new((bar_index - 1 + int(leftMax))/2, profHigh,
sessionType, color=color.rgb(0,0,0,100), textcolor=chart.fg_color)
if showProf
for i = 0 to array.size(vpRed) - 1
greenEnd = int(leftMax + (rightMax - leftMax) * (array.get(vpGreen,
i) / rightMaxVol))
redEnd = int(greenEnd + (rightMax - leftMax) * (array.get(vpRed, i)
/ rightMaxVol))
if dispMode == 'Mode 2'
array.set(greenBoxes, i, box.new(int(leftMax),
array.get(zoneBounds, i) - buffer, greenEnd, array.get(zoneBounds, i) - gap +
buffer, bgcolor=bullCol, border_width=0))
array.set(redBoxes, i, box.new(greenEnd, array.get(zoneBounds,
i) - buffer, redEnd, array.get(zoneBounds, i) - gap + buffer, bgcolor=bearCol,
border_width=0))
else if dispMode == 'Mode 1'
array.set(greenBoxes, i, box.new(int(leftMax),
array.get(zoneBounds, i) - buffer, greenEnd, array.get(zoneBounds, i) - gap +
buffer, bgcolor=bullCol, border_width=0))
else
array.set(greenBoxes, i, box.new(int(leftMax),
array.get(zoneBounds, i) - buffer, greenEnd, array.get(zoneBounds, i) - gap +
buffer, bgcolor=bullCol, border_width=0))
array.set(redBoxes, i, box.new(int(leftMax)-redEnd+greenEnd,
array.get(zoneBounds, i) - buffer, int(leftMax), array.get(zoneBounds, i) - gap +
buffer, bgcolor=bearCol, border_width=0))
outBox := box.new(int(leftMax), profHigh, bar_index-1, profLow,
chart.fg_color, boxWid, line.style_dashed, bgcolor=boxBg)
poc = pocLevel()
[val, vah] = valueLevels(poc)
if showPoc
line.delete(pocLine)
pocLine := line.new(int(leftMax), poc, bar_index-1, poc, color=pocCol,
width=pocWid)
if showVA
line.delete(vahLine)
line.delete(valLine)
vahLine := line.new(int(leftMax), vah, bar_index-1, vah, color=vahCol,
width=vahWid)
valLine := line.new(int(leftMax), val, bar_index-1, val, color=valCol,
width=valWid)
if showVAb
box.new(int(leftMax), vah, bar_index-1, val, border_color=color.rgb(54,
58, 69, 100), bgcolor=VAbCol)
if delete
box.delete(outBox)
line.delete(pocLine)
line.delete(vahLine)
line.delete(valLine)
for i = 0 to array.size(greenBoxes)-1
box.delete(array.get(greenBoxes, i))
for i = 0 to array.size(redBoxes)-1
box.delete(array.get(redBoxes, i))
drawForexBox(startBar, title, top, bottom) =>
box.new(int(startBar), top, bar_index-1, bottom, chart.fg_color, boxWid,
line.style_dashed, bgcolor=boxBg)
if showLabels
label.new((bar_index - 1 + int(startBar))/2, top, title,
color=color.rgb(0,0,0,100), textcolor=chart.fg_color)
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) =>
if array.size(o) > 0
for i = 0 to array.size(o) - 1
array.push(ltfOpen, array.get(o, i))
array.push(ltfHigh,array.get(h, i))
array.push(ltfLow,array.get(l, i))
array.push(ltfClose,array.get(c, i))
array.push(ltfVolume,array.get(v, i))
//==========================
//Calculations
//==========================
//Detecting different start dates
newDaily = dayofweek != dayofweek[1]
newWeekly = weekofyear != weekofyear[1]
newMonthly = (dayofmonth != dayofmonth[1] + 1) and (dayofmonth != dayofmonth[1])
newYearly = year != year[1]
newQuarterly = month != month[1] and (month - 1) % 3 == 0
utcHour = hour(time(timeframe.period, '0000-2400', 'GMT'), 'GMT')
newTokyo = utcHour != utcHour[1] + 1 and utcHour != utcHour[1]
endTokyo = utcHour >= 9 and utcHour[1] < 9
newLondon = utcHour >= 7 and utcHour[1] < 7
endLondon = utcHour >= 16 and utcHour[1] < 16
newNewYork = utcHour >= 13 and utcHour[1] < 13
endNewYork = utcHour >= 22 and utcHour[1] < 22
newSession = switch sessionType
'Tokyo' => newTokyo
'London' => newLondon
'New York' => newNewYork
'Daily' => newDaily
'Weekly' => newWeekly
'Monthly' => newMonthly
'Yearly' => newYearly
'Quarterly' => newQuarterly
=> newDaily
zoneEnd = switch sessionType
'Tokyo' => endTokyo
'London' => endLondon
'New York' => endNewYork
'Daily' => newDaily
'Weekly' => newWeekly
'Monthly' => newMonthly
'Yearly' => newYearly
'Quarterly' => newQuarterly
=> newDaily
isForex = showFx
//Re calculating and drawing zones
calcSession(zoneEnd or (barstate.islast and showCur))
drawNewZone(zoneEnd)
drawCurZone(barstate.islast and not zoneEnd and showCur and activeZone, zoneEnd)
//Reseting profie at start of new zone
resetProfile(newSession)
//Updating data arrays
updateIntra(dO, dH, dL, dC, dV)
//Reseting zone start value
if zoneEnd
activeZone := false
if newSession
zoneStart := bar_index
activeZone := true
if newLondon
londonStart := bar_index
if newTokyo
tokyoStart := bar_index
if newNewYork
nyStart := bar_index
londonHigh = ta.highest(high, bar_index-londonStart+1)
tokyoHigh = ta.highest(high, bar_index-tokyoStart+1)
nyHigh = ta.highest(high, bar_index-nyStart+1)
londonLow = ta.lowest(low, bar_index-londonStart+1)
tokyoLow = ta.lowest(low, bar_index-tokyoStart+1)
nyLow = ta.lowest(low, bar_index-nyStart+1)
if endLondon and isForex
drawForexBox(londonStart, 'London', londonHigh, londonLow)
if endNewYork and isForex
drawForexBox(nyStart, 'New York', nyHigh, nyLow)
if endTokyo and isForex
drawForexBox(tokyoStart, 'Tokyo', tokyoHigh, tokyoLow)
//
//
//
//
//
// HIGHLIGHT CANDLES
INTRADAY = 'Intraday'
PERIOD_ONE = 'Period one'
PERIOD_TWO = 'Period two'
PERIOD_THREE = 'Period three'
PERIOD_FOUR = 'Period four'
PERIOD_FIVE = 'Period five'
PERIOD_SIX = 'Period six'
TOOLTIP = 'Times need to be in exchange timezone'
// Inputs
display_timeframes = input.string(title='What timeframes to display?', defval='Only
H1', options=['Only H1', INTRADAY])
// Time period inputs
display_period_one = input.bool(true, 'Display period one?', group=PERIOD_ONE)
period_one_session = input.session('0400-0500', 'Period one times',
group=PERIOD_ONE, tooltip=TOOLTIP)
period_one_colour = #ff048a
display_period_two = input.bool(true, 'Display period two?', group=PERIOD_TWO)
period_two_session = input.session('0800-0900', 'Period two times',
group=PERIOD_TWO, tooltip=TOOLTIP)
period_two_colour = #f700fb
display_period_three = input.bool(true, 'Display period three?',
group=PERIOD_THREE)
period_three_session = input.session('1200-1300', 'Period three times',
group=PERIOD_THREE, tooltip=TOOLTIP)
period_three_colour = #ffdd00
display_period_four = input.bool(true, 'Display period four?', group=PERIOD_FOUR)
period_four_session = input.session('1400-1500', 'Period four times',
group=PERIOD_FOUR, tooltip=TOOLTIP)
period_four_colour = #ff048a
display_period_five = input.bool(true, 'Display period five?', group=PERIOD_FIVE)
period_five_session = input.session('1600-1700', 'Period five times',
group=PERIOD_FIVE, tooltip=TOOLTIP)
period_five_colour = #f700fb
display_period_six = input.bool(true, 'Display period six?', group=PERIOD_SIX)
period_six_session = input.session('1800-1900', 'Period six times',
group=PERIOD_SIX, tooltip=TOOLTIP)
period_six_colour = #ffdd00
// Check timeframe
display_on_current_timeframe = display_timeframes == INTRADAY and
timeframe.isintraday or timeframe.multiplier == 60
InSession(sessionTimes) =>
not na(time(timeframe.period, sessionTimes))
candle_colour = if display_period_one and InSession(period_one_session)
period_one_colour
else if display_period_two and InSession(period_two_session)
period_two_colour
else if display_period_three and InSession(period_three_session)
period_three_colour
else if display_period_four and InSession(period_four_session)
period_four_colour
else if display_period_five and InSession(period_five_session)
period_five_colour
else if display_period_six and InSession(period_six_session)
period_six_colour
else
na
// Colour the bar
barcolor(color=candle_colour, title='Bar highlight')
///
///
//
//FIBLEVELS
color Offwhite = color.rgb(255, 255, 255, 71)
color _offwhite = color.rgb(255, 255, 255, 50)
color Red1 = color.rgb(255, 82, 82, 85)
color Red2 = color.rgb(243, 6, 6, 60)
color green = color.rgb(73, 241, 241, 85)
color green2 = color.rgb(73, 241, 241, 60)
color Black = color.rgb(7, 7, 7)
color Yellow = color.rgb(254, 229, 4)
string visual = "➞ Visuals Settings🔸"
string core = "➞ Main Core Settings 🔸"
string TIME = input.timeframe("D",title = "Fibo
Timeframe",
group = core,
options=["120","240","480","720",'D', 'W', 'M'],
tooltip = "Choose a Higher Timeframe than Chart Timeframe")
string Voldata = input.string("All",title =
"Volume Type",
group = core,
options=["Bear","Bull","All"],
tooltip = "Choose Volume Type to Show in Boxes")
int levs = input.int(12,"Volume
Levels",tooltip = "Number of the Volume levels to check", group = core)
bool ShowVolume = input.bool(true,"Show Volume
❓ ",inline = "01",group = visual)
color Bull = input.color(color.new(#42f07f,
35),"",inline = "01",group = visual)
color Bear = input.color(color.new(#f37451,
70),"",inline = "01",group = visual)
bool Showlevels = input.bool(true,"Show Levels
❓ ",inline = "02",group = visual)
color Bull1 = input.color(green,"",inline =
"02",group = visual)
color Bear1 = input.color(Red1,"",inline =
"02",group = visual)
bool ShowTarget = input.bool(true,"Show Target
❓ ",inline = "03",group = visual)
color Bull2 = input.color(color.lime,"",inline
= "03",group = visual)
color Bear2 = input.color(color.rgb(230, 0,
0),"",inline = "03",group = visual)
bool ShowPOC = input.bool(true,"Show POC
❓ ",inline = "04",group = visual)
int sync = bar_index
float scr = close
string TF = timeframe.isdwm ? "M" : "W"
int atrLen = 30
float mult = 0.3
float per = 10.0
float perct = close * (0.3/100)
float srdatr = ta.atr (atrLen) * mult
float band = math.min (srdatr, perct) [20] /2
var float [] Fibo = array.new_float(6,0.0)
var line [] Lines = array.new_line()
var label [] Labels = array.new_label()
var box [] FiboBOX = array.new_box(6)
float FH =
request.security(syminfo.tickerid, TIME, high[1]) + band
float FL =
request.security(syminfo.tickerid, TIME, low[1]) - band
float FC =
request.security(syminfo.tickerid, TIME, close[1]) + band
float [] TotalVolume = array.new_float()
float [] Greenvolume = array.new_float()
float [] redvolume = array.new_float()
var int newWeekBarIndex = na
var int newWeekTIME = na
weekChange = timeframe.change(TF)
if weekChange
newWeekBarIndex := bar_index
newWeekTIME := time
TF2 = timeframe.multiplier < 60 ? "1D" : "3D"
EXTIME = timeframe.in_seconds(TF2) * 1000
anchorTime = time + EXTIME
anchorBarIndex = (time - anchorTime) / (1000 *
timeframe.in_seconds(timeframe.period))
anchorBarsBack = bar_index - anchorBarIndex
// plot(anchorBarsBack)
// plot(bar_index)
BAR1 = math.floor(sync - newWeekBarIndex)
Volume(GV,RV,TV,BC)=>
GR = GV / TV
RR = RV / TV
[GR , RR]
PP = (FH + FL + FC) / 3
if BAR1 > 5000
BAR1:=3500
array.set(Fibo,0,PP + 0.382 * (FH - FL))
array.set(Fibo,1,PP - 0.382 * (FH - FL))
array.set(Fibo,2,PP + 0.618 * (FH - FL))
array.set(Fibo,3,PP - 0.618 * (FH - FL))
array.set(Fibo,4,PP + (FH - FL))
array.set(Fibo,5,PP - (FH - FL))
// int levs = array.size(Fibo) * 2
float FT = array.get(Fibo,4)
float FB = array.get(Fibo,5)
float [] VPlevels = array.new_float(levs+1)
var box [] VPboxes = array.new_box(levs+3)
if array.size(Fibo) > 6
for i = 0 to 5
array.shift(Fibo)
step = ( FT-FB ) / levs
for i=0 to levs by 1
array.set(VPlevels,i, FB + step * i)
if barstate.islast
int [] Points = array.new_int(levs,0)
float [] Volumes = array.new_float(levs,0.0)
float [] SCR = array.new_float()
float [] BUllV = array.new_float(levs,0.0)
float [] BEARV = array.new_float(levs,0.0)
for i = 0 to BAR1
array.push(SCR,close[i])
if Showlevels
for i = 0 to array.size(Fibo) - 1
C = i == 0 or i == 2 or i == 4
array.push(FiboBOX,box.new(newWeekTIME,
array.get(Fibo,i) + (band/2),
time + EXTIME,
array.get(Fibo,i) - (band/2),
bgcolor = C ? Bear1 : Bull1,
border_color =C ? color.new(Bear1,60) : color.new(Bull1,60),
border_width = 1,
xloc = xloc.bar_time))
for i=0 to array.size(SCR) -1
for x=0 to array.size(VPlevels) - 2 by 1
if array.get(SCR,i)>array.get(VPlevels,x)
and
array.get(SCR,i)<array.get(VPlevels,x+1)
array.set(Points,x,array.get(Points,x)+1)
array.set(Volumes,x,array.get(Volumes,x)+volume[x])
if array.get(SCR,i) > open[i]
array.set(BUllV,x,array.get(BUllV,x)+volume[x])
if array.get(SCR,i) < open[i]
array.set(BEARV,x,array.get(BEARV,x)+volume[x])
break
if array.get(SCR,i) > open[i]
array.push(Greenvolume,volume[i])
if array.get(SCR,i) < open[i]
array.push(redvolume,volume[i])
array.push(TotalVolume,volume[i])
[GR,RR] = Volume(array.sum(Greenvolume),
array.sum(redvolume),
array.sum(TotalVolume),
array.size(SCR) -1)
// label.new(bar_index,high,str.tostring(SCR.size()))
if ShowVolume
for i = 0 to array.size(Points) -1
str = Voldata == "All" ?
str.tostring(array.get(Volumes,i),format.volume)
: Voldata == "Bear" ?
str.tostring(array.get(BEARV,i),format.volume):
str.tostring(array.get(BUllV,i),format.volume)
box.delete(array.get(VPboxes,i))
array.set(VPboxes,i,
box.new(anchorBarsBack - array.get(Points,i),
array.get(VPlevels,i+1) + (band/2),
anchorBarsBack,
array.get(VPlevels,i) + (band/2),
border_color = color.from_gradient(array.get(Points,i),0,
array.max(Points),
Bear,
Bull),
bgcolor=color.from_gradient(array.get(Points,i),0,
array.max(Points),
Bear,
Bull),
text=str,
text_color=color.white
))
if ShowPOC
//get the max volume
// array.indexof(Volumes)
var box POC = na , box.delete(POC)
MaxVID = Volumes.indexof(Volumes.max())
POC:= box.new(newWeekTIME,VPlevels.get(MaxVID)+
(band/2),anchorTime,VPlevels.get(MaxVID+1)+ (band/2),
#e0f2e93a,border_style=line.style_solid,bgcolor=color.new(#586161,
75),
text="POC",text_color=chart.fg_color,text_halign =
text.align_center, text_valign = text.align_center,xloc=xloc.bar_time)
MID = (FB +FT ) / 2
if (scr < FT) and (scr > FB) and ShowTarget
max_bars_back(scr,2000)
if GR > RR
if (scr > MID)
array.push(Lines,
line.new(sync + 3,
hl2[1],sync + 10,
array.get(Fibo,2),
color= Bull2,
style = line.style_arrow_right,
width = 1))
array.push(Labels,
label.new(sync + 10,
array.get(Fibo,2),
"Possible Target ",
style=label.style_label_lower_left,
color=color.new(Bull2, 70),
textcolor = color.white,
size=size.small))
else if (scr < MID)
array.push(Lines,
line.new(sync + 3,
hl2[1],sync + 10,
array.get(Fibo,0),
color= Bull2,
style = line.style_arrow_right,
width = 1))
array.push(Labels,
label.new(sync + 10,
array.get(Fibo,0),
"Possible Target ",
style=label.style_label_lower_left,
color=color.new(Bull2, 70),
textcolor = color.white,
size=size.small))
else
if scr > MID
array.push(Lines,
line.new(sync + 3,
hl2[1],sync + 10,
array.get(Fibo,1),
color= Bear2,
style = line.style_arrow_right,
width = 1))
array.push(Labels,
label.new(sync + 10,
array.get(Fibo,1),
"Possible Target ",
style=label.style_label_lower_left,
color=color.new(Bear2, 70),
textcolor = color.white,
size=size.small))
else if scr < MID
array.push(Lines,
line.new(sync + 3,
hl2[1],sync + 10,
array.get(Fibo,3),
color= Bear2,
style = line.style_arrow_right,
width = 1))
array.push(Labels,
label.new(sync + 10,
array.get(Fibo,3),
"Possible Target ",
style=label.style_label_lower_left,
color=color.new(Bear2, 70),
textcolor = color.white,
size=size.small))
if array.size(Lines) > 1
line.delete(array.shift(Lines))
if array.size(Labels) > 1
label.delete(array.shift(Labels))
if array.size(FiboBOX) > 6
for i = 0 to 5
box.delete(array.shift(FiboBOX))
//MOVING AVERAGES
// Determine the chart timeframe
chart_tf = timeframe.period
// Define EMA periods based on timeframe
ema_period_yearly = chart_tf == "W" ? 52 : chart_tf == "5" ? 4032 : na
ema_period_quarterly = chart_tf == "D" ? 63 : chart_tf == "5" ? 1008 : na
ema_period_monthly = chart_tf == "H" ? 126 : chart_tf == "D" ? 21 : chart_tf == "5"
? 504 : na
ema_period_weekly = chart_tf == "15" ? 130 : chart_tf == "D" ? 5 : chart_tf ==
"5" ? 168 : na
ema_period_daily = chart_tf == "5" ? 78 : chart_tf == "D" ? 1 : na
ema_period_4h = chart_tf == "5" ? 312 : na
ema_period_1h = chart_tf == "5" ? 78 : na
ema_period_15m = chart_tf == "5" ? 3 : na
// Calculate EMAs
ema_yearly = not na(ema_period_yearly) ? ta.ema(close, ema_period_yearly) : na
ema_quarterly = not na(ema_period_quarterly) ? ta.ema(close,
ema_period_quarterly) : na
ema_monthly = not na(ema_period_monthly) ? ta.ema(close, ema_period_monthly) : na
ema_weekly = not na(ema_period_weekly) ? ta.ema(close, ema_period_weekly) : na
ema_daily = not na(ema_period_daily) ? ta.ema(close, ema_period_daily) : na
ema_4h = not na(ema_period_4h) ? ta.ema(close, ema_period_4h) : na
ema_1h = not na(ema_period_1h) ? ta.ema(close, ema_period_1h) : na
ema_15m = not na(ema_period_15m) ? ta.ema(close, ema_period_15m) : na
// Plot EMAs only if they are valid
plot(ema_yearly, color=color.blue, title="Yearly EMA")
plot(ema_quarterly, color=color.purple, title="Quarterly EMA")
plot(ema_monthly, color=color.orange, title="Monthly EMA")
plot(ema_weekly, color=color.green, title="Weekly EMA")
plot(ema_daily, color=color.red, title="Daily EMA")
plot(ema_4h, color=color.navy, title="4H EMA")
plot(ema_1h, color=color.yellow, title="1H EMA")
plot(ema_15m, color=color.white, title="15M EMA")