Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
179 views51 pages

Pawn Algo

The document is a Pine Script code for a trading indicator named 'pawn algo hourly opens structure'. It includes settings for order and propulsion blocks, styles for bullish and bearish signals, and methods for rendering and managing order blocks based on market swings. The script is designed to visualize and analyze market structures on an hourly basis, highlighting significant price levels and trends.

Uploaded by

warumonokisou
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
179 views51 pages

Pawn Algo

The document is a Pine Script code for a trading indicator named 'pawn algo hourly opens structure'. It includes settings for order and propulsion blocks, styles for bullish and bearish signals, and methods for rendering and managing order blocks based on market swings. The script is designed to visualize and analyze market structures on an hourly basis, highlighting significant price levels and trends.

Uploaded by

warumonokisou
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 51

//@version=5

indicator( 'pawn algo hourly opens structure', max_labels_count = 500,


max_lines_count = 500, max_boxes_count = 500, overlay = true)
//---------------------------------------------------------------------------------
------------------------------------}
//---------------------------------------------------------------------------------
------------------------------------
// Settings
//---------------------------------------------------------------------------------
------------------------------------{

display = display.all - display.status_line

obGroup = 'Order & Propulsion Blocks'


obLength = input.int(3, 'Swing Detection Length', minval = 1, group = obGroup,
display = display)

obMitigationPrice = input.string('Closing Price', 'Mitigation Price', options =


['Closing Price', 'Wick'], group = obGroup, display = display)
obCloseMitigationPrice = obMitigationPrice == 'Closing Price'

pbPropulsionBlock = input.bool(true, 'Highlight Propulsion Block Signals', group =


obGroup)
obUnassociatedTTip = 'An unassociated order block in the context of propulsion
blocks refers to an order block that is not linked or connected to any propulsion
block.'
obUnassociated = input.bool(true, 'Remove Unassociated Order Blocks', group =
obGroup, tooltip = obUnassociatedTTip)

obRemoveMitigatedTTip = 'The Remove Mitigated Blocks option will remove the


visualization of;\n -Mitigated Order Blocks,\n -Mitigated Propulsion Blocks and
their associated Order Blocks.'
obRemoveMitigated = input.bool(false, 'Remove Mitigated Blocks', group = obGroup,
tooltip = obRemoveMitigatedTTip)

obMostRecent = input.bool(false, 'Most Recent Blocks', inline = 'NR', group =


obGroup)
obMostRecentValue = input.int(30, '', minval = 1, inline = 'NR', group = obGroup,
display = display)

//Style
obStyleGroup = 'Order & Propulsion Blocks Style'

obShowBullish = input.bool(true, 'Bullish ', inline = 'bullish', group =


obStyleGroup)
obBullishColor = input(color.new(#2157f3, 4), 'OB', inline = 'bullish', group =
obStyleGroup)
pbBullishColor = input(color.new(#089981, 4), 'PB', inline = 'bullish', group =
obStyleGroup)

obShowBearish = input.bool(true, 'Bearish', inline = 'bearish', group =


obStyleGroup)
obBearishColor = input(color.new(#ff5d00, 4), 'OB', inline = 'bearish', group =
obStyleGroup)
pbBearishColor = input(color.new(#ff1100, 4), 'PB', inline = 'bearish', group =
obStyleGroup)
obBlockLabels = input.bool(true, 'Block Labels', inline = 'SZ', group =
obStyleGroup)
obLabelSize = input.string('Small', '', options = ['Tiny', 'Small', 'Normal'],
inline = 'SZ', group = obStyleGroup, display = display)

//---------------------------------------------------------------------------------
------------------------------------}
// 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 i (int) index of the bar

type BAR
float open = open
float high = high
float low = low
float close = close
int index = bar_index

type OrderBlock
int startIndex = bar_index
int endIndex = na
int confirmedIndex = na

float open = na
float high = na
float low = na
float close = na

line meanThresholdLine
label propulsionLabel
box orderblockLevelBox

bool isPropulsion

bool isProcessed = false


bool isActive = true
bool isMitigated = false

type SWING
float value = na
int index = na
bool cross = false

//---------------------------------------------------------------------------------
------------------------------------}
// Variables
//---------------------------------------------------------------------------------
------------------------------------{

BAR bar = BAR.new()


//---------------------------------------------------------------------------------
------------------------------------}
// Functions / Methods
//---------------------------------------------------------------------------------
------------------------------------{

method obRender(OrderBlock this, left, right, obOpen, obHigh, obLow, obClose,


color, isPropulsion, isBullish) =>

this.orderblockLevelBox.set_lefttop(left, isBullish ? obHigh : obLow)


this.orderblockLevelBox.set_rightbottom(right, isBullish ? obHigh : obLow)
this.orderblockLevelBox.set_bgcolor(color)
this.orderblockLevelBox.set_border_color(color)

if obBlockLabels
this.orderblockLevelBox.set_text((isPropulsion ? 'PB' : 'OB')) //
(isBullish? '▲' : '▼') +
this.orderblockLevelBox.set_text_color(color.new(color, 4))

if isPropulsion
this.meanThresholdLine.set_xy1(left , math.avg(obOpen, obClose))
this.meanThresholdLine.set_xy2(right, math.avg(obOpen, obClose))
this.meanThresholdLine.set_color(color.new(color, 4))

if pbPropulsionBlock
this.propulsionLabel.set_xy(left, isBullish ? obLow : obHigh)
this.propulsionLabel.set_textcolor(color.new(color, 4))

method obSetRight(OrderBlock this, right) =>


this.orderblockLevelBox.set_right(right), this.meanThresholdLine.set_x2(right),
this.endIndex := right

method obDelete(OrderBlock this) =>


this.orderblockLevelBox.delete(), this.meanThresholdLine.delete(),
this.propulsionLabel.delete()

swings(length)=>
var os = 0
var SWING swingHigh = SWING.new(na, na)
var SWING swingLow = SWING.new(na, na)

upper = ta.highest(length)
lower = ta.lowest (length)

os := high[length] > upper ? 0 : low[length] < lower ? 1 : os

if os == 0 and os[1] != 0
swingHigh := SWING.new(high[length], bar_index[length])

if os == 1 and os[1] != 1
swingLow := SWING.new(low[length], bar_index[length])

[swingHigh, swingLow]

breaches(obBullArray, obBearArray) =>


breachLow = bar.low
breachHigh = bar.high
breachIndex = bar.index
var SWING bullishBreachHigh = SWING.new(na, na)
var SWING bearishBreachLow = SWING.new(na, na)

if obBullArray.size() > 0
currentOrderBlock = obBullArray.get(0)
if bar.low <= currentOrderBlock.high and bar.low > currentOrderBlock.low
and bar.index > currentOrderBlock.confirmedIndex and not
currentOrderBlock.isMitigated and currentOrderBlock.isActive and not
currentOrderBlock.isPropulsion and bar.open > currentOrderBlock.high
breachLow := math.min(bar.low, breachLow[1])
breachHigh := breachLow == bar.low ? bar.high : breachHigh[1]
breachIndex := breachLow == bar.low ? bar.index : breachIndex[1]
bullishBreachHigh := SWING.new(breachHigh, breachIndex)
//log.info("yaz_kizim {0} {1}", bar.low, bar.index)

if obBearArray.size() > 0
currentOrderBlock = obBearArray.get(0)
if bar.high >= currentOrderBlock.low and bar.high < currentOrderBlock.high
and bar.index > currentOrderBlock.confirmedIndex and not
currentOrderBlock.isMitigated and currentOrderBlock.isActive and not
currentOrderBlock.isPropulsion and bar.open < currentOrderBlock.low
breachHigh := math.max(bar.high, breachHigh[1])
breachLow := breachHigh == bar.high ? bar.low : breachLow[1]
breachIndex := breachHigh == bar.high ? bar.index : breachIndex[1]
bearishBreachLow := SWING.new(breachLow, breachIndex)

[bullishBreachHigh, bearishBreachLow]

//---------------------------------------------------------------------------------
------------------------------------}
// Calculations
//---------------------------------------------------------------------------------
------------------------------------{

var bearishOrderBlockArray = array.new<OrderBlock>(0)


var bullishOrderBlockArray = array.new<OrderBlock>(0)

[swingHigh, swingLow] = swings(obLength)


[bullishBreachHigh, bearishBreachLow] = breaches(bullishOrderBlockArray,
bearishOrderBlockArray)

obTextSize = obLabelSize == 'Tiny' ? size.tiny


: obLabelSize == 'Small' ? size.small
: size.normal

if obShowBullish
if bar.close > swingHigh.value and not swingHigh.cross
swingHigh.cross := true

obBar = BAR.new(bar.open[1], bar.high[1], bar.low[1], bar.close[1],


bar.index[1])

for index = 1 to (bar.index - swingHigh.index) - 1


if bar.open[index] > bar.close[index]
if bar.low[index] <= obBar.low
obBar := BAR.new(bar.open[index], bar.high[index],
bar.low[index], bar.close[index], bar.index[index])

if bullishOrderBlockArray.size() > 0
recentOrderBlock = bullishOrderBlockArray.get(0)

if recentOrderBlock.isMitigated and recentOrderBlock.isPropulsion


previousOrderBlock = bullishOrderBlockArray.get(1)
if not previousOrderBlock.isPropulsion
previousOrderBlock.isMitigated := true

if recentOrderBlock.isMitigated or (not recentOrderBlock.isMitigated


and obBar.high > recentOrderBlock.high and obBar.index >
recentOrderBlock.startIndex) //and recentOrderBlock.low != obBar.low and
recentOrderBlock.high != obBar.high
bullishOrderBlockArray.unshift(OrderBlock.new(obBar.index,
bar.index, bar.index, obBar.open, obBar.high, obBar.low, obBar.close,
line.new(na, na, na, na, color = color(na), style =
line.style_dotted),
label.new(na, na, '▲', style = label.style_label_up, color =
color(na), size = size.small, textcolor = color(na)),
box.new(na, na, na, na, color(na), text_size = obTextSize,
text_halign = text.align_right, text_valign = text.align_top), false))

recentOrderBlock := bullishOrderBlockArray.get(0)
previousOrderBlock = bullishOrderBlockArray.get(1)

previousOrderBlock.isActive := false

if obBar.index <= previousOrderBlock.endIndex and


recentOrderBlock.low <= previousOrderBlock.high and recentOrderBlock.high >
previousOrderBlock.high
recentOrderBlock.isPropulsion := true

else if not previousOrderBlock.isPropulsion and obUnassociated


previousOrderBlock.obDelete()

else
bullishOrderBlockArray.unshift(OrderBlock.new(obBar.index, bar.index,
bar.index, obBar.open, obBar.high, obBar.low, obBar.close,
line.new(na, na, na, na, color = color(na), style =
line.style_dotted),
label.new(na, na, '▲', style = label.style_label_up, color =
color(na), size = size.small, textcolor = color(na)),
box.new(na, na, na, na, color(na), text_size = obTextSize,
text_halign = text.align_right, text_valign = text.align_top), false))

if bullishOrderBlockArray.size() > 0

recentOrderBlock = bullishOrderBlockArray.get(0)

if bar.close > bullishBreachHigh.value and not bullishBreachHigh.cross and


not recentOrderBlock.isMitigated and bullishBreachHigh.index >
recentOrderBlock.confirmedIndex
bullishBreachHigh.cross := true

recentOrderBlock.isActive := false
recentOrderBlock.obSetRight(bar.index)

bullishOrderBlockArray.unshift(OrderBlock.new(bar.index[bar.index -
bullishBreachHigh.index], bar.index, bar.index, bar.open[bar.index -
bullishBreachHigh.index], bullishBreachHigh.value, bar.low[bar.index -
bullishBreachHigh.index], bar.close[bar.index - bullishBreachHigh.index],
line.new(na, na, na, na, color = color(na), style =
line.style_dotted),
label.new(na, na, '▲', style = label.style_label_up, color =
color(na), size = size.small, textcolor = color(na)),
box.new(na, na, na, na, color(na), text_size = obTextSize,
text_halign = text.align_right, text_valign = text.align_top), true))

for arayIndex = bullishOrderBlockArray.size() - 1 to 0


currentOrderBlock = bullishOrderBlockArray.get(arayIndex)

if obRemoveMitigated and currentOrderBlock.isMitigated


currentOrderBlock.obDelete()

if not currentOrderBlock.isProcessed
currentOrderBlock.obRender(currentOrderBlock.startIndex, bar.index,
currentOrderBlock.open, currentOrderBlock.high, currentOrderBlock.low,
currentOrderBlock.close, currentOrderBlock.isPropulsion ? pbBullishColor :
obBullishColor, currentOrderBlock.isPropulsion, true)
currentOrderBlock.isProcessed := true

if currentOrderBlock.isActive and not currentOrderBlock.isMitigated

if (obCloseMitigationPrice ? bar.close : bar.low) <


currentOrderBlock.low
currentOrderBlock.isMitigated := true

currentOrderBlock.obSetRight(bar.index)

if obMostRecent
if bullishOrderBlockArray.size() > obMostRecentValue
currentOrderBlock = bullishOrderBlockArray.pop()
currentOrderBlock.obDelete()
else
if bullishOrderBlockArray.size() > 125
currentOrderBlock = bullishOrderBlockArray.pop()
currentOrderBlock.obDelete()

if obShowBearish
if bar.close < swingLow.value and not swingLow.cross
swingLow.cross := true

obBar = BAR.new(bar.open[1], bar.high[1], bar.low[1], bar.close[1],


bar.index[1])

for index = 1 to (bar.index - swingLow.index) - 1


if bar.open[index] < bar.close[index]
if bar.high[index] >= obBar.high
obBar := BAR.new(bar.open[index], bar.high[index],
bar.low[index], bar.close[index], bar.index[index])

if bearishOrderBlockArray.size() > 0
recentOrderBlock = bearishOrderBlockArray.get(0)

if recentOrderBlock.isMitigated and recentOrderBlock.isPropulsion


previousOrderBlock = bearishOrderBlockArray.get(1)
if not previousOrderBlock.isPropulsion
previousOrderBlock.isMitigated := true

if recentOrderBlock.isMitigated or (not recentOrderBlock.isMitigated


and obBar.low < recentOrderBlock.low and obBar.index > recentOrderBlock.startIndex)
bearishOrderBlockArray.unshift(OrderBlock.new(obBar.index,
bar.index, bar.index, obBar.open, obBar.high, obBar.low, obBar.close,
line.new(na, na, na, na, color = color(na), style =
line.style_dotted),
label.new(na, na, '▼', style = label.style_label_down, color =
color(na), size = size.small, textcolor = color(na)),
box.new(na, na, na, na, color(na), text_size = obTextSize,
text_halign = text.align_right, text_valign = text.align_bottom), false))

recentOrderBlock := bearishOrderBlockArray.get(0)
previousOrderBlock = bearishOrderBlockArray.get(1)

previousOrderBlock.isActive := false

if obBar.index <= previousOrderBlock.endIndex and


recentOrderBlock.high >= previousOrderBlock.low and recentOrderBlock.low <
previousOrderBlock.low
recentOrderBlock.isPropulsion := true

else if not previousOrderBlock.isPropulsion and obUnassociated


previousOrderBlock.obDelete()

else
bearishOrderBlockArray.unshift(OrderBlock.new(obBar.index, bar.index,
bar.index, obBar.open, obBar.high, obBar.low, obBar.close,
line.new(na, na, na, na, color = color(na), style =
line.style_dotted),
label.new(na, na, '▼', style = label.style_label_down, color =
color(na), size = size.small, textcolor = color(na)),
box.new(na, na, na, na, color(na), text_size = obTextSize,
text_halign = text.align_right, text_valign = text.align_bottom), false))

if bearishOrderBlockArray.size() > 0

recentOrderBlock = bearishOrderBlockArray.get(0)

if bar.close < bearishBreachLow.value and not bearishBreachLow.cross and


not recentOrderBlock.isMitigated and bearishBreachLow.index >
recentOrderBlock.confirmedIndex
bearishBreachLow.cross := true

recentOrderBlock.isActive := false
recentOrderBlock.obSetRight(bar.index)

bearishOrderBlockArray.unshift(OrderBlock.new(bar.index[bar.index -
bearishBreachLow.index], bar.index, bar.index, bar.open[bar.index -
bearishBreachLow.index], bar.high[bar.index - bearishBreachLow.index],
bearishBreachLow.value, bar.close[bar.index - bearishBreachLow.index],
line.new(na, na, na, na, color = color(na), style =
line.style_dotted),
label.new(na, na, '▼', style = label.style_label_down, color =
color(na), size = size.small, textcolor = color(na)),
box.new(na, na, na, na, color(na), text_size = obTextSize,
text_halign = text.align_right, text_valign = text.align_bottom), true))

for arayIndex = bearishOrderBlockArray.size() - 1 to 0


currentOrderBlock = bearishOrderBlockArray.get(arayIndex)
if obRemoveMitigated and currentOrderBlock.isMitigated
currentOrderBlock.obDelete()

if not currentOrderBlock.isProcessed
currentOrderBlock.obRender(currentOrderBlock.startIndex, bar.index,
currentOrderBlock.open, currentOrderBlock.high, currentOrderBlock.low,
currentOrderBlock.close, currentOrderBlock.isPropulsion ? pbBearishColor :
obBearishColor, currentOrderBlock.isPropulsion, false)
currentOrderBlock.isProcessed := true

if currentOrderBlock.isActive and not currentOrderBlock.isMitigated

if (obCloseMitigationPrice ? bar.close : bar.high) >


currentOrderBlock.high
currentOrderBlock.isMitigated := true

currentOrderBlock.obSetRight(bar.index)

if obMostRecent
if bearishOrderBlockArray.size() > obMostRecentValue
currentOrderBlock = bearishOrderBlockArray.pop()
currentOrderBlock.obDelete()
else
if bearishOrderBlockArray.size() > 125
currentOrderBlock = bearishOrderBlockArray.pop()
currentOrderBlock.obDelete()

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

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0
at https://mozilla.org/MPL/2.0/
// © Cleverchesstrading
// The Pawn Algo is a simple indicator that is useful for scalping in sync with a
higher timeframe should only be use in clear trending markets.
// The script is based of a simple pattern close above previous candle high means
higher prices we can see it in a green bar. Close below previous candle low means
lower prices we can see it in a red bar. Close inside previous candle range means
price is going to consolidate do some kind of retracement or reversal we mark it in
a black or dark color bar.
// It plot an arrow and a liquidity level when it detects a change in sentiment
from bullish to bearish or bearish to bullish.
// It plot the Higher timeframe previous completed candle range into the selected
Lower timeframe to easily see the HTF levels into the lower timeframe.
// The HTF range change colors depending of previous HTF candles closes following
the same idea, close above previous candle high means green range, close below
previous candle low means red range and close inside means a gray range. Finally it
plots the 50% of the HTF range and the previous close high and low.
// Finally it draws a yellow value zone that is the difference between the previous
candle close and 50% of the previous range. This zone is ideal for taking
continuation trades in favor of the HTF trend.
// last version improvements:We made available the HTF range in days,weeks,months
and we add some visual signature when price takes the HTF high or the low. And some
colors to the Close and HTF 50% labels. Finally a way to filter entries is added
//@version=5
//indicator("ThePawnAlgo", overlay=true)
//inputs
HTFenable= input.bool(true, "See HTF in LTF",group = "HTF/LTF range")
RangeType= input.string("minutes", "HTFtype min/days/weeks/Months?", options
=[ "minutes","days","weeks","Months"],group = "HTF/LTF range")
RangeTF= input.int(1440, "HTF minutes option", 1, 1440,tooltip = "Max valid number
is 1440minutes",group = "HTF/LTF range")//HTF min range
RangeTFday= input.int(1, "HTF Days/Weeks/Months", 1, 365,tooltip = "Max valid
numbers are 365Days, 52Weeks, 12Months",group = "HTF/LTF range")//HTF days range
RangeLTF= input.int(1200, "LTF visibility min", 1, 1440,tooltip = "This is the max
timeframe to see the HTF",group = "HTF/LTF range")//LTF range visible

Barcolors= input.bool(true, "Show colored bars",group = "Visualization")


inside= input.bool(false, "Show insidebars",group = "Visualization")
buysignals= input.bool(true, "Show Buys arrows",group = "Entries")
sellsignals= input.bool(true, "Show Sells arrows",group = "Entries")
showstopsell= input.bool(true, "Show Sl sell",group = "Visualization")
showstopbuy= input.bool(true, "Show Sl buy",group = "Visualization")
hlbreaks=input.bool(true, "Show HTF HL breaks",group = "Visualization")

showalignonly= input.bool(true, "Show only HTF aling entries", group = "Entries")

showpredisonly= input.bool(true, "Show only premium/discount entries", group =


"Entries")

//variables
var float stopvaluebuy=0.0
var float stopvalueshort=0.0
var string HTFrequest=""
var string BIAS=""
var string biasHTF=""
var string HTFclose=""
var bool slbuytaken=false
var bool slselltaken=false
var bool insideHTF=false
var float Midrange=0.0
var float Midrangecurrent=0.0
var bool HTFHtaken=false
var bool HTFLtaken=false

//Simple pattern to identify if price is going higher or lower


longCondition = close>high[1]
shortCondition = close<low[1]
//bars colors
barcolor(longCondition and Barcolors? color.green:shortCondition and Barcolors?
color.red :na)
barcolor(close<=high[1] and close>close[1] and inside and Barcolors? color.rgb(1,
70, 3):close>=low[1] and close<close[1] and inside and Barcolors?color.rgb(82, 0,
0) :Barcolors?color.rgb(0, 0, 0):na)

//Sentiment change
if longCondition
BIAS:="Long"
else if shortCondition
BIAS:="Short"

//recalculating liquidity when is taken


if high>stopvalueshort
slselltaken:=true
if low<stopvaluebuy
slbuytaken:=true

//liquidity levels last high or low after the signal


if longCondition and barstate.isconfirmed and (BIAS[1]=="Short" or slbuytaken)
stopvaluebuy:=low
slselltaken:=false
slbuytaken:=false
if shortCondition and barstate.isconfirmed and (BIAS[1]=="Long" or slselltaken)
stopvalueshort:=high
slselltaken:=false
slbuytaken:=false

//HTF requested range is ajusted here for days weeks months or minutes option, be
aware of the limits
if RangeType=="days"
HTFrequest:=str.tostring(RangeTFday)+"D"
else if RangeType=="weeks"
if RangeTFday<=52
HTFrequest:=str.tostring(RangeTFday)+"W"
else
HTFrequest:="52W"
else if RangeType=="Months"
if RangeTFday<=12
HTFrequest:=str.tostring(RangeTFday)+"M"
else
HTFrequest:="12M"
else if RangeType=="minutes"
HTFrequest:=str.tostring(RangeTF)

//HTF Range previous highs lows and close


RangeHigh = request.security(syminfo.tickerid, HTFrequest, high[1], lookahead =
barmerge.lookahead_on)
RangeLow = request.security(syminfo.tickerid, HTFrequest, low[1], lookahead =
barmerge.lookahead_on )
RangeClose = request.security(syminfo.tickerid, HTFrequest, close[1], lookahead =
barmerge.lookahead_on )

//Detecting a new HTF range to reset highs or lows taken


if RangeClose!=RangeClose[1]
HTFHtaken:=false
HTFLtaken:=false

//HTF 50% calculation


Midrange:=((RangeHigh-RangeLow)/2)+RangeLow //50% HTF

//HTF buy and sell sentiment or inside candle


if RangeClose>RangeHigh[1]
biasHTF:="long"
insideHTF:=false
else if RangeClose<RangeLow[1]
biasHTF:="short"
insideHTF:=false
else if RangeClose>RangeLow[1] and RangeClose<RangeHigh[1] and RangeClose!
=RangeClose[1]
insideHTF:=true
//here we check HTF previous close
if RangeClose>RangeClose[1]
HTFclose:="higher"
else if RangeClose<RangeClose[1]
HTFclose:="lower"

//premium or discount relative to open and 50%


discount=(not(showpredisonly) or low<Midrange or low<RangeClose)
premium=(not(showpredisonly) or high>Midrange or high>RangeClose)

//HTF plot visible only in selected lower times or below maximum levels
visibility=( (((timeframe.isdaily and timeframe.multiplier<RangeTFday*20) or
(timeframe.isweekly and timeframe.multiplier<RangeTFday*4)) and
RangeType=="Months") or ( ((timeframe.isdaily and
timeframe.multiplier<RangeTFday*5) or (timeframe.isweekly and
timeframe.multiplier<RangeTFday)) and RangeType=="weeks") or
(timeframe.multiplier<=RangeLTF and timeframe.isminutes )) and HTFenable
Mr=plot(Midrange, title="HTFMidrange", color=biasHTF=="long" and visibility?
color.rgb(0, 92, 3,80): biasHTF=="short" and visibility? color.rgb(131, 0,
0,80):na, linewidth = 2, style = plot.style_circles)
Rc=plot(RangeClose,title="HTFclose", color=HTFclose=="higher" and visibility?
color.rgb(2, 63, 0, 50):HTFclose=="lower" and visibility? color.rgb(117, 0, 0,
50):na, linewidth = 2, style = plot.style_line)
Rl=plot(RangeLow, color=insideHTF and visibility?color.rgb(255, 255, 255, 50):na)
Rh=plot(RangeHigh, color=insideHTF and visibility?color.rgb(255, 255, 255, 50):na)
//HRF range
fill(Rh, Rl, color=insideHTF and visibility? color.rgb(0, 0, 0, 90):biasHTF=="long"
and visibility? color.rgb(0, 131, 0, 95): biasHTF=="short" and visibility?
color.rgb(133, 3, 3, 90):na)
//Value zone
fill(Mr, Rc, visibility? color.rgb(129, 131, 0, 86):na)

//HTF labels
labelRangeHigh = label.new( visibility ? bar_index:na , RangeHigh,
text=RangeType=="Months"?'________________P'+str.tostring(RangeTFday)+"M
H":RangeType=="weeks"?'________________P'+str.tostring(RangeTFday)+"W
H":RangeType=="days"?'________________P'+str.tostring(RangeTFday)+"D
H":'________________P'+str.tostring(RangeTF)+"H", color=color.rgb(0, 0, 0, 80),
textcolor=color.rgb(0, 0, 0, 80),style=label.style_none, size=size.normal)
label.delete(labelRangeHigh[1])
labelRangeLow = label.new( visibility ? bar_index:na , RangeLow,
text=RangeType=="Months"?'________________P'+str.tostring(RangeTFday)+"M
L":RangeType=="weeks"?'________________P'+str.tostring(RangeTFday)+"W
L":RangeType=="days"?'________________P'+str.tostring(RangeTFday)+"D
L":'________________P'+str.tostring(RangeTF)+"L", color=color.rgb(0, 0, 0, 80),
textcolor=color.rgb(0, 0, 0, 80),style=label.style_none, size=size.normal)
label.delete(labelRangeLow[1])
labelRangeClose = label.new(visibility ? bar_index:na , RangeClose,
text=RangeType=="Months"?'_______________P'+str.tostring(RangeTFday)+"M
C":RangeType=="weeks"?'_______________P'+str.tostring(RangeTFday)+"W
C":RangeType=="days"?'_______________P'+str.tostring(RangeTFday)+"D
C":'_______________P'+str.tostring(RangeTF)+"C", color=color.rgb(0, 0, 0, 80),
textcolor=HTFclose=="higher"?color.rgb(0, 92, 3,50):HTFclose=="lower"?
color.rgb(131, 0, 0,50):color.rgb(0, 0, 0, 80),style=label.style_none,
size=size.normal)
label.delete(labelRangeClose[1])
labelRange50 = label.new(visibility ? bar_index:na , Midrange,
text='_______________'+" HTF 50%", color=color.rgb(0, 0, 0, 80),
textcolor=biasHTF=="long"?color.rgb(0, 92, 3,80):biasHTF=="short"?color.rgb(131, 0,
0,80):color.rgb(0, 0, 0, 80),style=label.style_none, size=size.normal)
label.delete(labelRange50[1])
//HTF High Low taken
if high>RangeHigh
HTFHtaken:=true
if low<RangeLow
HTFLtaken:=true
//Ploting the highs and lows taken
plot(HTFHtaken and HTFHtaken[1]==false and high>RangeHigh and (high>high[1] or
high[1]>RangeHigh) and hlbreaks and visibility? high:na, style=plot.style_circles,
color=biasHTF=="short"?color.rgb(216, 184, 4, 80):color.rgb(8, 228, 0, 80),
linewidth=10, title='hightaken')
plot(HTFLtaken and HTFLtaken[1]==false and low<RangeLow and (low<low[1] or
low[1]<RangeLow) and hlbreaks and visibility? low:na, style=plot.style_circles,
color=biasHTF=="long"?color.rgb(216, 184, 4, 80):color.rgb(216, 4, 50, 80),
linewidth=10, title='lowtaken')

//Arrows entry signals


plotshape(longCondition and BIAS[1]=="Short" and barstate.isconfirmed and discount
and visibility, style=shape.triangleup, location = location.belowbar,
color=buysignals and (not(showalignonly) or biasHTF=="long") ?color.rgb(2, 92, 196,
47):na,size =size.tiny)
plotshape(shortCondition and BIAS[1]=="Long" and barstate.isconfirmed and premium
and visibility, style=shape.triangledown, location = location.abovebar,
color=sellsignals and (not(showalignonly) or biasHTF=="short")?color.rgb(255, 82,
82, 45):na,size =size.tiny )

//liquidity plot
plot(showstopbuy and BIAS=="Long" and discount and barstate.isconfirmed and
visibility?stopvaluebuy:showstopsell and BIAS=="Short" and premium and
barstate.isconfirmed and visibility?stopvalueshort:na, title='sl',
color=BIAS=="Long"?color.rgb(30, 53, 0, 47):BIAS=="Short"?color.rgb(102, 46, 0, 46)
: na, linewidth=1, style=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
//indicator( 'Swing Failure Pattern [LuxAlgo]', 'LuxAlgo - Swing Failure Pattern',
max_labels_count = 500, max_lines_count = 500, max_boxes_count = 500, overlay =
true)
//---------------------------------------------------------------------------------
------------------------------------}
//Settings
//---------------------------------------------------------------------------------
------------------------------------{
sp = ' '
len = input.int ( 5 , 'Swings' , minval= 1
)
bull = input.bool ( true , 'Bullish SFP'
)
bear = input.bool ( true , 'Bearish SFP'
)

iVal = input.string ('None', 'Validation'+sp+ ' ', group='Volume


Validation'
, options = ['Volume outside swing < Threshold' ,'Volume outside swing >
Threshold','None'])
percent = input.float (25, 'Volume Threshold %' , inline='valy',
group='Volume Validation'
, tooltip = '% of Total Volume' , minval= 0 ,
maxval=100 )
auto = input.bool (true, '' , inline='auto',
group='Volume Validation' )
mlt = input.int (50 , ' Auto' + sp , inline='auto',
group='Volume Validation' )
res = input.timeframe('1' , sp +' LTF' + sp +' ', inline='ltf' ,
group='Volume Validation' )
prem = input.bool (false ,' Premium' ,
group='Volume Validation'
, tooltip = 'Premium Plan or higher'
)
showDash = input.bool (true , 'Show Dashboard' , group=
'Dashboard' )
dashLoc = input.string ( 'Top Right' , 'Location'
, options = ['Top Right', 'Bottom Right', 'Bottom Left'] , group=
'Dashboard' )
textSize = input.string ( 'Normal' , 'Size'
, options = ['Tiny', 'Small', 'Normal'] , group=
'Dashboard' )
dSwingLine = input.bool (true , 'Swing Lines' , group=
'Style' )
dOpposLine = input.bool (true , 'Confirmation Lines' , group=
'Style' )
dSFP_Line = input.bool (true , 'Swing Failure Wick' , group=
'Style' )
dSFP_Label = input.bool (true , 'Swing Failure Label' , group=
'Style' )
colBl = input.color (#089981 , 'Lines / Labels' , inline='lin' , group=
'Style' )
colBr = input.color (#f23645 , '' , inline='lin' , group=
'Style'
, tooltip = 'Bullish/Bearish'
)
colBl2 = input.color (#08998180, 'SFP Wicks ', inline='wic' , group=
'Style' )
colBr2 = input.color (#f2364580, '' , inline='wic' , group=
'Style'
, tooltip = 'Wick outside Swing, Bullish/Bearish'
)

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

//UDT
//-----------------------------------------------------------------------------{
type piv
float swing_prc // price
int swing_bix // bar_index
float oppos_prc // price
int oppos_bix // bar_index
bool active
bool confirmed
line swing_line
line oppos_line
line wicky_line
label wicky_label

type swing
int bix
float prc

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

//Variables
//-----------------------------------------------------------------------------{
n = bar_index
INV = color(na)
FGc = chart.fg_color

table_position = dashLoc == 'Bottom Left' ? position.bottom_left


: dashLoc == 'Top Right' ? position.top_right
: position.bottom_right

table_size = textSize == 'Tiny' ? size.tiny


: textSize == 'Small' ? size.small
: size.normal

var tb = table.new(table_position, 2, 3
, bgcolor = #1e222d
, border_color = #373a46
, border_width = 1
, frame_color = #373a46
, frame_width = 1)

var swing swingH = swing.new()


var swing swingL = swing.new()
var piv pivH = piv.new()
var piv pivL = piv.new()

validate = iVal != 'None'


valHigher= iVal == 'Volume outside swing > Threshold'
valLower = iVal == 'Volume outside swing < Threshold'

//---------------------------------------------------------------------------------
------------------------------------}
//Method
//---------------------------------------------------------------------------------
------------------------------------{
method n(float piv) => bool out = not na(piv)

//---------------------------------------------------------------------------------
------------------------------------}
//Execution
//---------------------------------------------------------------------------------
------------------------------------{
tfS = timeframe.in_seconds( res )
tfC = timeframe.in_seconds(timeframe.period)
rs = auto ? tfC / mlt : tfS
if not validate
res := timeframe.period
else
rs := prem ? rs : math.max(60, rs)
res := timeframe.from_seconds(math.min(tfC, rs))

ph = ta.pivothigh(len, 1)
pl = ta.pivotlow (len, 1)
[ltf_close, ltf_volume] = request.security_lower_tf(syminfo.tickerid, res, [close,
volume])

ltf_size = ltf_close.size()

if validate
if ltf_size > 0 and ltf_size[1] == 0
line.new(n, close, n, close + syminfo.mintick, color=color.silver,
style=line.style_dotted, extend=extend.both)

//---------------------------------------------------------------------------------
------------------------------------}
//Bearish Pattern
//---------------------------------------------------------------------------------
------------------------------------{
if bear

if ph.n()
swingH.bix := n-1
swingH.prc := ph

sw = swingH.prc
bx = swingH.bix
if high > sw
and open < sw
and close < sw
valid = true
if validate
if ltf_close.size() > 0
outsideVolume = 0.
totalVolume = ltf_volume.sum()
for j = 0 to ltf_close.size() -1
if ltf_close.get(j) > sw
outsideVolume += ltf_volume.get(j)
if (valHigher ? 100 / totalVolume * outsideVolume < percent
: 100 / totalVolume * outsideVolume > percent
)
valid := false

//if valid
// label.new(n, high, text=str.format("Total Volume: {0}\nWick
Volume: {1}", totalVolume, outsideVolume))

if valid

opposL = sw
opposB = n

for i = 1 to n - bx -1
if low [i] < opposL
opposL := low [i]
opposB := n - i

if not pivH.confirmed
pivH.swing_line .delete()
pivH.oppos_line .delete()
pivH.wicky_line .delete()
pivH.wicky_label.delete()
pivH := piv.new(sw, bx, opposL, opposB, true, false)

if dSwingLine
pivH.swing_line := line.new (bx , sw , n, sw ,
color=colBr)
if dOpposLine
pivH.oppos_line := line.new (opposB, opposL, n, opposL,
color=colBr, style=line.style_dotted)
if dSFP_Line
pivH.wicky_line := line.new (n , high , n, sw ,
color=colBr2, width=3)
if dSFP_Label
pivH.wicky_label := label.new(n , high
, style=label.style_label_down
, text='SFP', textcolor=colBr
, color=INV, size=size.normal
)

if pivH.active and not pivH.confirmed

pivH.swing_line.set_x2(n)
pivH.oppos_line.set_x2(n)

if close < pivH.oppos_prc


pivH.confirmed := true

if pivH.wicky_label.get_x() == n
pivH.wicky_label.set_text('SFP\n▼')
else
label.new(n, high, style=label.style_label_down, text='▼',
textcolor=colBr, color=INV, size=size.normal)

if n - pivH.swing_bix > 500


or close > pivH.swing_prc
pivH.active := false
if not pivH.confirmed
pivH.swing_line .delete()
pivH.oppos_line .delete()
pivH.wicky_line .delete()
pivH.wicky_label.delete()

//---------------------------------------------------------------------------------
------------------------------------}
//Bullish Pattern
//---------------------------------------------------------------------------------
------------------------------------{
if bull

if pl.n()
swingL.bix := n-1
swingL.prc := pl

sw = swingL.prc
bx = swingL.bix
if low < sw
and open > sw
and close > sw
valid = true
if validate
if ltf_close.size() > 0
outsideVolume = 0.
totalVolume = ltf_volume.sum()
for j = 0 to ltf_close.size() -1
if ltf_close.get(j) < sw
outsideVolume += ltf_volume.get(j)
if (valHigher ? 100 / totalVolume * outsideVolume < percent
: 100 / totalVolume * outsideVolume > percent
)
valid := false
if valid

opposH = sw
opposB = n

for i = 1 to n - bx -1
if high[i] > opposH
opposH := high[i]
opposB := n - i

if not pivL.confirmed
pivL.swing_line .delete()
pivL.oppos_line .delete()
pivL.wicky_line .delete()
pivL.wicky_label.delete()

pivL := piv.new(sw, bx, opposH, opposB, true, false)

if dSwingLine
pivL.swing_line := line.new (bx , sw , n, sw ,
color=colBl )
if dOpposLine
pivL.oppos_line := line.new (opposB, opposH, n, opposH,
color=colBl , style=line.style_dotted)
if dSFP_Line
pivL.wicky_line := line.new (n , low , n, sw ,
color=colBl2, width=3)
if dSFP_Label
pivL.wicky_label := label.new(n , low
, style=label.style_label_up
, text='SFP', textcolor=colBl
, color=INV, size=size.normal
)

if pivL.active and not pivL.confirmed

pivL.swing_line.set_x2(n)
pivL.oppos_line.set_x2(n)

if close > pivL.oppos_prc


pivL.confirmed := true

if pivL.wicky_label.get_x() == n
pivL.wicky_label.set_text('▲\nSFP')
else
label.new(n, low, style=label.style_label_up, text='▲',
textcolor=colBl, color=INV, size=size.normal)

if n - pivL.swing_bix > 500


or close < pivL.swing_prc
pivL.active := false
if not pivL.confirmed
pivL.swing_line .delete()
pivL.oppos_line .delete()
pivL.wicky_line .delete()
pivL.wicky_label.delete()

//---------------------------------------------------------------------------------
------------------------------------}
//Dashboard
//---------------------------------------------------------------------------------
------------------------------------{
if barstate.islast and validate and showDash
tb.cell(0, 0, str.format("LTF: {0}", res), text_color=color.white,
text_size=table_size)

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

//
//@version=6
//ndicator('Multi TimeFrame OHLC Overlay @MaxMaserati', shorttitle = 'MTC OHLC
@MaxMaserati', overlay = true, max_boxes_count = 500, max_lines_count = 500)

// Helper function to format timeframe label prefix


formatTimeframePrefix(timeframe) =>
tf = str.tonumber(timeframe)
if str.contains(timeframe, 'D')
'D' + str.replace(timeframe, 'D', '')
else if str.contains(timeframe, 'W')
'W' + str.replace(timeframe, 'W', '')
else if str.contains(timeframe, 'H')
'H' + str.replace(timeframe, 'H', '')
else
'M' + timeframe

DEFAULT_RESOLUTION = '240'

var prevBarIndex = bar_index

drawBox(left, right, top, bottom, diff, bodyColor, showBody) =>


drawnBox = box.new(left, top, right, bottom)
if showBody
box.set_border_color(drawnBox, color.new(color.black, 100))
box.set_bgcolor(drawnBox, bodyColor)
else
box.delete(drawnBox)
drawnBox := na
drawnBox
drawnBox

drawLines(left, right, level, lineColor, showLine) =>


if showLine
line.new(left, level, right, level, color = lineColor, width = 1)

timeframeInput = input.timeframe(DEFAULT_RESOLUTION, title = 'MTC @MaxMaserati')


// Extended Lines Options Group
extendedLinesGroup = 'Extended OHLC Lines'
showExtendedLines = input.bool(true, title = 'Show Extended OHLC Lines', group =
extendedLinesGroup)
extendedTimeframe = input.timeframe('D', title = 'Extended Lines Timeframe', group
= extendedLinesGroup)

// Labels Options Group


labelsGroup = 'Labels Options'
showLabels = input.bool(true, title = 'Show Labels', group = labelsGroup)
showOpenLabel = input.bool(true, title = 'Show Open Label', inline = 'labelOpen',
group = labelsGroup)
openLabelColor = input(color.new(color.blue, 0), title = '', inline = 'labelOpen',
group = labelsGroup)
showHighLabel = input.bool(true, title = 'Show High Label', inline = 'labelHigh',
group = labelsGroup)
highLabelColor = input(color.new(color.green, 0), title = '', inline = 'labelHigh',
group = labelsGroup)
showLowLabel = input.bool(true, title = 'Show Low Label', inline = 'labelLow',
group = labelsGroup)
lowLabelColor = input(color.new(color.red, 0), title = '', inline = 'labelLow',
group = labelsGroup)
showCloseLabel = input.bool(true, title = 'Show Close Label', inline =
'labelClose', group = labelsGroup)
closeLabelColor = input(color.new(color.purple, 0), title = '', inline =
'labelClose', group = labelsGroup)

// Extended Lines Colors


showExtendedOpen = input.bool(true, title = 'Show Extended Open', inline =
'extOpen', group = extendedLinesGroup)
extendedOpenColor = input(color.new(color.blue, 50), title = '', inline =
'extOpen', group = extendedLinesGroup)
showExtendedHigh = input.bool(true, title = 'Show Extended High', inline =
'extHigh', group = extendedLinesGroup)
extendedHighColor = input(color.new(color.green, 50), title = '', inline =
'extHigh', group = extendedLinesGroup)
showExtendedLow = input.bool(true, title = 'Show Extended Low', inline = 'extLow',
group = extendedLinesGroup)
extendedLowColor = input(color.new(color.red, 50), title = '', inline = 'extLow',
group = extendedLinesGroup)
showExtendedClose = input.bool(true, title = 'Show Extended Close', inline =
'extClose', group = extendedLinesGroup)
extendedCloseColor = input(color.new(color.purple, 50), title = '', inline =
'extClose', group = extendedLinesGroup)

// Display Options Group


displayGroup = 'Display Options'
showCurrentBox = input.bool(true, title = 'Show Box in Current Candle', group =
displayGroup)
showCurrentLines = input.bool(true, title = 'Show Lines in Current Candle', group =
displayGroup)

// Bullish Candle Group


bullishGroup = 'Bullish Candles'
showBullishBody = input.bool(true, title = '', inline = 'bullishBody', group =
bullishGroup)
bullishBodyColor = input(color.new(color.green, 80), title = 'Body', inline =
'bullishBody', group = bullishGroup)
showBullishWick = input.bool(true, title = '', inline = 'bullishWick', group =
bullishGroup)
bullishWickColor = input(color.new(color.green, 80), title = 'Wick', inline =
'bullishWick', group = bullishGroup)

// Bearish Candle Group


bearishGroup = 'Bearish Candles'
showBearishBody = input.bool(true, title = '', inline = 'bearishBody', group =
bearishGroup)
bearishBodyColor = input(color.new(color.red, 80), title = 'Body', inline =
'bearishBody', group = bearishGroup)
showBearishWick = input.bool(true, title = '', inline = 'bearishWick', group =
bearishGroup)
bearishWickColor = input(color.new(color.red, 80), title = 'Wick', inline =
'bearishWick', group = bearishGroup)

// OHLC Lines Group


ohlcGroup = 'OHLC Lines'
showOpenLine = input.bool(true, title = 'Open', inline = 'openLine', group =
ohlcGroup)
openLineColor = input(color.new(color.black, 30), title = '', inline = 'openLine',
group = ohlcGroup)
showHighLine = input.bool(true, title = 'High', inline = 'highLine', group =
ohlcGroup)
highLineColor = input(color.new(color.black, 30), title = '', inline = 'highLine',
group = ohlcGroup)
showLowLine = input.bool(true, title = 'Low', inline = 'lowLine', group =
ohlcGroup)
lowLineColor = input(color.new(color.black, 30), title = '', inline = 'lowLine',
group = ohlcGroup)
showCloseLine = input.bool(true, title = 'Close', inline = 'closeLine', group =
ohlcGroup)
closeLineColor = input(color.new(color.black, 30), title = '', inline =
'closeLine', group = ohlcGroup)

type OHLC
float o
float h
float l
float c
float prevC

makeOHLC(int bb = 0) =>
OHLC.new(open[bb], high[bb], low[bb], close[bb], close[bb + 1])

// Request data from both timeframes


[bar0, bar1] = request.security(syminfo.tickerid, timeframeInput, [makeOHLC(0),
makeOHLC(1)], lookahead = barmerge.lookahead_on)
[extOpen, extHigh, extLow, extClose] = request.security(syminfo.tickerid,
extendedTimeframe, [open[1], high[1], low[1], close[1]], lookahead =
barmerge.lookahead_on)

// Period calculations
isNewPeriod = ta.change(time(timeframeInput)) != 0
sec = barstate.islast ? isNewPeriod ? bar1 : bar0 : bar1
diff = sec.c - sec.o
left = prevBarIndex
right = barstate.islast ? isNewPeriod ? bar_index - 1 : bar_index : bar_index - 1

// Body range calculation


float bodyTop = math.max(sec.o, sec.c)
float bodyBottom = math.min(sec.o, sec.c)

// Variable declarations
var box prevBodyBox = na
var box prevWickBox = na
var array<line> prevHighLines = array.new_line()
var array<line> prevOpenLines = array.new_line()
var array<line> prevCloseLines = array.new_line()
var array<line> prevLowLines = array.new_line()
var line extendedOpenLine = na
var line extendedHighLine = na
var line extendedLowLine = na
var line extendedCloseLine = na
var label extOpenLabel = na
var label extHighLabel = na
var label extLowLabel = na
var label extCloseLabel = na
var line curentHigLine = na
var line currentLowLine = na
var line currentOpenLine = na
var line currentCloseLine = na

// Box and Line Drawing


if isNewPeriod
prevBarIndex := bar_index

// Draw boxes based on candle direction


if diff >= 0
drawBox(left, right, bodyTop, bodyBottom, diff, bullishBodyColor,
showBullishBody)
drawBox(left, right, sec.h, sec.l, diff, bullishWickColor, showBullishWick)
else
drawBox(left, right, bodyTop, bodyBottom, diff, bearishBodyColor,
showBearishBody)
drawBox(left, right, sec.h, sec.l, diff, bearishWickColor, showBearishWick)

// Draw OHLC lines


if showHighLine
array.push(prevHighLines, line.new(left, sec.h, right, sec.h, color =
highLineColor, width = 1))
if showOpenLine
array.push(prevOpenLines, line.new(left, sec.o, right, sec.o, color =
openLineColor, width = 1))
if showCloseLine
array.push(prevCloseLines, line.new(left, sec.c, right, sec.c, color =
closeLineColor, width = 1))
if showLowLine
array.push(prevLowLines, line.new(left, sec.l, right, sec.l, color =
lowLineColor, width = 1))

// Update extended lines and labels


if showExtendedLines and barstate.islast
// Delete previous lines and labels
line.delete(extendedOpenLine)
line.delete(extendedHighLine)
line.delete(extendedLowLine)
line.delete(extendedCloseLine)
label.delete(extOpenLabel)
label.delete(extHighLabel)
label.delete(extLowLabel)
label.delete(extCloseLabel)

tfPrefix = formatTimeframePrefix(extendedTimeframe)
rightExtend = bar_index + 25

if showExtendedOpen
extendedOpenLine := line.new(bar_index - 50, extOpen, rightExtend, extOpen,
color = extendedOpenColor, width = 2, extend = extend.none)
if showLabels and showOpenLabel
extOpenLabel := label.new(rightExtend, extOpen, tfPrefix + 'O', color =
color.new(color.black, 100), textcolor = openLabelColor, style =
label.style_label_left, size = size.small)
extOpenLabel

if showExtendedHigh
extendedHighLine := line.new(bar_index - 50, extHigh, rightExtend, extHigh,
color = extendedHighColor, width = 2, extend = extend.none)
if showLabels and showHighLabel
extHighLabel := label.new(rightExtend, extHigh, tfPrefix + 'H', color =
color.new(color.black, 100), textcolor = highLabelColor, style =
label.style_label_left, size = size.small)
extHighLabel

if showExtendedLow
extendedLowLine := line.new(bar_index - 50, extLow, rightExtend, extLow,
color = extendedLowColor, width = 2, extend = extend.none)
if showLabels and showLowLabel
extLowLabel := label.new(rightExtend, extLow, tfPrefix + 'L', color =
color.new(color.black, 100), textcolor = lowLabelColor, style =
label.style_label_left, size = size.small)
extLowLabel

if showExtendedClose
extendedCloseLine := line.new(bar_index - 50, extClose, rightExtend,
extClose, color = extendedCloseColor, width = 2, extend = extend.none)
if showLabels and showCloseLabel
extCloseLabel := label.new(rightExtend, extClose, tfPrefix + 'C', color
= color.new(color.black, 100), textcolor = closeLabelColor, style =
label.style_label_left, size = size.small)
extCloseLabel

// Handle last bar


if barstate.islast
if isNewPeriod
prevBodyBox := na
prevWickBox := na
array.clear(prevHighLines)
array.clear(prevOpenLines)
array.clear(prevCloseLines)
array.clear(prevLowLines)
else
box.delete(prevBodyBox)
box.delete(prevWickBox)
array.clear(prevHighLines)
array.clear(prevOpenLines)
array.clear(prevCloseLines)
array.clear(prevLowLines)
if showCurrentBox
if diff >= 0
prevBodyBox := drawBox(left, right, bodyTop, bodyBottom, diff,
bullishBodyColor, showBullishBody)
prevWickBox := drawBox(left, right, sec.h, sec.l, diff,
bullishWickColor, showBullishWick)
prevWickBox
else
prevBodyBox := drawBox(left, right, bodyTop, bodyBottom, diff,
bearishBodyColor, showBearishBody)
prevWickBox := drawBox(left, right, sec.h, sec.l, diff,
bearishWickColor, showBearishWick)
prevWickBox

if showCurrentLines
if showHighLine
line.delete(curentHigLine)
curentHigLine := line.new(left, sec.h, right, sec.h, color =
highLineColor, width = 1)
curentHigLine
//array.push(prevHighLines, line.new(left, sec.h, right, sec.h,
color=highLineColor, width=1))
if showOpenLine
line.delete(currentOpenLine)
currentOpenLine := line.new(left, sec.o, right, sec.o, color =
openLineColor, width = 1)
currentOpenLine
// array.push(prevOpenLines, line.new(left, sec.o, right, sec.o,
color=openLineColor, width=1))
if showCloseLine
line.delete(currentCloseLine)
currentCloseLine := line.new(left, sec.c, right, sec.c, color =
closeLineColor, width = 1)
currentCloseLine
// array.push(prevCloseLines, line.new(left, sec.c, right, sec.c,
color=closeLineColor, width=1))
if showLowLine
line.delete(currentLowLine)
currentLowLine := line.new(left, sec.l, right, sec.l, color =
lowLineColor, width = 1)
currentLowLine
// array.push(prevLowLines, line.new(left, sec.l, right, sec.l,
color=lowLineColor, width=1))

// Timeframe Table
var table tfTable = table.new(position.top_right, 1, 2, border_width = 1,
frame_color = color.gray, border_color = color.gray)
if barstate.islast
table.cell(tfTable, 0, 0, 'Time: ' + timeframeInput, text_color = color.white,
text_size = size.small, bgcolor = color.new(color.black, 0))
table.cell(tfTable, 0, 1, 'Ext Time: ' + extendedTimeframe, text_color =
color.white, text_size = size.small, bgcolor = color.new(color.black, 0))

// This source code is subject to the terms of the Mozilla Public License 2.0 at
https://mozilla.org/MPL/2.0/
// © tradeforopp
//@version=5
//ndicator("Protected Highs & Lows [TFO]", "Protected Highs & Lows [TFO]", true,
max_lines_count = 500, max_labels_count = 500, max_boxes_count = 500)

var g_STR = "Structure"


ps = input.int(1, "Pivot Strength", group = g_STR)
color_trend = input.bool(true, "Trend Candles", inline = "TREND", group = g_STR)
show_labels = input.bool(true, "Show Structure Labels", inline = "MSS", group =
g_STR)
label_type = input.string("MSS", "", options = ['MSS', 'BOS', 'All'], inline =
"MSS", group = g_STR)

var g_PHL = "Protected Highs & Lows"


show_phl = input.bool(true, "Show Protected Highs & Lows", inline = "PHL", group =
g_PHL)
trail_phl = input.bool(true, "Show Protected Trail", inline = "TRAIL", group =
g_PHL)
trail_width = input.int(2, "", inline = "TRAIL", group = g_PHL)

var g_PB = "Pullbacks"


use_valid_pbs = input.bool(true, "Use Valid Pullback Criteria", tooltip = "When
looking at the swing high that price must close above for a BOS/MSS, in order to
form a valid protected low, price must first close below the low of the candle that
made the swing high (and vice versa for protected highs)", group = g_PB)
extra_valid_pbs = input.bool(false, "Specific Pullback Candle Criteria", tooltip =
"When 'Use Valid Pullback Criteria' is enabled, if a given swing high is formed
with a down close candle, the script will look backward to find the most recent up-
close candle. Using this candle, price must close below its low to validate a
pullback from a swing high (and vice versa)", group = g_PB)

ph_color = input.color(#f23645, "", inline = "PHL", group = g_PHL)


pl_color = input.color(color.blue, "", inline = "PHL", group = g_PHL)

bull_color = input.color(color.teal, "", inline = "TREND", group = g_STR)


bear_color = input.color(#f23645, "", inline = "TREND", group = g_STR)

var g_RET = "Retracements"


show_rets = input.bool(false, "Show Retracements", tooltip = "Show retracements of
the previous zone with 30, 50, and 70% retracement levels", group = g_RET)
box_transp = input.int(85, "Box Transparency", 0, 100, tooltip = "Larger values
will make the retracement box more transparent", group = g_RET)
line_w = input.int(1, "Line Width", 0, 10, group = g_RET)
line_s = input.string('Dotted', "Line Style", options = ['Solid', 'Dashed',
'Dotted'], group = g_RET)

var style = switch line_s


'Solid' => line.style_solid
'Dashed' => line.style_dashed
'Dotted' => line.style_dotted

var bool bull = na

var float trail_price = na


var color trail_color = na

var ph = array.new_float()
var pl = array.new_float()

var pht = array.new_int()


var plt = array.new_int()

var float last_high = na


var float last_low = na

var int last_high_idx = na


var int last_low_idx = na

var float track_high = na


var float track_low = na

var int track_high_idx = na


var int track_low_idx = na

type pb
float price
int idx
bool valid = false
bool bull

type snd
box _box
line _30
line _50
line _70

type dwg
label[] _label
label[] _phl
line[] _line
bool[] _bull

method snd_add(snd s, float _high, float _low, bool bull) =>


_30 = (_high - _low) * 0.3 + _low
_50 = (_high - _low) * 0.5 + _low
_70 = (_high - _low) * 0.7 + _low
s._box := box.new(time, _high, time, _low, xloc = xloc.bar_time, border_color =
na, bgcolor = na)
s._30 := line.new(time, _30, time, _30, xloc = xloc.bar_time, color = na, style
= style, width = line_w)
s._50 := line.new(time, _50, time, _50, xloc = xloc.bar_time, color = na, style
= style, width = line_w)
s._70 := line.new(time, _70, time, _70, xloc = xloc.bar_time, color = na, style
= style, width = line_w)

method dwg_add(dwg d, label LB, label PHL, line LN, bool BL) =>
d._label.unshift(LB)
d._phl.unshift(PHL)
d._line.unshift(LN)
d._bull.unshift(BL)

method pb_set(pb p, float P, int I) =>


p.price := P
p.idx := I
p.valid := false

clear_all() =>
pl.clear()
plt.clear()
ph.clear()
pht.clear()

var pb_from_high = pb.new(bull = true)


var pb_from_low = pb.new(bull = false)

if ta.pivotlow(low, ps, ps) and pl.size() == 0


pl.unshift(low[ps])
plt.unshift(time[ps])

if extra_valid_pbs
for i = 0 to 3
if close[ps + i] < open[ps + i]
pb_set(pb_from_low, high[ps + i], bar_index)
break
else
pb_set(pb_from_low, high[ps], bar_index)

if na(last_low)
last_low := low[ps]
last_low_idx := bar_index - ps
else
if low[ps] < last_low
last_low := low[ps]
last_low_idx := bar_index - ps
if ta.pivothigh(high, ps, ps) and ph.size() == 0
ph.unshift(high[ps])
pht.unshift(time[ps])

if extra_valid_pbs
for i = 0 to 3
if close[ps + i] > open[ps + i]
pb_set(pb_from_high, low[ps + i], bar_index)
break
else
pb_set(pb_from_high, low[ps], bar_index)

if na(last_high)
last_high := high[ps]
last_high_idx := bar_index - ps
else
if high[ps] > last_high
last_high := high[ps]
last_high_idx := bar_index - ps

check_pb(pb p) =>
if p.bull
if close < p.price and p.valid == false
p.valid := true
else
if close > p.price and p.valid == false
p.valid := true

check_pb(pb_from_high)
check_pb(pb_from_low)

if (high[ps] > track_high or na(track_high) or last_low_idx >= track_high_idx) and


not na(ta.pivothigh(high, ps, ps)) and (use_valid_pbs ? pb_from_low.valid == true :
true)
track_high := high[ps]
track_high_idx := bar_index - ps
if (low[ps] < track_low or na(track_low) or last_high_idx >= track_low_idx) and not
na(ta.pivotlow(low, ps, ps)) and (use_valid_pbs ? pb_from_high.valid == true :
true)
track_low := low[ps]
track_low_idx := bar_index - ps

bos_bear = false
bos_bull = false
mss_bear = false
mss_bull = false
change = false

var dwgs = dwg.new(array.new_label(), array.new_label(), array.new_line(),


array.new_bool())
var snd = snd.new()

maintain(snd s) =>
if not na(s._box)
s._box.set_right(time)
s._30.set_x2(time)
s._50.set_x2(time)
s._70.set_x2(time)

maintain(snd)

if ph.size() > 0
if close > ph.get(0)
label _label = na
label _phl = na

if show_labels
save = false
if label_type == 'MSS' and not bull
save := true
else if label_type == 'BOS' and bull
save := true
else if label_type == 'All'
save := true
if save
_label := label.new(math.floor(math.avg(time, pht.get(0))),
ph.get(0), bull ? "BOS" : "MSS", xloc = xloc.bar_time, style =
label.style_label_down, color = #ffffff00, textcolor = na)

if bull
bos_bull := true
else
mss_bull := true

if show_rets and (use_valid_pbs ? pb_from_high.valid == true : true)


snd.snd_add(ph.get(0), track_low, true)

_line = line.new(pht.get(0), ph.get(0), time, ph.get(0), color = na, xloc =


xloc.bar_time, style = line.style_dashed)
bull := true
change := true

clear_all()
if not na(track_low)
if show_phl
_phl := label.new(time[bar_index - track_low_idx], track_low, "▲",
xloc = xloc.bar_time, style = label.style_label_up, textcolor = na, color =
#ffffff00)

pl.unshift(track_low)
plt.unshift(time[bar_index - track_low_idx])
last_high := na

dwgs.dwg_add(_label, _phl, _line, bull)

if pl.size() > 0
if close < pl.get(0)
label _label = na
label _phl = na

if show_labels
save = false
if label_type == 'MSS' and bull
save := true
else if label_type == 'BOS' and not bull
save := true
else if label_type == 'All'
save := true
if save
_label := label.new(math.floor(math.avg(time, plt.get(0))),
pl.get(0), not bull ? "BOS" : "MSS", xloc = xloc.bar_time, style =
label.style_label_up, color = #ffffff00, textcolor = na)

if not bull
bos_bear := true
else
mss_bear := true

if show_rets and (use_valid_pbs ? pb_from_low.valid == true : true)


snd.snd_add(pl.get(0), track_high, false)

_line = line.new(plt.get(0), pl.get(0), time, pl.get(0), color = na, xloc =


xloc.bar_time, style = line.style_dashed)
bull := false
change := true

clear_all()

if not na(track_high)
if show_phl
_phl := label.new(time[bar_index - track_high_idx], track_high,
"▼", xloc = xloc.bar_time, style = label.style_label_down, textcolor = na, color =
#ffffff00)

ph.unshift(track_high)
pht.unshift(time[bar_index - track_high_idx])
last_low := na

dwgs.dwg_add(_label, _phl, _line, bull)

if change[1]
if bos_bear[1] or mss_bear[1]
trail_price := track_high
trail_color := ph_color
else if bos_bull[1] or mss_bull[1]
trail_price := track_low
trail_color := pl_color

_bull = dwgs._bull.get(0)
dwgs._label.get(0).set_textcolor(_bull ? bull_color : bear_color)
dwgs._phl.get(0).set_textcolor(_bull ? pl_color : ph_color)
dwgs._line.get(0).set_color(_bull ? bull_color : bear_color)

snd._box.set_bgcolor(color.new(bull ? bull_color : bear_color, box_transp))


snd._30.set_color(_bull ? bull_color : bear_color)
snd._50.set_color(_bull ? bull_color : bear_color)
snd._70.set_color(_bull ? bull_color : bear_color)

barcolor(color_trend ? (bull ? bull_color : bear_color) : na)

plot(trail_phl ? trail_price : na, color = trail_color, linewidth = trail_width)

alertcondition(bos_bear[1] or bos_bull[1], "BOS Any")


alertcondition(mss_bear[1] or mss_bull[1], "MSS Any")

alertcondition(bos_bear[1], "BOS Bear")


alertcondition(bos_bull[1], "BOS Bull")

alertcondition(mss_bear[1], "MSS Bear")


alertcondition(mss_bull[1], "MSS Bull")

//@version=5

//indicator("Hourly Trading System (Zeiierman)", overlay=true, max_lines_count=100,


max_bars_back = 200, max_labels_count=100)

// ~~ Tooltips {

var t1 = "Sets the color for the 1-Hour Open line. Changing the color helps
distinguish it from other lines on the chart.

\n\nChoose between displaying the 1-Hour Open as a Line or a Zone. A zone shows an
area around the open price, providing a visual representation of a price range.

\n\nSets the line style for the 1-Hour Open (Solid, Dotted, Dashed). Different
styles can help visually differentiate the lines on your chart."

var t2 = "Sets the color for the 4-Hour Open line. Adjusting the color can help you
easily identify this line on your chart.

\n\nSets the line style for the 4-Hour Open (Solid, Dotted, Dashed). Different
styles can help visually differentiate the lines on your chart."

var t3 = "Specifies the width of the zone around the 1-Hour Open as a percentage.
Increasing this value widens the zone, showing a larger range around the open
price."
var t4 = "Enables or disables the display of retest markers. When enabled, markers
show where the price retested the 1-Hour Open line."

var t5 = "Sets the number of retests to display. Increasing this value shows more
retest markers on the chart."

var t6 = "Enables or disables the volume filter for retests. When enabled, only
retests with higher volume are displayed.

\n\nSets the length of the volume filter. Increasing this value smooths the volume
filter, potentially reducing the number of retest markers."

var t7 = "Enables or disables the 1-hour average line. This line shows the average
price over the past hour."

var t8 = "Enables or disables the display of hourly high and low labels. These
labels mark the highest and lowest prices within each hour."

var t9 = "Enables or disables the display of candlesticks on the chart.


Candlesticks provide a detailed view of price action.

\n\nEnables or disables bar coloring based on price direction. Up bars are colored
green and down bars are colored red."

var t10 = "Sets the timeframe for higher timeframe candles. Changing this value
adjusts the period over which higher timeframe candles are calculated."

var t11 = "Sets the number of higher timeframe candles to display. Increasing this
value shows more candles on the chart."

var t12 = "Sets the location for higher timeframe candles. Adjusting this value
moves the higher timeframe candles left or right on the chart."

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Settings {

H_col = input.color(color.rgb(105, 255, 190), title="1-Hour Open",


group="Levels", inline="1")

H_line_box = input.string("Zone", title="", options=["Line", "Zone"],


group="Levels", inline="1")

H_style = input.string("Solid", title="", options=["Solid", "Dotted", "Dashed"],


group="Levels", inline="1")

H_width = input.int(1, "", 1, 4, group="Levels", inline="1", tooltip=t1)

H4_col = input.color(color.rgb(105, 255, 190), "4-Hour Open", group="Levels",


inline="4")

H4_style = input.string("Dashed", title="", options=["Solid", "Dotted",


"Dashed"], group="Levels", inline="4", tooltip = t2)

H4_width = input.int(1, "", 1, 4, group="Levels", inline="4")

zoneDev = input.float(1,"Zone width",minval=0,step=.1, group="Levels",


inline="", tooltip = t3)/10000

hour_test = input.bool(false,title="Show Retests", group="Retest", inline="",


tooltip = t4)

retests = input.int(2, minval=1,maxval =100, title="Nbr of Retest",


group="Retest", inline="", tooltip = t5)

vol = input.bool(false, title="Volume Filter", group="Retest",


inline="Filter")

volLen = input.int(20, minval=1, title=" ", group="Retest", inline="Filter",


tooltip = t6)

re_up = input.color(color.lime, title="",group="Retest", inline="Retest")

re_dn = input.color(color.red, title="",group="Retest", inline="Retest")

average = input.bool(true, title="1 hour average", group="Average", inline="ma",


tooltip = t7)

hourly_hl= input.bool(true,"Hourly High & Low Labels",group="Average", tooltip =


t8)

ma_up = input.color(color.lime, title="",group="Average", inline="Average")

ma_dn = input.color(color.red, title="",group="Average", inline="Average")

candle = input.bool(false, title="Candlesticks", group="BarColor", inline="bar")

bar = input.bool(false, title="BarColor", group="BarColor", inline="bar",


tooltip = t9)

c_up = input.color(color.lime, title="",group="BarColor", inline="barcolor")

c_dn = input.color(color.red, title="",group="BarColor", inline="barcolor")

tf = input.timeframe("60","Timeframe", group="Higher Timeframe Candles",


tooltip = t10)

numb = input.int(2,"Nbr of Candles",minval=0, maxval=20, group="Higher


Timeframe Candles", tooltip = t11)

dn_col = input.color(color.new(color.red,10), title="Dn", inline="Candles",


group="Higher Timeframe Candles")
dn_wick = input.color(color.new(color.red,0), title="Wick", inline="Candles",
group="Higher Timeframe Candles")

up_col = input.color(color.new(color.lime,10), title="Up",inline="Candles",


group="Higher Timeframe Candles")

up_wick = input.color(color.new(color.lime,0), title="Wick", inline="Candles",


group="Higher Timeframe Candles")

loc = input.int(2,"Location", group="Location Settings", tooltip = t12)

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Functions {

Style(styleInput) =>

switch styleInput

"Solid" => line.style_solid

"Dotted" => line.style_dotted

"Dashed" => line.style_dashed

Line(_time, _open, duration, color, style, width) =>

line.new(_time, _open, _time + duration, _open, xloc=xloc.bar_time,


color=color, style=style, width=width)

Line_Vert(start_time, color, style) =>

var line ver_line = na

ver_line := line.new(start_time, high, start_time, low, xloc=xloc.bar_time,


color=color, extend=extend.both, style=style)

line.delete(ver_line[1])

Label(end_time, y_, text_, color_, style_)=>

var label lab = na

lab := label.new(end_time, y_, xloc=xloc.bar_time, text=text_, textcolor =


color.white, color=color_, style = style_)

label.delete(lab[1])
Box(left,top,right,bot,width,col)=>box.new(left,top,right,bot,border_color=col,bord
er_style=Style(H_style),border_width=width,bgcolor=color.new(col,75),xloc=xloc.bar_
time)

bars_per_hour() =>

var int bars_per_hour = na

if (timeframe.isintraday)

if (timeframe.multiplier == 1)

bars_per_hour := 60

else if (timeframe.multiplier == 5)

bars_per_hour := 12

else if (timeframe.multiplier == 15)

bars_per_hour := 4

else

bars_per_hour := na

else

bars_per_hour := na

bars_per_hour

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Line Style {

H_StyleOption = Style(H_style)

H4_StyleOption = Style(H4_style)

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Arrays {

var line deletedLine = na

open_l = array.new_line()
start_points = array.new_float()

end_points = array.new_float()

retest_counts = array.new_int()

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Var {

var line1 = line(na)

var line2 = line(na)

var box1 = box(na)

var box2 = box(na)

var count = 0

var end = int(na)

var pos = false

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Time {

time_hour = hour(time)

time_4hour = (timeframe.isintraday and minute(time) == 0 and hour(time) % 4 == 0)

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Create 1 -Hour Open Line {

var start_point = close

var hourHigh = high

var hourLow = low

var hourHighi = 0

var hourLowi = 0

var hourHL = array.new<label>()


if time_hour != time_hour[1]

start_point := open

if H_line_box=="Line"

line2 := Line(time, open, 3600000, H_col, H_StyleOption, H_width)

else

box2 := Box(time,open*(1+zoneDev),time+3600000,open*(1-
zoneDev),H_width,H_col)

count := 0

end := time + 3600000

pos := true

//Line_Vert(end, color.white, line.style_dotted)

//Label(end, start_point[1],"1 Hour")

if hourly_hl

//Change the previous Labels

if hourHL.size()>0

for i=0 to hourHL.size()-1 by 2

hourHL.get(i+1).set_text("H["+str.tostring(i/2+2)+"]")

hourHL.get(i).set_text("L["+str.tostring(i/2+2)+"]")

//Save High & Low Labels

hourHL.unshift(label.new(hourHighi,hourHigh,"H[1]",xloc.bar_time,textcolor
= color.white, color=color.new(color.green,0),style=label.style_label_down))

hourHL.unshift(label.new(hourLowi,hourLow,"L[1]",xloc.bar_time,textcolor =
color.white, color=color.new(color.red,0), style=label.style_label_up))

//High & Low Reset

hourHigh := high

hourLow := low

//Current High & Low Labels

if hourly_hl
hourHigh := math.max(high,hourHigh)

hourLow := math.min(low,hourLow)

if hourHigh!=hourHigh[1]

Label(time,hourHigh,"High",color.green,label.style_label_down)

hourHighi := time

if hourLow!=hourLow[1]

Label(time,hourLow,"Low",color.red,label.style_label_up)

hourLowi := time

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Create 4-Hour Open Line {

if time_4hour

line1 := Line(time, open, 4 * 3600000, H4_col, H4_StyleOption, H4_width)

count := 0

end := time + 4 * 3600000

pos := true

//Line_Vert(end, color.red, line.style_dotted)

//Label(end, high, "4 Hour")

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Number of bars per hour for the current timeframe {

bars_hour = bars_per_hour()

// Calculate how many bars are left until the next hour

bars_left = 0

if not na(bars_hour)

bars_passed = 0
if timeframe.isintraday

bars_passed := minute / timeframe.multiplier

bars_left := bars_hour - bars_passed

t = ""

if not na(bars_left)

t := str.tostring(math.round(bars_left))

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Calculate session average {

var float[] ma = array.new_float(1, na)

var int[] lena = array.new_int(1, 0)

time_avg() =>

if (time_hour != time_hour[1])

ma.set(0, close)

lena.set(0, 1)

else

ma.set(0, nz(ma.get(0)) + close)

lena.set(0, lena.get(0) + 1)

ma.get(0) / lena.get(0)

ma_hour = average?time_avg():na

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Direction {

dir(start_)=>

var dir = 0

if (not na(start_))

dir := close >= start_ ? 1 : -1


//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Color the bars based on Dir {

col = dir(start_point)==1?c_up:c_dn

ma_col = dir(start_point)==1?ma_up:ma_dn

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Plots {

plot(ma_hour, color=time_hour==time_hour[2]?ma_col:na, linewidth=1, title="Hourly


Average Price")

plotcandle(candle?open:na,candle?high:na,candle?low:na,candle?close:na,
color=candle?col:na, bordercolor =candle?col:na, wickcolor=candle?col:na,
title="Candlesticks")

barcolor(bar?col:na, title="BarColor")

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Table {

var Table = table.new(position = position.top_right, columns = 2, rows = 4,


border_color = color.white, frame_color = color.white, bgcolor = color.blue,
border_width = 1)

// Hourly, 4-hour, and Daily Percentage Changes

var float hourly_change = na

var float four_hour_change = na

var float daily_change = na

// Retrieve the previous 1-hour, 4-hour, and daily close prices

float prev_hour_close = request.security(syminfo.tickerid, "60", close[1],


lookahead = barmerge.lookahead_on)
float prev_4hour_close = request.security(syminfo.tickerid, "240", close[1],
lookahead = barmerge.lookahead_on)

float prev_daily_close = request.security(syminfo.tickerid, "D", close[1],


lookahead = barmerge.lookahead_on)

if not na(prev_hour_close)

hourly_change := (close - prev_hour_close) / prev_hour_close * 100

if not na(prev_4hour_close)

four_hour_change := (close - prev_4hour_close) / prev_4hour_close * 100

if not na(prev_daily_close)

daily_change := (close - prev_daily_close) / prev_daily_close * 100

H1_color = hourly_change>0?color.lime:color.red

H4_color = four_hour_change>0?color.lime:color.red

D_color = daily_change>0?color.lime:color.red

// Table

if barstate.islast

table.cell(table_id = Table, column = 0, row = 0, text = "1 hour closes in:",


text_color = color.white)

table.cell(table_id = Table, column = 1, row = 0, text = t + " bars", bgcolor =


color.blue, text_color = color.white)

table.cell(table_id = Table, column = 0, row = 1, text = "1H Δ%:", text_color =


color.white)

table.cell(table_id = Table, column = 1, row = 1, text =


str.tostring(hourly_change, format.percent), bgcolor = H1_color, text_color =
color.white)

table.cell(table_id = Table, column = 0, row = 2, text = "4H Δ%:", text_color =


color.white)

table.cell(table_id = Table, column = 1, row = 2, text =


str.tostring(four_hour_change, format.percent), bgcolor = H4_color, text_color =
color.white)

table.cell(table_id = Table, column = 0, row = 3, text = "Daily Δ%:",


text_color = color.white)

table.cell(table_id = Table, column = 1, row = 3, text =


str.tostring(daily_change, format.percent), bgcolor = D_color, text_color =
color.white)

if (timeframe.in_seconds(timeframe.period) >= 15 * 60)

var error_table = table.new(position=position.top_center, columns=1, rows=1,


border_width=1, frame_width = 1, frame_color = color.maroon,border_color=color.red)

error_text = "Error: Timeframe is above 15 minutes. \n\n The system works in


the 1 - 5 min Timeframe"

table.cell(error_table, 0, 0, error_text, text_size=size.large,


bgcolor=color.red, text_color=color.white)

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ HFT Candle {

// ~~ HTF Error Message {

tfs = str.tonumber(tf)

if str.tostring(tf) == "1D"

tfs := 1440

error = str.tonumber(timeframe.period)>=tfs

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ UDT {

type HTF

array<box> candle

array<line> wickH

array<line> wickL

array<float> hl

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Variables {

b = bar_index

var candle1 =
HTF.new(array.new<box>(numb),array.new<line>(numb),array.new<line>(numb),array.new<
float>(numb*2))

[o,h,l,c] = request.security(syminfo.tickerid,tf,
[open,high,low,close],lookahead=barmerge.lookahead_on)

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Code {

if numb>0

if o!=o[1] //New candle declaration

candle1.candle.shift().delete()

candle1.wickH.shift().delete()

candle1.wickL.shift().delete()

candle1.hl.shift()

candle1.hl.shift()

candle1.candle.push(box.new(b+numb*4+loc,math.max(o,c),b+numb*4+loc+2,math.min(o,c)
,color(na),bgcolor=o>c?dn_col:up_col))

candle1.wickH.push(line.new(b+numb*4+loc+1,math.max(o,c),b+numb*4+loc+1,h,color=o>c
?dn_col:up_col))

candle1.wickL.push(line.new(b+numb*4+loc+1,math.min(o,c),b+numb*4+loc+1,l,color=o>c
?dn_col:up_col))

candle1.hl.push(h)

candle1.hl.push(l)

else // Relocate previous & current candles

d = loc

for [i,x] in candle1.candle


if i<numb-1

x.set_left(b+d*2)

x.set_right(b+d*2+2)

candle1.wickH.get(i).set_x1(b+d*2+1)

candle1.wickH.get(i).set_x2(b+d*2+1)

candle1.wickL.get(i).set_x1(b+d*2+1)

candle1.wickL.get(i).set_x2(b+d*2+1)

else

x.set_lefttop(b+d*2,math.max(o,c))

x.set_rightbottom(b+d*2+2,math.min(o,c))

x.set_bgcolor(o>c?dn_col:up_col)

candle1.wickH.get(i).set_xy1(b+d*2+1,math.max(o,c))

candle1.wickH.get(i).set_xy2(b+d*2+1,h)

candle1.wickH.get(i).set_color(o>c?dn_wick:up_wick)

candle1.wickL.get(i).set_xy1(b+d*2+1,math.min(o,c))

candle1.wickL.get(i).set_xy2(b+d*2+1,l)

candle1.wickL.get(i).set_color(o>c?dn_wick:up_wick)

candle1.hl.set(numb*2-2,h)

candle1.hl.set(numb*2-1,l)

d += 2

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Retest condition for 1-Hour Open Line {

linePrice1 = line2.get_y1()

var retest_count_1h = 0

repos_1 = false

reneg_1 = false
if pos and count > 1 and time <= end and retest_count_1h < retests and

(H4_style=="Line"?low[1] > linePrice1 and low <= linePrice1 and

close >= linePrice1 : low[1] > box2.get_top() and low <= box2.get_top()

and close >= box2.get_bottom())

repos_1 := true

pos := false

count := 0

retest_count_1h += 1

if pos and count > 1 and time <= end and retest_count_1h < retests and

(H4_style=="Line"?high[1] < linePrice1 and high >= linePrice1 and

close <= linePrice1 : high[1] < box2.get_bottom() and high >=


box2.get_bottom()

and close <= box2.get_top())

reneg_1 := true

pos := false

count := 0

retest_count_1h += 1

count += 1

if (count > 1)

pos := true

if (hour(time) != hour(time[1]))

retest_count_1h := 0

HourPosRetest = vol?hour_test and repos_1 and volume > ta.wma(volume,


volLen):hour_test and repos_1

HourNegRetest = vol?hour_test and reneg_1 and volume > ta.wma(volume,


volLen):hour_test and reneg_1

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// ~~ Plots {

plotshape(HourPosRetest ? low : na, color=HourPosRetest ? re_up : na,


location=location.belowbar, style=shape.triangleup, size=size.tiny)

plotshape(HourNegRetest ? high : na, color=HourNegRetest ? re_dn : na,


location=location.abovebar, style=shape.triangledown, size=size.tiny)

//
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

// 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')

showBear = input(true, 'Bearish Structures', inline = 'bear', group = 'Style')

bearCss = input.color(#f23645, '', inline = 'bear', group = 'Style')

showSupport = input(false, 'Support', inline = 's', group = 'Style')

supCss = input.color(#089981, '', inline = 's', group = 'Style')


showResistance = input(false, 'Resistance', inline = 'r', group = 'Style')

resCss = input.color(#f23645, '', inline = 'r', 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 = dh == -p and dh[p] == p and high[p] == ta.highest(length)

bearf = dl == p and dl[p] == -p and low[p] == ta.lowest(length)


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

if ta.crossover(close, upper.value) and not upper.iscrossed

line.new(upper.loc, upper.value, n, upper.value, color = showBull ? bullCss :


na)

ms_lbl := label.new(int(math.avg(n, upper.loc)), upper.value, os == -1 ?


'ChoCH' : 'BOS'

, color = color(na)

, textcolor = showBull ? bullCss : na

, style = label.style_label_down

, size = size.tiny)

//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

else if showSupport and not broken_sup

lower_lvl.set_x2(n)

if close < lower_lvl.get_y2()

broken_sup := true

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

//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

if ta.crossunder(close, lower.value) and not lower.iscrossed

line.new(lower.loc, lower.value, n, lower.value, color = showBear ? bearCss :


na)

label.new(int(math.avg(n, lower.loc)), lower.value, os == 1 ? 'ChoCH' : 'BOS'

, color = color(na)

, textcolor = showBear ? bearCss : na

, style = label.style_label_up

, size = size.tiny)

//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

else if showResistance and not broken_res


upper_lvl.set_x2(n)

if close > upper_lvl.get_y2()

broken_res := true

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

//Dashboard

//-----------------------------------------------------------------------------{

var table_position = dashLoc == 'Bottom Left' ? position.bottom_left

: dashLoc == 'Top Right' ? position.top_right

: position.bottom_right

var table_size = textSize == 'Tiny' ? size.tiny

: textSize == 'Small' ? size.small

: size.normal

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)

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

//@version=6
//indicator("FVG Breakout/Breakdown", overlay=true)

// Define NWOG logic (New Week Opening Gap)


fridayCloseTime = timestamp("2024-01-01 15:59 +0000") // Friday Close Time (3:59 PM
UTC)
mondayOpenTime = timestamp("2024-01-04 00:00 +0000") // Monday Open Time (12:00 AM
UTC)

var float fridayClose = na


var float mondayOpen = na

if (time == fridayCloseTime)
fridayClose := close
if (time == mondayOpenTime)
mondayOpen := open

// Calculate the NWOG gap (difference between Friday close and Monday open)
nwogGap = mondayOpen - fridayClose

// Plot the NWOG levels (Monday Open +/- NWOG Gap)


nwogHigh = mondayOpen + nwogGap
nwogLow = mondayOpen - nwogGap

plot(nwogHigh, color=color.green, linewidth=2, title="NWOG High")


plot(nwogLow, color=color.red, linewidth=2, title="NWOG Low")

// Define FVG logic (Fair Value Gap)


// Bullish FVG: low[1] > high[3] (gap up)
bullishFVG = low[1] > high[3]
// Bearish FVG: high[1] < low[3] (gap down)
bearishFVG = high[1] < low[3]

// Plot FVG Zones


plotshape(series=bullishFVG, location=location.belowbar, color=color.purple,
style=shape.labelup, title="Bullish FVG", text="")
plotshape(series=bearishFVG, location=location.abovebar, color=color.red,
style=shape.labeldown, title="Bearish FVG", text="")

// Define Fresh Move conditions


freshBreakout = close > nwogHigh and bullishFVG // Fresh buy signal when price
breaks above NWOG high and FVG
freshBreakdown = close < nwogLow and bearishFVG // Fresh sell signal when price
breaks below NWOG low and FVG

// Plot Buy/Sell signals based on Fresh Moves


plotshape(series=freshBreakout, location=location.belowbar, color=color.purple,
style=shape.labelup, title="Fresh Buy", text="BUY")
plotshape(series=freshBreakdown, location=location.abovebar, color=color.red,
style=shape.labeldown, title="Fresh Sell", text="SELL")

// Alerts for Fresh Buy/Sell signals


alertcondition(freshBreakout, title="Fresh Buy Signal", message="Fresh Buy signal
based on NWOG breakout and FVG!")
alertcondition(freshBreakdown, title="Fresh Sell Signal", message="Fresh Sell
signal based on NWOG breakdown and FVG!")

You might also like