Professional Documents
Culture Documents
structure with limit lines
structure with limit lines
structure with limit lines
0 at
https://mozilla.org/MPL/2.0/
// ┬й sevencampbell
//@version=5
//trategy(title = "Zazzamira 50-25-25 Trend System W Alerts", overlay = true,
default_qty_value = 4, initial_capital=10000,default_qty_type=strategy.fixed,
pyramiding=3, process_orders_on_close=true, max_lines_count=500)
// // UpFractal
// bool upflagDownFrontier = true
// bool upflagUpFrontier0 = true
// bool upflagUpFrontier1 = true
// bool upflagUpFrontier2 = true
// bool upflagUpFrontier3 = true
// bool upflagUpFrontier4 = true
// for i = 1 to n
// upflagDownFrontier := upflagDownFrontier and (high[n-i] < high[n])
// upflagUpFrontier0 := upflagUpFrontier0 and (high[n+i] < high[n])
// upflagUpFrontier1 := upflagUpFrontier1 and (high[n+1] <= high[n] and
high[n+i + 1] < high[n])
// upflagUpFrontier2 := upflagUpFrontier2 and (high[n+1] <= high[n] and
high[n+2] <= high[n] and high[n+i + 2] < high[n])
// upflagUpFrontier3 := upflagUpFrontier3 and (high[n+1] <= high[n] and
high[n+2] <= high[n] and high[n+3] <= high[n] and high[n+i + 3] < high[n])
// upflagUpFrontier4 := upflagUpFrontier4 and (high[n+1] <= high[n] and
high[n+2] <= high[n] and high[n+3] <= high[n] and high[n+4] <= high[n] and high[n+i
+ 4] < high[n])
// flagUpFrontier = upflagUpFrontier0 or upflagUpFrontier1 or upflagUpFrontier2 or
upflagUpFrontier3 or upflagUpFrontier4
// // downFractal
// bool downflagDownFrontier = true
// bool downflagUpFrontier0 = true
// bool downflagUpFrontier1 = true
// bool downflagUpFrontier2 = true
// bool downflagUpFrontier3 = true
// bool downflagUpFrontier4 = true
// for i = 1 to n
// downflagDownFrontier := downflagDownFrontier and (low[n-i] > low[n])
// downflagUpFrontier0 := downflagUpFrontier0 and (low[n+i] > low[n])
// downflagUpFrontier1 := downflagUpFrontier1 and (low[n+1] >= low[n] and
low[n+i + 1] > low[n])
// downflagUpFrontier2 := downflagUpFrontier2 and (low[n+1] >= low[n] and
low[n+2] >= low[n] and low[n+i + 2] > low[n])
// downflagUpFrontier3 := downflagUpFrontier3 and (low[n+1] >= low[n] and
low[n+2] >= low[n] and low[n+3] >= low[n] and low[n+i + 3] > low[n])
// downflagUpFrontier4 := downflagUpFrontier4 and (low[n+1] >= low[n] and
low[n+2] >= low[n] and low[n+3] >= low[n] and low[n+4] >= low[n] and low[n+i + 4] >
low[n])
// flagDownFrontier = downflagUpFrontier0 or downflagUpFrontier1 or
downflagUpFrontier2 or downflagUpFrontier3 or downflagUpFrontier4
// var zz = array.new_float()
// var yy = array.new_int()
// if upFractal
// array.push(zz, high)
// array.push(yy,bar_index)
// if downFractal
// array.push(zz, low)
// array.push(yy,bar_index)
var Depth = 3
var Deviation = 1
var Backstep = 1
if(indi_type==2)
Depth := 2
var zz = array.new_float()
var yy = array.new_int()
x1 = down ? lw : hg
y1 = down ? low[lw] : high[hg]
if down == down[1]
if repaint
if(array.size(zz)>0)
array.pop(zz)
array.pop(yy)
down
if down != down[1]
if down
last_h := hg
else
last_l := lw
if not repaint
nx = down?last_h:last_l
array.push(zz, (down ? low[last_l] : high[last_h]))
array.push(yy,bar_index-(down?last_l:last_h))
down
if repaint
array.push(zz, y1)
array.push(yy,bar_index-x1)
allowPlot()=>
(last_bar_index-bar_index<=max_bars)
checkTrigger()=>
value1 = 0.0, value2 = 0.0, value3 = 0.0, value4 = 0.0, counter = 0, res =
false, pos = 0
if(array.size(zz)>=4 and array.size(yy)>=4)
for x = array.size(zz)-1 to 0
if(x<array.size(zz))
price = array.get(zz,x)
counter += 1
if(counter == 1)
value1 := price
if(counter == 2)
value2 := price
pos := array.get(yy,x)
if(counter == 3)
value3 := price
if(counter == 4)
value4 := price
break
if((value1<value2 and value1>value3 and value4>value2) or
(value1>value2 and value1<value3 and value4<value2))
res := true
[res, math.max(value1,value2), math.min(value1,value2), pos]
updateExpansionLines(Time,Line,clear,checktimes)=>
if(array.size(Line)>0)
for x = 0 to array.size(Line)-1
if(x < array.size(checktimes) and x < array.size(Line))
if(Time>array.get(checktimes,x))
line.set_x2(array.get(Line,x),Time)
if(clear)
array.remove(Line,x)
updateExpansionLines(time,expansionLines,false,check)
updateExpansionLines(time,minorExpansionLines,false,checkMinor)
getHighOffset(Time)=>
x = 1, hi = high, res = 0
while(time[x]>=Time)
if(high[x]>hi)
hi := high[x]
res := x
x += 1
res
getLowOffset(Time)=>
x = 1, lo = low, res = 0
while(time[x]>=Time)
if(low[x]<lo)
lo := low[x]
res := x
x += 1
res
checkCross(line_array, price)=>
result = false
Prices = price
if array.size(line_array) > 0
for x = 0 to array.size(line_array)-1
Price = line.get_y1(array.get(line_array,x))
if (Prices > Price and Prices[1] <= Price) or (Prices < Price and
Prices[1] >= Price)
result := true
result
operateMinorBox(price,hi_price,lo_price,Time)=>
var lastMinorExp = 0
confirm = false
array.push(expansionLines,line.new(time2,ppp,time,ppp,xloc.bar_time,extend.none,Maj
or_Expansion_Line_Color,
(Major_Expansion_Line_Style=="Solid"?
line.style_solid:Major_Expansion_Line_Style=="Dotted"?line.style_dotted:
line.style_dashed),Major_Expansion_Line_Thickness))
array.push(check,time2)
hi_pos = getHighOffset(time2)
lo_pos = getLowOffset(time2)
if(not origCrossedHigh)
rrr = low[lo_pos]
array.push(majorBoxLines,
line.new(time[lo_pos],rrr,Time,rrr,xloc.bar_time,extend.none,Buy_Line_Color,
(Buy_Line_Style=="Solid"?
line.style_solid:Buy_Line_Style=="Dotted"?line.style_dotted:line.style_dashed),
Buy_Line_Thickness))
array.push(majorBoxLineType,0)
else if(not origCrossedLow)
rrr = high[hi_pos]
array.push(majorBoxLines,
line.new(time[hi_pos],rrr,Time,rrr,xloc.bar_time,extend.none,Sell_Line_Color,
(Sell_Line_Style=="Solid"?
line.style_solid:Sell_Line_Style=="Dotted"?line.style_dotted:line.style_dashed),
Sell_Line_Thickness))
array.push(majorBoxLineType,1)
array.push(majorBoxLineRef,time2)
array.push(Crossed,false)
true
else if(not array.get(minorCrossedHigh,x) and not
array.get(minorCrossedLow,x))
box.set_right(array.get(minorBoxes,x),Time)
true
else if(show_minor_expansion and time1!=lastMinorExp)
updateExpansionLines(time2,minorExpansionLines,true,checkMinor)
array.push(minorExpansionLines,
line.new(time2,ppp,time,ppp,xloc.bar_time,extend.none,Minor_Expansion_Line_Color,
(Minor_Expansion_Line_Style=="Solid"?
line.style_solid:Minor_Expansion_Line_Style=="Dotted"?line.style_dotted:
line.style_dashed),Minor_Expansion_Line_Thickness))
array.push(checkMinor,time2)
lastMinorExp := time1
true
confirm
operateLiquidity(hi_price,lo_price,Time)=>
result = false
if(array.size(majorBoxLines)>0 and array.size(majorBoxLineRef)>0 and
array.size(Crossed)>0)
z = array.size(majorBoxLines)-1
for x = 0 to z
line_price = line.get_y2(array.get(majorBoxLines,x))
hi_pos = getHighOffset(array.get(majorBoxLineRef,x))
lo_pos = getLowOffset(array.get(majorBoxLineRef,x))
qq = 0.0
if(array.get(majorBoxLineType,x)==0 and lo_price <= line_price)
if not array.get(Crossed,x)
result := true
qq := high[hi_pos]
if x == z
array.set(majorBoxLines,x,line.new(time[hi_pos],qq,Time,qq,xloc.bar_time,extend.non
e,Sell_Line_Color,(Sell_Line_Style=="Solid"?line.style_solid:
Sell_Line_Style=="Dotted"?
line.style_dotted:line.style_dashed),Sell_Line_Thickness))
array.set(majorBoxLineType,x,1)
else
array.set(Crossed,x,true)
else if(array.get(majorBoxLineType,x)==1 and hi_price >= line_price)
if not array.get(Crossed,x)
result := true
qq := low[lo_pos]
if x == z
array.set(majorBoxLines,x,line.new(time[lo_pos],qq,Time,qq,xloc.bar_time,extend.non
e,Buy_Line_Color,(Buy_Line_Style=="Solid"?line.style_solid:
Buy_Line_Style=="Dotted"?
line.style_dotted:line.style_dashed),Buy_Line_Thickness))
array.set(majorBoxLineType,x,0)
else
array.set(Crossed,x,true)
if not array.get(Crossed,x)
line.set_x2(array.get(majorBoxLines,x),Time)
result
major_line_confirm = operateMinorBox(close,high,low,time)
major_line_cross = checkCross(expansionLines,close)
liquidity_line_touch = operateLiquidity(high,low,time)
//@version=5
//ndicator("Smart Money Breakouts [ChartPrime]", overlay=true,
max_labels_count=500, max_lines_count=500)
color GREEN = #1592e6
color TAIL = #673ab7
color RED = #673ab7
color _Green = #1592e6
color OFF = color.new(color.red,100)
string CORE = "�� Core Settings �"
var array<int> score = array.new_int(2,0)
//
var float UpdatedHigh = na
var float UpdatedLow = na
var bool ShortTrade = false
var bool TradeisON = false
var bool LongTrade = false
var int HighIndex = na
var bool phActive = false
var bool plActive = false
var int LowIndex = na
var bool HBreak = false
var line tpLine = na
var label LAB = na
var float TP = 0.0
var float SL = 0.0
int Sync = bar_index
bool BUY = false
bool SELL = false
type Vol
array<float> Total
array<float> Green
array<float> Red
array<float> SCR
Volume = Vol.new(
array.new_float(),
array.new_float(),
array.new_float(),
array.new_float()
Adj = volAdj(30)
VolCal(Index,Sync) =>
Bars = math.abs(Index - Sync)
for i = 0 to Bars -1
Volume.SCR.push(close[i])
for i = 0 to Volume.SCR.size() -1
Volume.Total.push(volume[i])
if ta.change(fixnan(PH)) != 0
UpdatedHigh := PH
phActive := true
HighIndex := Sync - period
if ta.change(fixnan(PL)) != 0
UpdatedLow := PL
plActive := true
LowIndex := Sync - period
// LONG
if ScrHigh > UpdatedHigh and plActive
BUY := true
phActive := false
//Sell
if ScrLow < UpdatedLow and phActive
SELL := true
plActive := false
// lets Draw
if true
if TradeFire and not TradeisON
TP := switch
Long => high + (Adj * Tar)
Short => low - (Adj * Tar)
SL := switch
Long => low - (Adj * Tar)
Short => high + (Adj * Tar)
TradeisON:= true
if true
line.new(bar_index,
Long ? high : low,
bar_index,
TP,
width=1,
color = TAIL,
style= line.style_dashed)
tpLine:= line.new(bar_index,
TP,
bar_index+2,
TP,
style= line.style_dashed,
color = TAIL
)
LAB:=label.new(bar_index,
TP,
"Target",
color = TAIL,
style= label.style_label_left,
size=size.small,
textcolor = color.white
)
if TradeisON
line.set_x2(tpLine,bar_index)
label.set_x(LAB,bar_index+1)
if close >= SL
score.set(1,score.get(1)+1)
label.set_color(LAB,color.new(RED,70))
label.set_tooltip(LAB,"Stoploss Hit : "+
str.tostring(math.round_to_mintick(SL)))
TradeisON:=false
// where is my table ?!
var tb = table.new(position.top_right, 3, 3,
bgcolor= color.new(color.gray,80))
if barstate.islast
//-- END --
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0
International (CC Dy-NC-SA 4.0) https://creativecommons.org/licenses/Dy-nc-sa/4.0/
// © LuxAlgo
//@version=5
//indicator("Breaker Blocks with Signals [LuxAlgo]", max_lines_count=500,
max_boxes_count=500, max_labels_count=500, max_bars_back=3000, overlay=true)
//------------------------------------------------------------------------------
//Settings
//-----------------------------------------------------------------------------{
shZZ = false
len = input.int ( 5 ,
title=' Length' , inline='MS' , group='Market Structure'
, minval=1, maxval=10
)
//Breaker block
breakerCandleOnlyBody = input.bool ( false , title='Use only candle body'
, group='Breaker Block' )
breakerCandle_2Last = input.bool ( false , title='Use 2 candles instead of 1'
, group='Breaker Block', tooltip='In the same direction')
tillFirstBreak = input.bool ( true , title='Stop at first break of
center line' , group='Breaker Block' )
//PD array
onlyWhenInPDarray = input.bool ( false , title='Only when E is in
Premium/Discount Array', group='PD array' )
showPDarray = input.bool ( false , title='show Premium/Discount Zone'
, group='PD array' )
showBreaks = input.bool ( false , title='Highlight Swing Breaks'
, group='PD array' )
showSPD = input.bool ( true , title='Show Swings/PD Arrays'
, group='PD array' )
PDtxtCss = input.color ( color.silver, 'Text Color' , group='PD
array' )
PDSCss = input.color ( color.silver, 'Swing Line Color', group='PD
array' )
//Take profit
iTP = input.bool ( false , title='Enable
TP' , inline='RR' , group='TP'
)
tpCss = input.color ( #2157f3, title='' ,
inline='RR', group='TP' )
R1a = input.float ( 1 , title='R:R 1', minval= 1,
maxval=1, inline='RR1', group='TP' )
R2a = input.float ( 2 , title= ':' , minval=.2,
step= .1, inline='RR1', group='TP' )
R1b = input.float ( 1 , title='R:R 2', minval= 1,
maxval=1, inline='RR2', group='TP' )
R2b = input.float ( 3 , title= ':' , minval=.2,
step= .1, inline='RR2', group='TP' )
R1c = input.float ( 1 , title='R:R 3', minval= 1,
maxval=1, inline='RR3', group='TP' )
R2c = input.float ( 4 , title= ':' , minval=.2,
step= .1, inline='RR3', group='TP' )
//Colors
cBBplusA = input.color (color.rgb(12, 181, 26, 93)
,
title=' ' , inline='bl' , group='Colours
+BB Last Swings' )
cBBplusB = input.color (color.rgb(12, 181, 26, 85)
,
title='' , inline='bl' , group='Colours
+BB Last Swings' )
cSwingBl = input.color (color.rgb(255, 82, 82, 85)
,
title=' ' , inline='bl' , group='Colours
+BB Last Swings' )
cBB_minA = input.color (color.rgb(255, 17, 0, 95)
,
title=' ' , inline='br' , group='Colours -
BB Last Swings' )
cBB_minB = input.color (color.rgb(255, 17, 0, 85)
,
title='' , inline='br' , group='Colours -
BB Last Swings' )
cSwingBr = input.color (color.rgb(0, 137, 123, 85)
,
title=' ' , inline='br' , group='Colours -
BB Last Swings' )
_arrowup = '▲'
_arrowdn = '▼'
_c = '●'
_x = '❌'
//-----------------------------------------------------------------------------}
//General Calculations
//-----------------------------------------------------------------------------{
per = last_bar_index - bar_index <= 2000
mx = math.max(close , open )
mn = math.min(close , open )
atr = ta.atr (10 )
n = bar_index
hi = high
lo = low
mCxSize = 50
//-----------------------------------------------------------------------------}
//User Defined Types
//-----------------------------------------------------------------------------{
type ZZ
int [] d
int [] x
float [] y
line [] l
bool [] b
type mss
int dir
line [] l_mssBl
line [] l_mssBr
line [] l_bosBl
line [] l_bosBr
label[] lbMssBl
label[] lbMssBr
label[] lbBosBl
label[] lbBosBr
type block
int dir
bool Broken
bool Mitigated
box BB_boxA
box BB_boxB
line BB_line
box FVG_box
line line_1
line line_2
bool Broken_1
bool Broken_2
box PDa_boxA
box PDa_boxB
box PDa_box1
line PDaLine1
label PDaLab_1
box PDa_box2
line PDaLine2
label PDaLab_2
bool PDbroken1
bool PDbroken2
line TP1_line
line TP2_line
line TP3_line
bool TP1_hit
bool TP2_hit
bool TP3_hit
bool scalp
label HL
label[] aLabels
//-----------------------------------------------------------------------------}
//Variables
//-----------------------------------------------------------------------------{
BBplus = 0, signUP = 1, cnclUP = 2, LL1break = 3, LL2break = 4, SW1breakUP = 5
, SW2breakUP = 6, tpUP1 = 7, tpUP2 = 8, tpUP3 = 9, BB_endBl =10
BB_min =11, signDN =12, cnclDN =13, HH1break =14, HH2break =15, SW1breakDN =16
, SW2breakDN =17, tpDN1 =18, tpDN2 =19, tpDN3 =20, BB_endBr =21
signals =
array.from(
false // BBplus
, false // signUP
, false // cnclUP
, false // LL1break
, false // LL2break
, false // SW1breakUP
, false // SW2breakUP
, false // tpUP1
, false // tpUP2
, false // tpUP3
, false // BB_endBl
, false // BB_min
, false // signDN
, false // cnclDN
, false // HH1break
, false // HH2break
, false // SW1breakDN
, false // SW2breakDN
, false // tpDN1
, false // tpDN2
, false // tpDN3
, false // BB_endBr
)
var ZZ aZZ =
ZZ.new(
array.new < int >(mCxSize, 0),
array.new < int >(mCxSize, 0),
array.new < float >(mCxSize, na),
array.new < line >(mCxSize, na),
array.new < bool >(mCxSize, na))
//-----------------------------------------------------------------------------}
//Functions/methods
//-----------------------------------------------------------------------------{
method in_out(ZZ aZZ, int d, int x1, float y1, int x2, float y2, color col, bool b)
=>
aZZ.d.unshift(d), aZZ.x.unshift(x2), aZZ.y.unshift(y2), aZZ.b.unshift(b),
aZZ.d.pop(), aZZ.x.pop(), aZZ.y.pop(), aZZ.b.pop()
if shZZ
aZZ.l.unshift(line.new(x1, y1, x2, y2, color= col)), aZZ.l.pop().delete()
method setLine(line ln, int x1, float y1, int x2, float y2) => ln.set_xy1(x1, y1),
ln.set_xy2(x2, y2)
max_bars_back(time, 1000)
var int dir= na, var int x1= na, var float y1= na, var int x2= na, var float
y2= na
sz = aZZ.d.size( )
x2 := bar_index -1
ph = ta.pivothigh(hi, left, 1)
pl = ta.pivotlow (lo, left, 1)
if ph
dir := aZZ.d.get (0)
x1 := aZZ.x.get (0)
y1 := aZZ.y.get (0)
y2 := nz(hi[1])
if dir < 1 // if previous point was a pl, add, and change direction ( 1)
aZZ.in_out( 1, x1, y1, x2, y2, col, true)
else
if dir == 1 and ph > y1
aZZ.x.set(0, x2), aZZ.y.set(0, y2)
if shZZ
aZZ.l.get(0).set_xy2(x2, y2)
if pl
dir := aZZ.d.get (0)
x1 := aZZ.x.get (0)
y1 := aZZ.y.get (0)
y2 := nz(lo[1])
if dir > -1 // if previous point was a ph, add, and change direction (-1)
aZZ.in_out(-1, x1, y1, x2, y2, col, true)
else
if dir == -1 and pl < y1
aZZ.x.set(0, x2), aZZ.y.set(0, y2)
if shZZ
aZZ.l.get(0).set_xy2(x2, y2)
iH = aZZ.d.get(2) == 1 ? 2 : 1
iL = aZZ.d.get(2) == -1 ? 2 : 1
switch
// MSS Bullish
close > aZZ.y.get(iH) and aZZ.d.get(iH) == 1 and MSS.dir < 1 and per =>
float green1prT = na
float green1prB = na
float avg = na
green1idx = n - i
green1prT := breakerCandleOnlyBody ? mx[i] : high[i]
green1prB := breakerCandleOnlyBody ? mn[i] : low [i]
if breakerCandle_2Last
if close[i +1] > open[i +1]
green2prT = breakerCandleOnlyBody ? mx[i +1] :
high[i +1]
green2prB = breakerCandleOnlyBody ? mn[i +1] : low
[i +1]
if green2prT > green1prT or green2prB < green1prB
green1idx -= 1
green1prT := math.max(green1prT, green2prT)
green1prB := math.min(green1prB, green2prB)
// Breaker Block +
avg := math.avg(green1prB, green1prT)
while BB.aLabels.size() > 0
BB.aLabels.pop().delete()
BB.PDa_boxA.delete(), BB.PDa_boxB.delete(), BB.dir := 1
BB.BB_boxA.set_left (green1idx)
BB.BB_boxA.set_top (green1prT)
BB.BB_boxA.set_right ( n )
BB.BB_boxA.set_bottom (green1prB)
BB.BB_boxA.set_bgcolor(cBBplusA )
BB.BB_boxB.set_left ( n )
BB.BB_boxB.set_top (green1prT)
BB.BB_boxB.set_right ( n + 8)
BB.BB_boxB.set_bottom (green1prB)
BB.BB_boxB.set_bgcolor(cBBplusB )
BB.BB_boxB.set_text('+BB')
BB.BB_boxB.set_text_color(cBBplusB.notransp())
BB.BB_boxB.set_text_valign(text.align_bottom)
if showSPD
BB.line_1.set_xy1(Cx, Cy), BB.line_1.set_xy2(n , Cy),
BB.Broken_1 := false
BB.line_2.set_xy1(Ex, Ey), BB.line_2.set_xy2(n , Ey),
BB.Broken_2 := false
BB.HL.set_xy(Ex, Ey),
BB.HL.set_style(label.style_label_up), BB.HL.set_text('LL')
BB.TP1_hit := false
BB.TP2_hit := false
BB.TP3_hit := false
BB.Broken := false
BB.Mitigated := false
BB.scalp := false
BB.PDbroken1 := false
BB.PDbroken2 := false
BB.PDaLab_1.set_style(label.style_label_lower_left)
cnt := 1
hh1 := getY
1 =>
if getY - getY2 > hh1
BB.PDa_box2.set_lefttop (getX,
getY )
BB.PDaLine2.set_xy1 (getX,
getY )
BB.PDa_box2.set_rightbottom(n , getY
- getY2)
BB.PDaLine2.set_xy2 (n , getY
)
BB.PDa_box2.set_bgcolor
( cSwingBl )
BB.PDaLab_2.set_xy
( getX, getY )
BB.PDaLab_2.set_size
( size.small )
BB.PDaLab_2.set_textcolor
( PDtxtCss )
BB.PDaLab_2.set_text ('Premium PD
Array')
BB.PDaLab_2.set_style(label.style_label_lower_left)
cnt := 2
if cnt == 2
break
I = green1prT - green1prB
E1 = green1prT + (I * R2a / R1a)
E2 = green1prT + (I * R2b / R1b)
E3 = green1prT + (I * R2c / R1c)
if iTP
if not BB.TP1_hit
BB.TP1_line.set_xy1(n, E1)
BB.TP1_line.set_xy2(n + 20, E1)
if not BB.TP2_hit
BB.TP2_line.set_xy1(n, E2)
BB.TP2_line.set_xy2(n + 20, E2)
if not BB.TP3_hit
BB.TP3_line.set_xy1(n, E3)
BB.TP3_line.set_xy2(n + 20, E3)
signals.set(BBplus, true)
alert('+BB', alert.freq_once_per_bar_close)
BB.aLabels.unshift(createLab('u', low, cBBplusB.notransp(),
_arrowup, size.large))
break
MSS.dir := 1
// MSS Bearish
close < aZZ.y.get(iL) and aZZ.d.get(iL) == -1 and MSS.dir > -1 and per =>
Ex = aZZ.x.get(iL -1), Ey = aZZ.y.get(iL -1)
Dx = aZZ.x.get(iL ), Dy = aZZ.y.get(iL ), DyMn = mn[n - Dx]
Cx = aZZ.x.get(iL +1), Cy = aZZ.y.get(iL +1)
Bx = aZZ.x.get(iL +2), By = aZZ.y.get(iL +2), ByMn = mn[n - Bx]
Ax = aZZ.x.get(iL +3), Ay = aZZ.y.get(iL +3), AyMx = mx[n - Ax]
_y = math.min(ByMn, DyMn)
//_x = _y == ByMn ? Bx : Dx
mid = AyMx - ((AyMx - _y) / 2) // 50% fib A- min(B, D)
isOK = onlyWhenInPDarray ? Ay > Cy and Ay > Ey and Ey > mid : true
//
float red_1_prT = na
float red_1_prB = na
float avg = na
if Ey > Cy and Cx != Dx and isOK
// latest LL to LL further -> search first red bar
for i = n - Dx to n - Cx
if close[i] < open[i]
// reset previous swing box's
BB.PDa_box1.set_lefttop(na, na), BB.PDaLine1.set_xy1(na,
na), BB.PDaLab_1.set_xy(na, na)
BB.PDa_box2.set_lefttop(na, na), BB.PDaLine2.set_xy1(na,
na), BB.PDaLab_2.set_xy(na, na)
red_1_idx = n - i
red_1_prT := breakerCandleOnlyBody ? mx[i] : high[i]
red_1_prB := breakerCandleOnlyBody ? mn[i] : low [i]
if breakerCandle_2Last
if close[i +1] < open[i +1]
red_2_prT = breakerCandleOnlyBody ? mx[i +1] :
high[i +1]
red_2_prB = breakerCandleOnlyBody ? mn[i +1] : low
[i +1]
if red_2_prT > red_1_prT or red_2_prB < red_1_prB
red_1_idx -= 1
red_1_prT := math.max(red_1_prT, red_2_prT)
red_1_prB := math.min(red_1_prB, red_2_prB)
// Breaker Block -
avg := math.avg(red_1_prB, red_1_prT)
while BB.aLabels.size() > 0
BB.aLabels.pop().delete()
BB.PDa_boxA.delete(), BB.PDa_boxB.delete(), BB.dir := -1
BB.BB_boxA.set_left (red_1_idx)
BB.BB_boxA.set_top (red_1_prT)
BB.BB_boxA.set_right ( n )
BB.BB_boxA.set_bottom (red_1_prB)
BB.BB_boxA.set_bgcolor(cBB_minA )
BB.BB_boxB.set_left (n)
BB.BB_boxB.set_top (red_1_prT)
BB.BB_boxB.set_right ( n + 8)
BB.BB_boxB.set_bottom (red_1_prB)
BB.BB_boxB.set_bgcolor(cBB_minB )
BB.BB_boxB.set_text('-BB')
BB.BB_boxB.set_text_color(cBB_minB.notransp())
BB.BB_boxB.set_text_valign(text.align_top)
if showSPD
BB.line_1.set_xy1(Cx, Cy), BB.line_1.set_xy2(n , Cy),
BB.Broken_1 := false
BB.line_2.set_xy1(Ex, Ey), BB.line_2.set_xy2(n , Ey),
BB.Broken_2 := false
BB.HL.set_xy(Ex, Ey),
BB.HL.set_style(label.style_label_down), BB.HL.set_text('HH'),
BB.HL.set_textcolor(PDtxtCss)
BB.TP1_hit := false
BB.TP2_hit := false
BB.TP3_hit := false
BB.Broken := false
BB.Mitigated := false
BB.scalp := false
BB.PDbroken1 := false
BB.PDbroken2 := false
// Previous swings
cnt = 0, ll1 = low
for c = 0 to sz -2
getX = aZZ.x.get(c)
getY = aZZ.y.get(c)
if getY < ll1 and aZZ.d.get(c) == -1 and showSPD
getY2 = (mx[n - getX] - low[n - getX]) / 4
switch cnt
0 =>
BB.PDa_box1.set_lefttop (getX, getY +
getY2)
BB.PDaLine1.set_xy1 (getX,
getY )
BB.PDa_box1.set_rightbottom( n ,
getY )
BB.PDaLine1.set_xy2 ( n ,
getY )
BB.PDa_box1.set_bgcolor ( cSwingBr
)
BB.PDaLab_1.set_xy ( getX,
getY )
BB.PDaLab_1.set_size
( size.small )
BB.PDaLab_1.set_textcolor ( PDtxtCss )
BB.PDaLab_1.set_text ('Discount PD
Array')
BB.PDaLab_1.set_style(label.style_label_upper_left)
cnt := 1
ll1 := getY
1 =>
if getY + getY2 < ll1
BB.PDa_box2.set_lefttop (getX, getY
+ getY2)
BB.PDaLine2.set_xy1 (getX,
getY )
BB.PDa_box2.set_rightbottom( n , getY )
BB.PDaLine2.set_xy2
( n , getY )
BB.PDa_box2.set_bgcolor
( cSwingBr )
BB.PDaLab_2.set_xy
( getX, getY )
BB.PDaLab_2.set_size
( size.small )
BB.PDaLab_2.set_textcolor
( PDtxtCss )
BB.PDaLab_2.set_text ('Discount PD
Array')
BB.PDaLab_2.set_style(label.style_label_upper_left)
cnt := 2
if cnt == 2
break
I = red_1_prT - red_1_prB
E1 = red_1_prB - (I * R2a / R1a)
E2 = red_1_prB - (I * R2b / R1b)
E3 = red_1_prB - (I * R2c / R1c)
if iTP
if not BB.TP1_hit
BB.TP1_line.set_xy1(n, E1)
BB.TP1_line.set_xy2(n + 20, E1)
if not BB.TP2_hit
BB.TP2_line.set_xy1(n, E2)
BB.TP2_line.set_xy2(n + 20, E2)
if not BB.TP3_hit
BB.TP3_line.set_xy1(n, E3)
BB.TP3_line.set_xy2(n + 20, E3)
signals.set(BB_min, true)
alert('-BB', alert.freq_once_per_bar_close)
BB.aLabels.unshift(createLab('d', high,
cBB_minB.notransp(), _arrowdn, size.large))
break
MSS.dir := -1
//-----------------------------------------------------------------------------}
//Calculations
//-----------------------------------------------------------------------------{
draw(len, tpCss)
lft = BB.BB_boxB.get_left ()
top = BB.BB_boxB.get_top ()
btm = BB.BB_boxB.get_bottom()
avg = BB.BB_line.get_y2 ()
l_1 = BB.line_1.get_y2 ()
l_2 = BB.line_2.get_y2 ()
TP1 = BB.TP1_line.get_y2 ()
TP2 = BB.TP2_line.get_y2 ()
TP3 = BB.TP3_line.get_y2 ()
switch BB.dir
1 =>
if not BB.Mitigated
if close < btm
BB.Mitigated := true
signals.set(BB_endBl, true)
alert('+BB Mitigated', alert.freq_once_per_bar_close)
BB.BB_boxB.set_right(n)
BB.BB_line.set_x2 (n)
else
BB.BB_boxB.set_right(n + 8)
BB.BB_line.set_x2 (n + 8)
BB.TP1_line.set_x2 (n)
BB.TP2_line.set_x2 (n)
BB.TP3_line.set_x2 (n)
if n > BB.BB_boxB.get_left()
if not BB.Broken
if BB.scalp
if not BB.TP1_hit and open < TP1 and high > TP1
BB.TP1_hit := true
signals.set(tpUP1, true)
alert('TP UP 1', alert.freq_once_per_bar)
BB.aLabels.unshift(createLab('c', TP1, #ff00dd, _c))
if not BB.TP2_hit and open < TP2 and high > TP2
BB.TP2_hit := true
signals.set(tpUP2, true)
alert('TP UP 2', alert.freq_once_per_bar)
BB.aLabels.unshift(createLab('c', TP2, #ff00dd, _c))
if not BB.TP3_hit and open < TP3 and high > TP3
BB.TP3_hit := true
signals.set(tpUP3, true)
alert('TP UP 3', alert.freq_once_per_bar)
BB.aLabels.unshift(createLab('c', TP3, #ff00dd, _c))
switch
open > avg and open < top and close > top =>
BB.TP1_hit := false
BB.TP2_hit := false
BB.TP3_hit := false
BB.scalp := true
signals.set(signUP, true)
alert('signal UP', alert.freq_once_per_bar_close)
BB.aLabels.unshift(createLab('u', low, color.lime,
_arrowup, size.normal))
close < avg and close > btm =>
BB.Broken := true
BB.scalp := false
signals.set(cnclUP, true)
alert('cancel UP', alert.freq_once_per_bar_close)
BB.aLabels.unshift(createLab('u', low, color.orange,
_x))
else
// reset
if not tillFirstBreak and close > top
BB.Broken := false
BB.scalp := true
signals.set(BBplus, true)
alert('+BB (R)', alert.freq_once_per_bar_close)
BB.aLabels.unshift(createLab('u', low, color.blue, 'R',
size.normal))
if not BB.Broken_1
BB.line_1.set_x2(n)
if close < l_1
BB.Broken_1 := true
signals.set(LL1break, true)
alert('LL 1 break', alert.freq_once_per_bar_close)
if showBreaks
BB.aLabels.unshift(createLab('c', low, #c00000, _c))
if not BB.Broken_2
BB.line_2.set_x2(n)
if close < l_2
BB.Broken_2 := true
signals.set(LL2break, true)
alert('LL 2 break', alert.freq_once_per_bar_close)
if showBreaks
BB.aLabels.unshift(createLab('c', low, #c00000, _c))
if not BB.PDbroken1
BB.PDa_box1.set_right(n)
BB.PDaLine1.set_x2 (n)
if close > BB.PDa_box1.get_top() and n > BB.PDa_box1.get_left()
BB.PDbroken1 := true
signals.set(SW1breakUP, true)
alert('Swing UP 1 break', alert.freq_once_per_bar_close)
if showBreaks
BB.aLabels.unshift(createLab('c', high, #c00000, _c))
if not BB.PDbroken2
BB.PDa_box2.set_right(n)
BB.PDaLine2.set_x2 (n)
if close > BB.PDa_box2.get_top() and n > BB.PDa_box2.get_left()
BB.PDbroken2 := true
signals.set(SW2breakUP, true)
alert('Swing UP 2 break', alert.freq_once_per_bar_close)
if showBreaks
BB.aLabels.unshift(createLab('c', high, #c00000, _c))
-1 =>
if not BB.Mitigated
if close > top
BB.Mitigated := true
signals.set(BB_endBr, true)
alert('-BB Mitigated', alert.freq_once_per_bar_close)
if showBreaks
BB.aLabels.unshift(createLab('d', high, cBB_minB.notransp(),
_c))
BB.BB_boxB.set_right(n)
BB.BB_line.set_x2 (n)
else
BB.BB_boxB.set_right(n + 8)
BB.BB_line.set_x2 (n + 8)
BB.TP1_line.set_x2 (n)
BB.TP2_line.set_x2 (n)
BB.TP3_line.set_x2 (n)
if n > BB.BB_boxB.get_left()
if not BB.Broken
if BB.scalp
if not BB.TP1_hit and open > TP1 and low < TP1
BB.TP1_hit := true
signals.set(tpDN1, true)
alert('TP DN 1', alert.freq_once_per_bar)
BB.aLabels.unshift(createLab('c', TP1, #ff00dd, _c))
if not BB.TP2_hit and open > TP2 and low < TP2
BB.TP2_hit := true
signals.set(tpDN2, true)
alert('TP DN 2', alert.freq_once_per_bar)
BB.aLabels.unshift(createLab('c', TP2, #ff00dd, _c))
if not BB.TP3_hit and open > TP3 and low < TP3
BB.TP3_hit := true
signals.set(tpDN3, true)
alert('TP DN 3', alert.freq_once_per_bar)
BB.aLabels.unshift(createLab('c', TP3, #ff00dd, _c))
switch
open < avg and open > btm and close < btm =>
BB.TP1_hit := false
BB.TP2_hit := false
BB.TP3_hit := false
BB.scalp := true
signals.set(signDN, true)
alert('signal DN', alert.freq_once_per_bar_close)
BB.aLabels.unshift(createLab('d', high, color.orange,
_arrowdn, size.normal))
close > avg and close < top =>
BB.Broken := true
BB.scalp := false
signals.set(cnclDN, true)
alert('cancel DN', alert.freq_once_per_bar_close)
BB.aLabels.unshift(createLab('d', high, color.red ,
_x))
else
// reset
if not tillFirstBreak and close < btm
BB.Broken := false
BB.scalp := true
signals.set(BB_min, true)
alert('-BB (R)', alert.freq_once_per_bar_close)
BB.aLabels.unshift(createLab('d', high, color.blue, 'R',
size.normal))
if not BB.Broken_1
BB.line_1.set_x2(n)
if close > l_1
BB.Broken_1 := true
signals.set(HH1break, true)
alert('HH 1 break', alert.freq_once_per_bar_close)
if showBreaks
BB.aLabels.unshift(createLab('c', high, #c00000, _c))
if not BB.Broken_2
BB.line_2.set_x2(n)
if close > l_2
BB.Broken_2 := true
signals.set(HH2break, true)
alert('HH 2 break', alert.freq_once_per_bar_close)
if showBreaks
BB.aLabels.unshift(createLab('c', high, #c00000, _c))
if not BB.PDbroken1
BB.PDa_box1.set_right(n)
BB.PDaLine1.set_x2 (n)
if close < BB.PDa_box1.get_bottom() and n > BB.PDa_box1.get_left()
BB.PDbroken1 := true
signals.set(SW1breakDN, true)
alert('Swing DN 1 break', alert.freq_once_per_bar_close)
if showBreaks
BB.aLabels.unshift(createLab('c', low, #c00000, _c))
if not BB.PDbroken2
BB.PDa_box2.set_right(n)
BB.PDaLine2.set_x2 (n)
if close < BB.PDa_box2.get_bottom() and n > BB.PDa_box2.get_left()
BB.PDbroken2 := true
signals.set(SW2breakDN, true)
alert('Swing DN 2 break', alert.freq_once_per_bar_close)
if showBreaks
BB.aLabels.unshift(createLab('c', low, #c00000, _c))
}
//@version=5
//ndicator("Buyside & Sellside Liquidity [LuxAlgo]", "LuxAlgo - Buyside & Sellside
Liquidity", overlay = true, max_lines_count = 500, max_boxes_count = 500,
max_bars_back = 3000)
//------------------------------------------------------------------------------
//Settings
//-----------------------------------------------------------------------------{
liqGrp = 'Liquidity Detection'
liqLen = input.int (7, title = 'Detection Length', minval = 3, maxval = 13,
inline = 'LIQ', group = liqGrp)
liqMar = 10 / input.float (6.9, 'Margin', minval = 4, maxval = 9, step = 0.1,
inline = 'LIQ', group = liqGrp)
//-----------------------------------------------------------------------------}
//General Calculations
//-----------------------------------------------------------------------------{
maxSize = 50
atr = ta.atr(10)
atr200 = ta.atr(200)
per = mode == 'Present' ? last_bar_index - bar_index <= 500 : true
//-----------------------------------------------------------------------------}
//User Defined Types
//-----------------------------------------------------------------------------{
// @type used to store pivot high/low data
//
// @field d (array<int>) The array where the trend direction is to be
maintained
// @field x (array<int>) The array where the bar index value of pivot high/low
is to be maintained
// @field y (array<float>) The array where the price value of pivot high/low is
to be maintained
type ZZ
int [] d
int [] x
float [] y
type bar
float o = open
float h = high
float l = low
float c = close
int i = bar_index
type liq
box bx
box bxz
box bxt
bool brZ
bool brL
line ln
line lne
//-----------------------------------------------------------------------------}
//Variables
//-----------------------------------------------------------------------------{
var ZZ aZZ = ZZ.new(
array.new <int> (maxSize, 0),
array.new <int> (maxSize, 0),
array.new <float>(maxSize, na)
)
bar b = bar.new()
//-----------------------------------------------------------------------------}
//Functions/methods
//-----------------------------------------------------------------------------{
// @function maintains arrays
// it prepends a `value` to the arrays and removes their oldest
element at last position
// @param aZZ (UDT<array<int>, array<int>, array<float>>) The UDT obejct of
arrays
// @param _d (array<int>) The array where the trend direction is maintained
// @param _x (array<int>) The array where the bar index value of pivot
high/low is maintained
// @param _y (array<float>) The array where the price value of pivot
high/low is maintained
//
// @returns none
method in_out(ZZ aZZ, int _d, int _x, float _y) =>
aZZ.d.unshift(_d), aZZ.x.unshift(_x), aZZ.y.unshift(_y), aZZ.d.pop(),
aZZ.x.pop(), aZZ.y.pop()
max_bars_back(time, 1000)
//-----------------------------------------------------------------------------}
//Calculations
//-----------------------------------------------------------------------------{
x2 := b.i - 1
ph = ta.pivothigh(liqLen, 1)
pl = ta.pivotlow (liqLen, 1)
if ph
dir := aZZ.d.get(0)
x1 := aZZ.x.get(0)
y1 := aZZ.y.get(0)
y2 := nz(b.h[1])
if dir < 1
aZZ.in_out(1, x2, y2)
else
if dir == 1 and ph > y1
aZZ.x.set(0, x2), aZZ.y.set(0, y2)
if per
count = 0
st_P = 0.
st_B = 0
minP = 0.
maxP = 10e6
for i = 0 to maxSize - 1
if aZZ.d.get(i) == 1
if aZZ.y.get(i) > ph + (atr / liqMar)
break
else
if aZZ.y.get(i) > ph - (atr / liqMar) and aZZ.y.get(i) < ph +
(atr / liqMar)
count += 1
st_B := aZZ.x.get(i)
st_P := aZZ.y.get(i)
if aZZ.y.get(i) > minP
minP := aZZ.y.get(i)
if aZZ.y.get(i) < maxP
maxP := aZZ.y.get(i)
if count > 2
getB = b_liq_B.get(0)
if st_B == getB.bx.get_left()
getB.bx.set_top(math.avg(minP, maxP) + (atr / liqMar))
getB.bx.set_rightbottom(b.i + 10, math.avg(minP, maxP) - (atr /
liqMar))
else
b_liq_B.unshift(
liq.new(
box.new(st_B, math.avg(minP, maxP) + (atr / liqMar), b.i + 10,
math.avg(minP, maxP) - (atr / liqMar), bgcolor=color(na), border_color=color(na)),
box.new(na, na, na, na, bgcolor = color(na), border_color =
color(na)),
box.new(st_B, st_P, b.i + 10, st_P, text = 'Buyside liquidity',
text_size = size.tiny, text_halign = text.align_left, text_valign =
text.align_bottom, text_color = color.new(cLIQ_B, 25), bgcolor = color(na),
border_color = color(na)),
false,
false,
line.new(st_B , st_P, b.i - 1, st_P, color = color.new(cLIQ_B,
0)),
line.new(b.i - 1, st_P, na , st_P, color = color.new(cLIQ_B,
0), style = line.style_dotted))
)
if pl
dir := aZZ.d.get (0)
x1 := aZZ.x.get (0)
y1 := aZZ.y.get (0)
y2 := nz(b.l[1])
if dir > -1
aZZ.in_out(-1, x2, y2)
else
if dir == -1 and pl < y1
aZZ.x.set(0, x2), aZZ.y.set(0, y2)
if per
count = 0
st_P = 0.
st_B = 0
minP = 0.
maxP = 10e6
for i = 0 to maxSize - 1
if aZZ.d.get(i) == -1
if aZZ.y.get(i) < pl - (atr / liqMar)
break
else
if aZZ.y.get(i) > pl - (atr / liqMar) and aZZ.y.get(i) < pl +
(atr / liqMar)
count += 1
st_B := aZZ.x.get(i)
st_P := aZZ.y.get(i)
if aZZ.y.get(i) > minP
minP := aZZ.y.get(i)
if aZZ.y.get(i) < maxP
maxP := aZZ.y.get(i)
if count > 2
getB = b_liq_S.get(0)
if st_B == getB.bx.get_left()
getB.bx.set_top(math.avg(minP, maxP) + (atr / liqMar))
getB.bx.set_rightbottom(b.i + 10, math.avg(minP, maxP) - (atr /
liqMar))
else
b_liq_S.unshift(
liq.new(
box.new(st_B, math.avg(minP, maxP) + (atr / liqMar), b.i + 10,
math.avg(minP, maxP) - (atr / liqMar), bgcolor=color(na), border_color=color(na)),
box.new(na, na, na, na, bgcolor=color(na),
border_color=color(na)),
box.new(st_B, st_P, b.i + 10, st_P, text = 'Sellside liquidity',
text_size = size.tiny, text_halign = text.align_left, text_valign = text.align_top,
text_color = color.new(cLIQ_S, 25), bgcolor=color(na), border_color=color(na)),
false,
false,
line.new(st_B , st_P, b.i - 1, st_P, color = color.new(cLIQ_S,
0)),
line.new(b.i - 1, st_P, na , st_P, color = color.new(cLIQ_S,
0), style = line.style_dotted))
)
if not x.brL
x.lne.set_x2(b.i)
else if x.brZ
if b.l > x.ln.get_y1() - marBuy * (atr) and b.h < x.ln.get_y1() + marBuy *
(atr)
x.bxz.set_right(b.i + 1)
x.bxz.set_top(math.max(b.h, x.bxz.get_top()))
if liqBuy
x.lne.set_x2(b.i + 1)
else
x.brZ := false
for i = 0 to b_liq_S.size() - 1
x = b_liq_S.get(i)
if not x.brL
x.lne.set_x2(b.i)
x.bxz.set_lefttop(b.i - 1, x.ln.get_y1())
x.bxz.set_rightbottom(b.i + 1, math.max(x.ln.get_y1() - marSel * (atr),
b.l))
x.bxz.set_bgcolor(color.new(cLIQ_S, liqSel ? 73 : 100))
else if x.brZ
if b.l > x.ln.get_y1() - marSel * (atr) and b.h < x.ln.get_y1() + marSel *
(atr)
x.bxz.set_rightbottom(b.i + 1, math.min(b.l, x.bxz.get_bottom()))
if liqSel
x.lne.set_x2(b.i + 1)
else
x.brZ := false
if bull
l = 13
if bull[1]
st = math.abs(b.l - b.l[1]) / l
for i = 0 to l - 1
array.push(b_liq_V, box.new(b.i - 2, b.l[1] + i * st, b.i, b.l[1] +
(i + 1) * st, border_color = na, bgcolor = color.new(cLQV_B, 90) ))
else
st = math.abs(b.l - b.h[2]) / l
for i = 0 to l - 1
if lqText and i == 0
array.push(b_liq_V, box.new(b.i - 2, b.h[2] + i * st, b.i,
b.h[2] + (i + 1) * st, text = 'Liquidity Void ', text_size = size.tiny,
text_halign = text.align_right, text_valign = text.align_bottom, text_color = na,
border_color = na, bgcolor = color.new(cLQV_B, 90) ))
else
array.push(b_liq_V, box.new(b.i - 2, b.h[2] + i * st, b.i,
b.h[2] + (i + 1) * st, border_color = na, bgcolor = color.new(cLQV_B, 90) ))
if bear
l = 13
if bear[1]
st = math.abs(b.h[1] - b.h) / l
for i = 0 to l - 1
array.push(b_liq_V, box.new(b.i - 2, b.h + i * st, b.i, b.h + (i +
1) * st, border_color = na, bgcolor = color.new(cLQV_S, 90) ))
else
st = math.abs(b.l[2] - b.h) / l
for i = 0 to l - 1
if lqText and i == l - 1
array.push(b_liq_V, box.new(b.i - 2, b.h + i * st, b.i, b.h +
(i + 1) * st, text = 'Liquidity Void ', text_size = size.tiny, text_halign =
text.align_right, text_valign = text.align_top, text_color = na, border_color = na,
bgcolor = color.new(cLQV_S, 90) ))
else
array.push(b_liq_V, box.new(b.i - 2, b.h + i * st, b.i, b.h +
(i + 1) * st, border_color = na, bgcolor = color.new(cLQV_S, 90) ))
if b_liq_V.size() > 0
qt = b_liq_V.size()
for bn = qt - 1 to 0
if bn < b_liq_V.size()
cb = b_liq_V.get(bn)
ba = math.avg(cb.get_bottom(), cb.get_top())
//-----------------------------------------------------------------------------}
// ~~ © Zeiierman {
//@version=5
//ndicator("Golden Swap
(Zeiierman)",overlay=true,max_labels_count=500,max_lines_count=500)
//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Tooltips {
t1="Select the timeframe for the Golden Swap signals. Changing this affects the
period over which the signals are calculated and displayed on the chart."
t2="Toggle the display of Golden Swap signals"
t3="Enable or disable the display of pre-signals for Golden Swaps. These are
preliminary signals that indicate a potential upcoming Golden Swap signal."
t4="Turn on/off the Symmetry Precision filter. This filter adds an additional layer
of precision to the signals by considering the symmetry of price movements. \n\nSet
the level of precision for Symmetry Signals. A higher value allows for greater
variation in symmetry, while a lower value demands closer symmetry."
t5="Enable or disable the BaselineBound Threshold. This setting acts as a filter
for signals, where only those meeting the threshold criteria are considered
valid. \n\nAdjust the range factor for the BaselineBound pattern. Increasing this
value widens the threshold range, potentially allowing more signals to pass through
the filter."
t7="Enable or disable the display of Open, High, and Low levels for the selected
timeframe. Adjusting this affects the visibility of these price levels on the
chart. \n\nSelect the timeframe for displaying Open, High, and Low levels. Changing
this setting will adjust the period over which these levels are calculated and
shown."
//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Fetch Data
[oq, hq, lq, tq] = request.security(syminfo.tickerid, tfq, [open, high, low,
time])
[o1q, h1q, l1q, t1q] = request.security(syminfo.tickerid, tf1, [open[1], high[1],
low[1], time[1]])
[o2, h2, l2, t2_] = request.security(syminfo.tickerid, tf2, [open[1], high[1],
low[1], time[1]])
[o3, h3, l3, t3_] = request.security(syminfo.tickerid, tf3, [open[1], high[1],
low[1], time[1]])
[o4, h4, l4, t4_] = request.security(syminfo.tickerid, tf4, [open[1], high[1],
low[1], time[1]])
//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Variables
var line[] lines = array.new_line(30)
var label[] labels = array.new_label(30)
//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0
at https://mozilla.org/MPL/2.0/
// © ChartPrime
//@
//
-----------------------------------------------------------------------------------
----------------------------------}
// 𝙄𝙉𝙋𝙐𝙏𝙎
//
-----------------------------------------------------------------------------------
----------------------------------{
extension = input.int(50, "Extension to the right of High and Low", group =
"Settings")
timeframe = input.timeframe("D", "timeframe", tooltip = "Use Higher Timeframe then
Current", group = "Settings")
// Variables Declaration
var color color = na
color color1 = na
var bool check = na
//
-----------------------------------------------------------------------------------
----------------------------------}
// 𝘾𝘼𝙇𝘾𝙐𝙇𝘼𝙏𝙄𝙊𝙉𝙎
//
-----------------------------------------------------------------------------------
----------------------------------{
// To avoid differences on historical and realtime bars:
// returns a value from the higher timeframe on the bar after it completes:
indexHighTF = barstate.isrealtime ? 1 : 0
indexCurrTF = barstate.isrealtime ? 0 : 1
//
-----------------------------------------------------------------------------------
----------------------------------}
// 𝙑𝙄𝙎𝙐𝘼𝙇𝙄𝙕𝘼𝙏𝙄𝙊𝙉
//
-----------------------------------------------------------------------------------
----------------------------------{
// BreakOut labels
if high_break and check[1] == false and show_break
line.new(m_Left, m_Right,
color = chart.fg_color,
width = show_trend ? 1 : 2,
style = show_trend ? line.style_solid : line.style_dotted
)
//
-----------------------------------------------------------------------------------
----------------------------------}
// 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/
// © LuxAlgo
//@version=5
//------------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------{
//-----------------------------------------------------------------------------}
// User Defined Types
//-----------------------------------------------------------------------------{
type BAR
float o = open
float h = high
float l = low
float c = close
int i = bar_index
type htfBar
float price = na
int index = na
type htfBarArray
htfBar opn
htfBar top
htfBar btm
htfBar prc
type ImmediateRebalance
label lb
line ln
int idx
int count
type STAT
int bullTotal = 0
int bullFailed = 0
int bearTotal = 0
int bearFailed = 0
//-----------------------------------------------------------------------------}
// Variables
//-----------------------------------------------------------------------------{
BAR b = BAR.new()
var STAT stat = STAT.new()
//-----------------------------------------------------------------------------}
// Functions / Methods
//-----------------------------------------------------------------------------{
irArray.unshift(
ImmediateRebalance.new(
label.new(x2, y, bull ? '◥' : '◢', textcolor = color, color = color(na),
style = label.style_label_center, size = irSZ, tooltip = bull ? 'Bullish Immediate
Rebalance' : 'Bearish Immediate Rebalance'),
line.new(x2, y, x2, y, color = color, width = 1, style =
line.style_dotted),
lastIdxC, (lastIdxC - lastIdxO + 1)
)
)
//-----------------------------------------------------------------------------}
// Calculations
//-----------------------------------------------------------------------------{
string tf = switch
irTF == "5 Minutes" and timeframe.isintraday and timeframe.multiplier <= 5
=> '5'
irTF == "15 Minutes" and timeframe.isintraday and timeframe.multiplier <= 15
=> '15'
irTF == "1 Hour" and timeframe.isintraday and timeframe.multiplier <= 60
=> '60'
irTF == "4 Hours" and timeframe.isintraday and timeframe.multiplier <= 240
=> '240'
irTF == "1 Day" and timeframe.isintraday => 'D'
irTF == "1 Week" and (timeframe.isdaily or timeframe.isintraday) => 'W'
=> timeframe.period
if timeframe.change(tf)
bullProcess := false
bearProcess := false
if barArray.size() > 2
barArray.pop()
barArray.unshift(barHist)
else
if b.h > barHigh.price
barHigh.price := b.h
barHigh.index := b.i
barClose.price := b.c
barClose.index := b.i
if barArray.size() > 2
if b.l < barArray.get(1).top.price
bullBarIndexEnd := b.i
if barArray.size() > 2
bullCondition := barArray.get(0).btm.price < barArray.get(2).top.price and
barArray.get(0).btm.price > barArray.get(2).prc.price and
barArray.get(0).prc.price > barArray.get(2).top.price and
barArray.get(1).prc.price > barArray.get(2).top.price and
barArray.get(0).prc.price > barArray.get(1).prc.price
plotImmediateRebalances(barArray.get(2).top.index, barArray.get(2).top.price,
bullBarIndexEnd1, irBC, true, math.max(barArray.get(2).opn.price,
barArray.get(2).prc.price), bIR, barArray.get(0).opn.index,
barArray.get(0).prc.index, irSZl, irWTH)
plotImmediateRebalances(barArray.get(2).btm.index, barArray.get(2).btm.price,
bearBarIndexEnd1, irSC, false, math.min(barArray.get(2).opn.price,
barArray.get(2).prc.price), aIR, barArray.get(0).opn.index,
barArray.get(0).prc.index, irSZl, irWTH)
if aIR.size() > 0
for i = aIR.size() - 1 to 0
lF = aIR.get(i)
if b.i > (lF.idx + lF.count * (irCFR - 1)) and b.h > lF.lb.get_y()
lF.lb.set_text('❌')
lF.lb.set_tooltip('Failed Bearish Immediate Rebalance')
lF.lb.set_size(size.normal)
lF.ln.set_x2(b.i)
stat.bearFailed += 1
aIR.remove(i)
break
if bIR.size() > 0
for i = bIR.size() - 1 to 0
lF = bIR.get(i)
if b.i > (lF.idx + lF.count * (irCFR - 1)) and b.l < lF.lb.get_y()
lF.lb.set_text('❌')
lF.lb.set_tooltip('Failed Bullish Immediate Rebalance')
lF.lb.set_size(size.normal)
lF.ln.set_x2(b.i)
stat.bullFailed += 1
bIR.remove(i)
break
//-----------------------------------------------------------------------------}
// Calculations - Dashboard
//-----------------------------------------------------------------------------{
var table tb = na
//-----------------------------------------------------------------------------}
// 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/
// © LuxAlgo
//@version=5
//indicator("Market Structure CHoCH/BOS (Fractal) [LuxAlgo]", "LuxAlgo - Market
Structure (Fractal)", overlay = true, max_lines_count = 500, max_labels_count =
500)
//------------------------------------------------------------------------------
// Settings
//-----------------------------------------------------------------------------{
length = input.int(5, minval = 3)
//Colors
showBull = input(true, 'Bullish Structures', inline = 'bull', group = 'Style')
bullCss = input.color(#089981, '', inline = 'bull', group = 'Style')
//Dashboard
showDash = input(false, 'Show Dashboard', group = 'Dashboard')
dashLoc = input.string('Top Right', 'Location', options = ['Top Right', 'Bottom
Right', 'Bottom Left'], group = 'Dashboard')
textSize = input.string('Small', 'Size' , options = ['Tiny', 'Small',
'Normal'] , group = 'Dashboard')
//-----------------------------------------------------------------------------}
//Types
//-----------------------------------------------------------------------------{
type fractal
float value
int loc
bool iscrossed
//-----------------------------------------------------------------------------}
//Fractal Detection
//-----------------------------------------------------------------------------{
var p = int(length/2)
n = bar_index
dh = math.sum(math.sign(high - high[1]), p)
dl = math.sum(math.sign(low - low[1]), p)
bullf_count = ta.cum(bullf ? 1 : 0)
bearf_count = ta.cum(bearf ? 1 : 0)
//-----------------------------------------------------------------------------}
//Bullish market structure
//-----------------------------------------------------------------------------{
var upper = fractal.new()
var line lower_lvl = na
var label ms_lbl = na
var bull_ms_count = 0
var broken_sup = false
var os = 0
if bullf
upper.value := high[p]
upper.loc := n-p
upper.iscrossed := false
//Set support
k = 2
min = low[1]
for i = 2 to (n - upper.loc)-1
min := math.min(low[i], min)
k := low[i] == min ? i : k
if showSupport
lower_lvl := line.new(n-k, min, n, min, color = bullCss, style =
line.style_dashed)
broken_sup := false
upper.iscrossed := true
bull_ms_count += 1
os := 1
//-----------------------------------------------------------------------------}
//Bearish market structure
//-----------------------------------------------------------------------------{
var lower = fractal.new()
var line upper_lvl = na
var broken_res = false
var bear_ms_count = 0
if bearf
lower.value := low[p]
lower.loc := n-p
lower.iscrossed := false
//Set resistance
k = 2
max = high[1]
for i = 2 to (n - lower.loc)-1
max := math.max(high[i], max)
k := high[i] == max ? i : k
if showResistance
upper_lvl := line.new(n-k, max, n, max, color = bearCss, style =
line.style_dashed)
broken_res := false
lower.iscrossed := true
bear_ms_count += 1
os := -1
//-----------------------------------------------------------------------------}
//Dashboard
//-----------------------------------------------------------------------------{
var table_position = dashLoc == 'Bottom Left' ? position.bottom_left
: dashLoc == 'Top Right' ? position.top_right
: position.bottom_right
var tb = table.new(table_position, 2, 3
, bgcolor = #1e222d
, border_color = #373a46
, border_width = 1
, frame_color = #373a46
, frame_width = 1)
if showDash
if barstate.isfirst
tb.cell(0, 0, 'Structure To Fractal %', text_color = color.white, text_size
= table_size)
tb.merge_cells(0,0,1,0)
tb.cell(0, 1, 'Bullish', text_color = #089981, text_size = table_size)
tb.cell(1, 1, 'Bearish', text_color = #f23645, text_size = table_size)
if barstate.islast
tb.cell(0, 2, str.tostring(bull_ms_count / bullf_count * 100,
format.percent), text_color = #089981, text_size = table_size)
tb.cell(1, 2, str.tostring(bear_ms_count / bearf_count * 100,
format.percent), text_color = #f23645, text_size = table_size)
//-----------------------------------------------------------------------------}
//Plots
//-----------------------------------------------------------------------------{
plot(broken_res and not broken_res[1] ? low : na, 'Resistance Breakout', #089981,
2, plot.style_circles)
plot(broken_sup and not broken_sup[1] ? high : na, 'Support Breakout', #f23645, 2,
plot.style_circles)
//-----------------------------------------------------------------------------}
// 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/
// © LuxAlgo
//@version=5
//ndicator("Market Structure with Inducements & Sweeps [LuxAlgo]", "LuxAlgo -
Market Structure with Inducements & Sweeps", overlay = true, max_lines_count = 500,
max_labels_count = 500)
//---------------------------------------------------------------------------------
------------------------------------}
//Settings
//---------------------------------------------------------------------------------
------------------------------------{
len = input(50, 'CHoCH Detection Period')
shortLen = input(3, 'IDM Detection Period')
//Styling
bullCss = input(#089981, 'Bullish Elements', group = 'Style')
bearCss = input(#ff5252, 'Bearish Elements', group = 'Style')
//---------------------------------------------------------------------------------
------------------------------------}
//Functions
//---------------------------------------------------------------------------------
------------------------------------{
//Swings detection/measurements
n = bar_index
swings(len)=>
var os = 0
var int topx = na
var int btmx = na
upper = ta.highest(len)
lower = ta.lowest(len)
//---------------------------------------------------------------------------------
------------------------------------}
//Swings
//---------------------------------------------------------------------------------
------------------------------------{
[top, topx, btm, btmx] = swings(len)
[stop, stopx, sbtm, sbtmx] = swings(shortLen)
var os = 0
var top_crossed = false
var btm_crossed = false
//---------------------------------------------------------------------------------
------------------------------------}
//CHoCH Detection
//---------------------------------------------------------------------------------
------------------------------------{
if top
topy := top
top_crossed := false
if btm
btmy := btm
btm_crossed := false
if os == 1 and showChoch
line.new(topx, topy, n, topy, color = bullCss, style = line.style_dashed)
label.new(int(math.avg(n, topx)), topy, 'CHoCH', color = color(na), style =
label.style_label_down, textcolor = bullCss, size = size.tiny)
else if showChoch
line.new(btmx, btmy, n, btmy, color = bearCss, style = line.style_dashed)
label.new(int(math.avg(n, btmx)), btmy, 'CHoCH', color = color(na), style =
label.style_label_up, textcolor = bearCss, size = size.tiny)
stopy = fixnan(stop)
sbtmy = fixnan(sbtm)
//---------------------------------------------------------------------------------
------------------------------------}
//Bullish BOS
//---------------------------------------------------------------------------------
------------------------------------{
//IDM
if low < sbtmy and not sbtm_crossed and os == 1 and sbtmy != btmy
if showIdm
line.new(sbtmx, sbtmy, n, sbtmy, color = idmCss, style = line.style_dotted)
label.new(int(math.avg(n, sbtmx)), sbtmy, 'IDM', color = color(na), style =
label.style_label_up, textcolor = idmCss, size = size.tiny)
sbtm_crossed := true
//BOS
if close > max and sbtm_crossed and os == 1
if showBos
line.new(max_x1, max, n, max, color = bullCss)
label.new(int(math.avg(n, max_x1)), max, 'BOS', color = color(na), style =
label.style_label_down, textcolor = bullCss, size = size.tiny)
sbtm_crossed := false
//---------------------------------------------------------------------------------
------------------------------------}
//Bearish BOS
//---------------------------------------------------------------------------------
------------------------------------{
//IDM
if high > stopy and not stop_crossed and os == 0 and stopy != topy
if showIdm
line.new(stopx, stopy, n, stopy, color = color.gray, style =
line.style_dotted)
label.new(int(math.avg(n, stopx)), stopy, 'IDM', color = color(na), style =
label.style_label_down, textcolor = color.gray, size = size.tiny)
stop_crossed := true
//BOS
if close < min and stop_crossed and os == 0
if showBos
line.new(min_x1, min, n, min, color = bearCss)
label.new(int(math.avg(n, min_x1)), min, 'BOS', color = color(na), style =
label.style_label_up, textcolor = bearCss, size = size.tiny)
stop_crossed := false
//---------------------------------------------------------------------------------
------------------------------------}
//Sweeps
//---------------------------------------------------------------------------------
------------------------------------{
if high > max and close < max and os == 1 and n - max_x1 > 1 and showSweeps
line.new(max_x1, max, n, max, color = sweepsCss, style = line.style_dotted)
label.new(int(math.avg(n, max_x1)), max, 'x', color = color(na), style =
label.style_label_down, textcolor = sweepsCss)
if low < min and close > min and os == 0 and n - min_x1 > 1 and showSweeps
line.new(min_x1, min, n, min, color = sweepsCss, style = line.style_dotted)
label.new(int(math.avg(n, min_x1)), min, 'x', color = color(na), style =
label.style_label_up, textcolor = sweepsCss)
//Trailing max/min
max := math.max(high, max)
min := math.min(low, min)
//---------------------------------------------------------------------------------
------------------------------------}
//Extensions
//---------------------------------------------------------------------------------
------------------------------------{
var ext_choch = line.new(na,na,na,na, style = line.style_dashed)
var ext_bos = line.new(na,na,na,na)
var ext_idm = line.new(na,na,na,na, style = line.style_dotted, color = idmCss)
if barstate.islast
if os == 1
if showChoch
ext_choch.set_xy1(btmx, btmy), ext_choch.set_xy2(n, btmy),
ext_choch.set_color(bearCss)
ext_choch_lbl.set_xy(n, btmy),
ext_choch_lbl.set_style(label.style_label_up), ext_choch_lbl.set_textcolor(bearCss)
if showBos
ext_bos.set_xy1(max_x1, max), ext_bos.set_xy2(n, max),
ext_bos.set_color(bullCss)
ext_bos_lbl.set_xy(n, max),
ext_bos_lbl.set_style(label.style_label_down), ext_bos_lbl.set_textcolor(bullCss)
if showBos
ext_bos.set_xy1(min_x1, min), ext_bos.set_xy2(n, min),
ext_bos.set_color(bearCss)
ext_bos_lbl.set_xy(n, min),
ext_bos_lbl.set_style(label.style_label_up), ext_bos_lbl.set_textcolor(bearCss)
//---------------------------------------------------------------------------------
------------------------------------}
//Plots
//---------------------------------------------------------------------------------
------------------------------------{
plot(showCircles ? top : na, 'Swing High', color.new(bearCss, 50), 5,
plot.style_circles, offset = -len)
plot(showCircles ? btm : na, 'Swing Low', color.new(bullCss, 50), 5,
plot.style_circles, offset = -len)
//---------------------------------------------------------------------------------
------------------------------------}
// 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/
// © LuxAlgo
//@version=5
//indicator('Range Average Retest Model [LuxAlgo]', 'LuxAlgo - Range Average Retest
Model', overlay=true, max_bars_back = 5000, max_boxes_count = 500, max_lines_count
= 500)
//---------------------------------------------------------------------------------
------------------------------------}
//CONSTANTS & STRINGS & INPUTS
//---------------------------------------------------------------------------------
------------------------------------{
BULLISH_LEG = 1
BEARISH_LEG = 0
ARRAY_MAX_SIZE = 165
BULLISH_AREA = 'BULLISH'
BEARISH_AREA = 'BEARISH'
BOTH_AREA = 'BOTH'
GREEN = #089981
RED = #F23645
SWINGS_GROUP = 'SWINGS'
TRADES_GROUP = 'TRADES'
STYLE_GROUP = 'STYLE'
//---------------------------------------------------------------------------------
------------------------------------}
//DATA STRUCTURES & VARIABLES
//---------------------------------------------------------------------------------
------------------------------------{
// @type Storage UDT for swing areas
// @field startTime Time of the first barBar
// @field endTime Time of the last barBar
// @field endIndex Bar index of the last bar
// @field areaHigh Highest price
// @field areaLow Lowest price
// @field averagePrice Average price as 0.5*(areaHigh+areaLow)
// @field areaColor Default colour for drawing lines
// @field touched True for swing areas with associated trades, false
otherwise
type area
int startTime
int endTime
int endIndex
float areaHigh
float areaLow
float averagePrice
color areaColor
bool touched = false
//---------------------------------------------------------------------------------
------------------------------------}
//USER-DEFINED FUNCTIONS
//---------------------------------------------------------------------------------
------------------------------------{
// @function Get the value of the current leg, it can be 0 (bearish) or
1 (bullish)
// @returns int
leg() =>
var leg = 0
newLegHigh = legHigh > ta.highest(pivotLengthInput)
newLegLow = legLow < ta.lowest( pivotLengthInput)
if newLegHigh
leg := BEARISH_LEG
else if newLegLow
leg := BULLISH_LEG
leg
// @function Update the last area with its final values and if it is not
a valid one, delete it from storage
// @param areaHigh (float) area high
// @param areaLow (float) area low
// @returns area ID
updateLastArea(float areaHigh = na, float areaLow = na) =>
if array.size(areas) > 0
area a_rea = array.last(areas)
updateAreaValues(a_rea, areaHigh, areaLow)
a_rea.endIndex := legIndex
a_rea.endTime := legTime
a_rea.averagePrice :=
math.round_to_mintick(0.5*(a_rea.areaHigh+a_rea.areaLow))
if not validAveragePrice(a_rea.averagePrice)
array.pop(areas)
if showAverageInput
line.new(t_rade.startLineTime, t_rade.entry, t_rade.openTrade ? time :
t_rade.endTime, t_rade.entry, xloc = xloc.bar_time, color = t_rade.tradeColor,
style = line.style_dashed)
//---------------------------------------------------------------------------------
------------------------------------}
//MUTABLE VARIABLES & EXECUTION
//---------------------------------------------------------------------------------
------------------------------------{
// @variable Get current leg value, this is the leg value on the current
bar
currentLeg = leg()
// we check for stop loss and take profit hits on all open trades
for eachTrade in trades
if eachTrade.openTrade
if high > eachTrade.top or low < eachTrade.bottom
updateTrade(eachTrade)
// we plot all the drawings (boxes and lines) only once at the end of historical
data, and then once per bar on bar close
if barstate.islastconfirmedhistory or (barstate.isrealtime and
barstate.isconfirmed)
if showAreasInput
// we draw all touched areas
for eachArea in areas
if eachArea.touched
drawArea(eachArea)
//@version=5
const bool DEBUG = false
const int maxBoxesCount = 500
const float overlapThresholdPercentage = 0.0
int maxDistanceToLastBar = 1250 // Affects Running Time
const int maxSDZones = 30
const int minZoneSize = 10
const int RETEST_COOLDOWN = 5
const int minDistanceBetweenZones = 5
const float maxZoneSizeATR = 1.5
//ndicator(title = 'Supply & Demand (MTF) | Flux Charts', shorttitle = "Supply and
Demand (MTF) | Flux Charts", overlay = true, max_boxes_count = maxBoxesCount,
max_labels_count = maxBoxesCount, max_lines_count = maxBoxesCount, max_bars_back =
2000)
atr = ta.atr(20)
averageBodySize = ta.sma(math.abs(close - open), 20)
type sdZoneInfo
float top
float bottom
string sdType
int startTime
int breakTime
int guid
string timeframeStr
bool disabled = false
string combinedTimeframesStr = na
bool combined = false
type sdZone
sdZoneInfo info
bool isRendered = false
box sdBox = na
line sdBoxLineTop = na
line sdBoxLineMiddle = na
line sdBoxLineBottom = na
//
box sdBoxText = na
type retestLabelContainer
int guid
array<label> labels
box.delete(sdZoneF.sdBox)
box.delete(sdZoneF.sdBoxText)
line.delete(sdZoneF.sdBoxLineTop)
line.delete(sdZoneF.sdBoxLineMiddle)
line.delete(sdZoneF.sdBoxLineBottom)
type timeframeInfo
int index = na
string timeframeStr = na
bool isEnabled = false
sdZoneInfo[] demandZonesList = na
sdZoneInfo[] supplyZonesList = na
newTFInfo
sd.isRendered := true
int zoneSize = na
if na(info.breakTime)
zoneSize := (time + 1) - info.startTime
else
zoneSize := (info.breakTime - info.startTime)
render = true
if zoneSize < timeframe.in_seconds(info.timeframeStr) * minZoneSize * 1000
render := false
if info.startTime < nz(oldestBarTime, time)
render := false
startX = info.startTime
maxEndX = info.startTime + zoneSize / 2
sdZone newSD =
createSDZone(sdZoneInfo.new(math.max(curSD1.info.top, curSD2.info.top),
math.min(curSD1.info.bottom, curSD2.info.bottom), curSD1.info.sdType))
newSD.info.startTime := math.min(curSD1.info.startTime,
curSD2.info.startTime)
newSD.info.breakTime := math.max(nz(curSD1.info.breakTime),
nz(curSD2.info.breakTime))
newSD.info.breakTime := newSD.info.breakTime == 0 ? na :
newSD.info.breakTime
newSD.info.guid := newSD.info.startTime
newSD.info.timeframeStr := curSD1.info.timeframeStr
clampSDZone(newSD.info)
newSD.info.combined := true
if timeframe.in_seconds(curSD1.info.timeframeStr) !=
timeframe.in_seconds(curSD2.info.timeframeStr)
newSD.info.combinedTimeframesStr :=
(na(curSD1.info.combinedTimeframesStr) ?
formatTimeframeString(curSD1.info.timeframeStr) :
curSD1.info.combinedTimeframesStr) + " & " + (na(curSD2.info.combinedTimeframesStr)
? formatTimeframeString(curSD2.info.timeframeStr) :
curSD2.info.combinedTimeframesStr)
allSDZonesList.unshift(newSD)
lastCombinations += 1
handleSDZonesFinal () =>
if DEBUG
log.info("Demand Count " + str.tostring(demandZonesList.size()))
log.info("Supply Count " + str.tostring(supplyZonesList.size()))
log.info("All " + str.tostring(allSDZonesList.size()))
log.info("Max " + str.tostring(demandZones))
if allSDZonesList.size () > 0
for i = 0 to allSDZonesList.size() - 1
safeDeleteSDZone(allSDZonesList.get(i))
allSDZonesList.clear()
for i = 0 to timeframeInfos.size() - 1
curTimeframe = timeframeInfos.get(i)
if not curTimeframe.isEnabled
continue
if curTimeframe.demandZonesList.size() > 0
for j = 0 to math.min(curTimeframe.demandZonesList.size() - 1,
demandZones - 1)
sdZoneInfoF = curTimeframe.demandZonesList.get(j)
sdZoneInfoF.timeframeStr := curTimeframe.timeframeStr
allSDZonesList.unshift(createSDZone(sdZoneInfo.copy(sdZoneInfoF)))
if curTimeframe.supplyZonesList.size() > 0
for j = 0 to math.min(curTimeframe.supplyZonesList.size() - 1,
supplyZones - 1)
sdZoneInfoF = curTimeframe.supplyZonesList.get(j)
sdZoneInfoF.timeframeStr := curTimeframe.timeframeStr
allSDZonesList.unshift(createSDZone(sdZoneInfo.copy(sdZoneInfoF)))
if combineSDs
combineSDsFunc()
if allSDZonesList.size() > 0
for i = 0 to allSDZonesList.size() - 1
curSD = allSDZonesList.get(i)
if isSDValid(curSD.info)
renderSDZone(curSD)
// Invalidation
if demandZonesList.size() > 0
for i = demandZonesList.size() - 1 to 0
currentSD = demandZonesList.get(i)
if na(currentSD.breakTime)
if (sdEndMethod == "Wick" ? low : math.min(open, close)) <
currentSD.bottom
currentSD.breakTime := time
if supplyZonesList.size() > 0
for i = supplyZonesList.size() - 1 to 0
currentSD = supplyZonesList.get(i)
if na(currentSD.breakTime)
if (sdEndMethod == "Wick" ? high : math.max(open, close)) >
currentSD.top
currentSD.breakTime := time
[demandZonesListTimeframe1, supplyZonesListTimeframe1] =
getTFData(timeframeInfos.get(0), timeframe1)
[demandZonesListTimeframe2, supplyZonesListTimeframe2] =
getTFData(timeframeInfos.get(1), timeframe2)
[demandZonesListTimeframe3, supplyZonesListTimeframe3] =
getTFData(timeframeInfos.get(2), timeframe3)
var lastRetestIndexSupply = 0
var lastRetestIndexDemand = 0
float renderRetestLabelBuyside = na
int renderRetestLabelBuysideGUID = na
float renderRetestLabelSellside = na
int renderRetestLabelSellsideGUID = na
float renderBreakLabelBuyside = na
int renderBreakLabelBuysideGUID = na
float renderBreakLabelSellside = na
int renderBreakLabelSellsideGUID = na
handleTimeframeInfo(timeframeInfos.get(0), demandZonesListTimeframe1,
supplyZonesListTimeframe1)
handleTimeframeInfo(timeframeInfos.get(1), demandZonesListTimeframe2,
supplyZonesListTimeframe2)
handleTimeframeInfo(timeframeInfos.get(2), demandZonesListTimeframe3,
supplyZonesListTimeframe3)
handleSDZonesFinal()
// Breaks
if allSDZonesList.size() > 0
for i = 0 to allSDZonesList.size() - 1
curZone = allSDZonesList.get(i)
if curZone.info.disabled
continue
if not showInvalidated and not na(curZone.info.breakTime)
continue
if na(curZone.info.breakTime)
continue
if time - curZone.info.startTime < minZoneSize *
timeframe.in_seconds(curZone.info.timeframeStr) * 1000
continue
if curZone.info.startTime < nz(oldestBarTime, time)
continue
if time == curZone.info.breakTime
if curZone.info.sdType == "Supply"
if curZone.info.breakTime - curZone.info.startTime >
minZoneSize * timeframe.in_seconds() * 1000
renderBreakLabelBuyside := curZone.info.bottom
renderBreakLabelBuysideGUID := curZone.info.guid
else
if curZone.info.breakTime - curZone.info.startTime >
minZoneSize * timeframe.in_seconds() * 1000
renderBreakLabelSellside := curZone.info.top
renderBreakLabelSellsideGUID := curZone.info.guid
// Retests
if allSDZonesList.size() > 0
for i = 0 to allSDZonesList.size() - 1
curZone = allSDZonesList.get(i)
if curZone.info.disabled
continue
if not showInvalidated and not na(curZone.info.breakTime)
continue
if not na(curZone.info.breakTime)
continue
if time - curZone.info.startTime < minZoneSize *
timeframe.in_seconds(curZone.info.timeframeStr) * 1000
continue
if curZone.info.startTime < nz(oldestBarTime, time)
continue
// Retests
if retestLabels.keys().size() > 0
for i = 0 to retestLabels.keys().size() - 1
curKey = retestLabels.keys().get(i)
foundKey = false
if allSDZonesList.size() > 0
for j = 0 to allSDZonesList.size() - 1
if allSDZonesList.get(j).info.guid == curKey
if allSDZonesList.get(j).info.disabled
continue
if not showInvalidated and not
na(allSDZonesList.get(j).info.breakTime)
continue
if time - allSDZonesList.get(j).info.startTime < minZoneSize *
timeframe.in_seconds(allSDZonesList.get(j).info.timeframeStr) * 1000
continue
if allSDZonesList.get(j).info.startTime < nz(oldestBarTime,
time)
continue
foundKey := true
break
if not foundKey
for j = 0 to retestLabels.get(curKey).labels.size() - 1
label.delete(retestLabels.get(curKey).labels.get(j))
// Breaks
if not na(renderBreakLabelBuyside) and breaksEnabled
breakLabels.put(renderBreakLabelBuysideGUID, label.new(bar_index,
renderBreakLabelBuyside, style = label.style_label_up, color = color.blue, text =
"B", textcolor = color.white, size = size.small))
if breakLabels.keys().size() > 0
for i = 0 to breakLabels.keys().size() - 1
curKey = breakLabels.keys().get(i)
foundKey = false
if allSDZonesList.size() > 0
for j = 0 to allSDZonesList.size() - 1
if allSDZonesList.get(j).info.guid == curKey
if allSDZonesList.get(j).info.disabled
continue
foundKey := true
break
if not foundKey
label.delete(breakLabels.get(curKey))