Indicator · Pine Script v5 · On the chart

HSN Algo

by IAMATOMIC001

Calculates and plots Smart Money Concepts (SMC) features directly on the price chart, including supply and demand zones, internal and swing market structure breaks of structure, and order blocks.

View on GitHub

Repaints

GitHub stars3on the repository
Pine versionv5runs as is
Lines of code2,922
Settings40inputs
LicenceNone statedfile: MPL-2.0
Last update12 months ago31 Oct 2025

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

2,922 lines of Pine Script v5 from Indicators/HSN_ALGO[V9.5].pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

HSN_ALGO[V9.5].pine
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// Join our channel for more free tools: https://t.me/simpleforextools

//@version=5
// # ========================================================================= #
indicator(title = "HSN Algo  [V9.5]", shorttitle = "HSN Algo  [V9.5]", overlay = true, max_lines_count = 500, max_labels_count = 500, max_boxes_count = 500, max_bars_back = 500, max_polylines_count = 100)

// Supply & Demand
gr_sr = "Supply & Demand"
showsr = input(true, title="Show Supply & Demand", group = gr_sr)
swing_length = input.int(defval=8, title="Sensitivity", group = gr_sr)
box_width = input.float(defval=4, title="Zone Width", group = gr_sr)
box_extend_option = input.string("Right", title="Extend Box", options=["Right", "Both"], group = gr_sr) 
res = input.timeframe(title='Time Frame', defval='', group= gr_sr)
s1 = request.security(syminfo.tickerid, res, showsr, gaps=barmerge.gaps_on)
demand_color = input.color(#08998148, title = 'Supply & Demand Color', group = gr_sr ,inline = "1")
supply_color = input.color(#f2364648, title = '', group = gr_sr, inline = "1")


// # ========================================================================= #
//                                Supply & Demand
// # ========================================================================= #
history_of_demand_to_keep = 20
show_zigzag = false
show_price_action_labels = false
// Other initializations
avg_volume = ta.sma(volume, 20)
very_weak_multiplier = 0.5
weak_multiplier = 1
strong_multiplier = 1.5

// Rejection handling
var int[] demandRejections = array.new_int(history_of_demand_to_keep, 0)
var int[] supplyRejections = array.new_int(history_of_demand_to_keep, 0)
var int[] demandCreationBars = array.new_int(history_of_demand_to_keep, na)
var int[] supplyCreationBars = array.new_int(history_of_demand_to_keep, na)

var box[] current_demand_box = array.new_box(history_of_demand_to_keep, na)
var box[] current_supply_box = array.new_box(history_of_demand_to_keep, na)

f_check_demand_rejections() =>
    for i = 0 to history_of_demand_to_keep - 1
        if not na(array.get(demandCreationBars, i))
            if bar_index - array.get(demandCreationBars, i) > 15 and bar_index - array.get(demandCreationBars, i) % 15 == 0
                label.new(bar_index, high, "Checking demand rejection", color=color.red)
                dBox = array.get(current_demand_box, i)
                if (na(dBox))
                    continue
                withinBox = (high >= box.get_bottom(dBox) and high <= box.get_top(dBox)) or (close >= box.get_bottom(dBox) and close <= box.get_top(dBox))
                bearishCandlesCount = math.sum(close < open ? 1 : 0, 15)
                if withinBox and bearishCandlesCount >= 7
                    label.new(bar_index, low, "Bearish count > 7", color=color.blue)
                    array.set(demandRejections, i, array.get(demandRejections, i) + 1)

f_check_supply_rejections() =>
    for i = 0 to history_of_demand_to_keep - 1
        if not na(array.get(supplyCreationBars, i))
            if bar_index - array.get(supplyCreationBars, i) > 15 and bar_index - array.get(supplyCreationBars, i) % 15 == 0
                label.new(bar_index, low, "Checking supply rejection", color=color.red)
                sBox = array.get(current_supply_box, i)
                if (na(sBox))
                    continue
                withinBox = (low <= box.get_top(sBox) and low >= box.get_bottom(sBox)) or (close <= box.get_top(sBox) and close >= box.get_bottom(sBox))
                bullishCandlesCount = math.sum(close > open ? 1 : 0, 15)
                if withinBox and bullishCandlesCount >= 7
                    label.new(bar_index, high, "Bullish count > 7", color=color.blue)
                    array.set(supplyRejections, i, array.get(supplyRejections, i) + 1)

f_array_add_pop(array, new_value_to_add) =>
    array.unshift(array, new_value_to_add)
    array.pop(array)

f_sh_sl_labels(array, swing_type) =>
    var string label_text = na
    if swing_type == 1
        if array.get(array, 0) >= array.get(array, 1)
            label_text := 'HH'
        else
            label_text := 'LH'
        label.new(bar_index - swing_length, array.get(array,0), text = label_text, style=label.style_label_down, textcolor = color.white, color = color.new(color.white, 100), size = size.tiny)
    else if swing_type == -1
        if array.get(array, 0) >= array.get(array, 1)
            label_text := 'HL'
        else
            label_text := 'LL'
        label.new(bar_index - swing_length, array.get(array,0), text = label_text, style=label.style_label_up, textcolor = color.white, color = color.new(color.white, 100), size = size.tiny)

f_check_overlapping(new_poi, box_array, atr) =>
    atr_threshold = atr * 2
    okay_to_draw = true
    for i = 0 to array.size(box_array) - 1
        top = box.get_top(array.get(box_array, i))
        bottom = box.get_bottom(array.get(box_array, i))
        poi = (top + bottom) / 2
        upper_boundary = poi + atr_threshold
        lower_boundary = poi - atr_threshold
        if new_poi >= lower_boundary and new_poi <= upper_boundary
            okay_to_draw := false
            break
        else 
            okay_to_draw := true
    okay_to_draw

f_supply_demand(value_array, bn_array, box_array, label_array, box_type, atr) =>
    atr_buffer = atr * (box_width / 15)
    box_left = array.get(bn_array, 0)
    box_right = bar_index + 20
    var float box_top = 0.00
    var float box_bottom = 0.00
    var float poi = 0.00
    if box_type == 1
        box_top := array.get(value_array, 0)
        box_bottom := box_top - atr_buffer
        poi := (box_top + box_bottom) / 2
    else if box_type == -1
        box_bottom := array.get(value_array, 0)
        box_top := box_bottom + atr_buffer
        poi := (box_top + box_bottom) / 2
    okay_to_draw = f_check_overlapping(poi, box_array, atr)
    swing_volume = volume[swing_length]
    var string strength_text = ""
    
    highest_volume_last_20 = ta.highest(volume, 20)
    volume_percentage = math.round(swing_volume / highest_volume_last_20 * 100) 
    volume_percentage := math.min(volume_percentage, 100)  // Cap the volume percentage to 100

    var extend_option = extend.right
    if box_extend_option == "Right"
        extend_option := extend.right
    else if box_extend_option == "Both"
        extend_option := extend.both
    if box_type == 1 and okay_to_draw and s1
        box.delete( array.get(box_array, array.size(box_array) - 5) )
        f_array_add_pop(box_array, box.new( left = box_left, top = box_top, right = box_right, bottom = box_bottom, border_color = color.rgb(242,54,69,50), border_width=1,
             bgcolor = supply_color, extend = extend_option, text = strength_text, text_halign = text.align_center, text_valign = text.align_center, text_color = color.rgb(59, 59, 59), text_size = size.small, xloc = xloc.bar_index))
        box.delete( array.get(label_array, array.size(label_array) - 5) )
        f_array_add_pop(label_array, box.new( left = box_left, top = poi, right = box_right, bottom = poi, border_color = color.rgb(242,54,69,50), border_width=1, border_style=line.style_dotted,
             bgcolor = color.new(color.black,100), extend = extend_option,  text = 'Supply', text_halign = text.align_center, text_valign = text.align_center, text_color = color.rgb(59, 59, 59), text_size = size.small, xloc = xloc.bar_index))
    else if box_type == -1 and okay_to_draw and s1
        box.delete( array.get(box_array, array.size(box_array) - 5) )
        f_array_add_pop(box_array, box.new( left = box_left, top = box_top, right = box_right, bottom = box_bottom, border_color = color.rgb(0,188,212,50), border_width=1,
             bgcolor = demand_color, extend = extend_option,  text = strength_text, text_halign = text.align_center, text_valign = text.align_center, text_color = color.rgb(59, 59, 59), text_size = size.small, xloc = xloc.bar_index))
        box.delete( array.get(label_array, array.size(label_array) - 5) )
        f_array_add_pop(label_array, box.new( left = box_left, top = poi, right = box_right, bottom = poi, border_color = color.rgb(0,188,212,50), border_width=1, border_style=line.style_dotted,
             bgcolor = color.new(color.black,100), extend = extend_option,  text = 'Demand', text_halign = text.align_center, text_valign = text.align_center, text_color = color.rgb(59, 59, 59), text_size = size.small, xloc = xloc.bar_index))
f_sd_to_bos(box_array, bos_array, label_array, zone_type) =>
    if zone_type == 1
        for i = 0 to array.size(box_array) - 1
            level_to_break = box.get_top(array.get(box_array,i))
            if close >= level_to_break
                box.delete(array.get(box_array, i))
                box.delete(array.get(label_array, i))
    if zone_type == -1
        for i = 0 to array.size(box_array) - 1
            level_to_break = box.get_bottom(array.get(box_array,i))
            if close <= level_to_break
                box.delete(array.get(box_array, i))
                box.delete(array.get(label_array, i))

f_extend_box_endpoint(box_array) =>
    for i = 0 to array.size(box_array) - 1
        box.set_right(array.get(box_array, i), bar_index + 30) // Extend only 20 bars

atr567 = ta.atr(50)
swing_high = ta.pivothigh(high, swing_length, swing_length)
swing_low = ta.pivotlow(low, swing_length, swing_length)
var swing_high_values = array.new_float(5,0.00)
var swing_low_values = array.new_float(5,0.00)
var swing_high_bns = array.new_int(5,0)
var swing_low_bns = array.new_int(5,0)
var current_supply_poi = array.new_box(history_of_demand_to_keep, na)
var current_demand_poi = array.new_box(history_of_demand_to_keep, na)
var supply_bos = array.new_box(5, na)
var demand_bos = array.new_box(5, na)
if not na(swing_high)
    f_array_add_pop(swing_high_values, swing_high)
    f_array_add_pop(swing_high_bns, bar_index[swing_length])
    if show_price_action_labels
        f_sh_sl_labels(swing_high_values, 1)
    f_supply_demand(swing_high_values, swing_high_bns, current_supply_box, current_supply_poi, 1, atr567)
else if not na(swing_low)
    f_array_add_pop(swing_low_values, swing_low)
    f_array_add_pop(swing_low_bns, bar_index[swing_length])
    if show_price_action_labels
        f_sh_sl_labels(swing_low_values, -1)
    f_supply_demand(swing_low_values, swing_low_bns, current_demand_box, current_demand_poi, -1, atr567)
f_sd_to_bos(current_supply_box, supply_bos, current_supply_poi, 1)
f_sd_to_bos(current_demand_box, demand_bos, current_demand_poi, -1)
f_extend_box_endpoint(current_supply_box)
f_extend_box_endpoint(current_demand_box)

// Inside the main execution, after the box is drawn, check for rejections
if not na(swing_low)
    f_array_add_pop(swing_low_values, swing_low)
    f_array_add_pop(swing_low_bns, bar_index[swing_length])
    if show_price_action_labels
        f_sh_sl_labels(swing_low_values, -1)
    f_supply_demand(swing_low_values, swing_low_bns, current_demand_box, current_demand_poi, -1, atr567)
    f_check_demand_rejections()

if not na(swing_high)
    f_array_add_pop(swing_high_values, swing_high)
    f_array_add_pop(swing_high_bns, bar_index[swing_length])
    if show_price_action_labels
        f_sh_sl_labels(swing_high_values, 1)
    f_supply_demand(swing_high_values, swing_high_bns, current_supply_box, current_supply_poi, 1, atr567)
    f_check_supply_rejections()



//-----------------------------------------------------------------------------{
    //Boolean set
//-----------------------------------------------------------------------------{
s_BOS        = 0
s_CHoCH      = 1
i_BOS        = 2
i_CHoCH      = 3
i_pp_CHoCH   = 4
green_candle = 5
red_candle   = 6
s_CHoCHP     = 7
i_CHoCHP     = 8

boolean =
 array.from(
   false
 , false 
 , false 
 , false 
 , false 
 , false 
 , false 
 , false
 , false
 )


//-----------------------------------------------------------------------------{
    // User inputs
//-----------------------------------------------------------------------------{

show_swing_ms                   = input.string      ("All"                            , "Swing        "               , inline = "1", group = "MARKET STRUCTURE"            , options = ["All", "CHoCH", "CHoCH+", "BOS", "None"])
show_internal_ms                = input.string      ("None"                            , "Internal     "               , inline = "2", group = "MARKET STRUCTURE"            , options = ["All", "CHoCH", "CHoCH+", "BOS", "None"])
internal_r_lookback             = input.int         (5                                , ""                            , inline = "2", group = "MARKET STRUCTURE"            , minval = 2)
swing_r_lookback                = input.int         (50                               , ""                            , inline = "1", group = "MARKET STRUCTURE"            , minval = 2)
ms_mode                         = input.string      ("Manual"                         , "Market Structure Mode"       , inline = "a", group = "MARKET STRUCTURE"            , tooltip = "[Manual] Use selected lenght\n[Dynamic] Use automatic lenght" ,options = ["Manual", "Dynamic"])
i_ms_up_BOS                   = input.color       (#089981                          , ""                            , inline = "2", group = "MARKET STRUCTURE")
i_ms_dn_BOS                   = input.color       (#f23645                          , ""                            , inline = "2", group = "MARKET STRUCTURE")
s_ms_up_BOS                   = input.color       (#089981                          , ""                            , inline = "1", group = "MARKET STRUCTURE")
s_ms_dn_BOS                   = input.color       (#f23645                          , ""                            , inline = "1", group = "MARKET STRUCTURE")
ob_show                         = input.bool        (true                             , "Show Last    "               , inline = "1", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "Display volumetric order blocks on the chart \n\n[Input] Ammount of volumetric order blocks to show")
ob_num                          = input.int         (5                                , ""                            , inline = "1", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "Orderblocks number", minval = 1, maxval = 10)
ob_metrics_show                 = input.bool        (true                             , "Internal Buy/Sell Activity"  , inline = "2", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "Display volume metrics that have formed the orderblock")
css_metric_up                   = input.color       (color.new(#047c32, 50)        , "         "                   , inline = "2", group = "VOLUMETRIC ORDER BLOCKS")
css_metric_dn                   = input.color       (color.new(#cf041b, 50)        , ""                            , inline = "2", group = "VOLUMETRIC ORDER BLOCKS")
ob_swings                       = input.bool        (false                            , "Swing Order Blocks"          , inline = "a", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "Display swing volumetric order blocks")
css_swing_up                    = input.color       (color.new(color.gray  , 90)    , "                 "           , inline = "a", group = "VOLUMETRIC ORDER BLOCKS")
css_swing_dn                    = input.color       (color.new(color.silver, 90)    , ""                            , inline = "a", group = "VOLUMETRIC ORDER BLOCKS")
ob_filter                       = input.string      ("None"                           , "Filtering             "      , inline = "d", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "Filter out volumetric order blocks by BOS/CHoCH/CHoCH+", options = ["None", "BOS", "CHoCH", "CHoCH+"])
ob_mitigation                   = input.string      ("Absolute"                       , "Mitigation           "       , inline = "4", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "Trigger to remove volumetric order blocks", options = ["Absolute", "Middle"])
ob_pos                          = input.string      ("Precise"                        , "Positioning          "       , inline = "k", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "Position of the Order Block\n[Full] Cover the whole candle\n[Middle] Cover half candle\n[Accurate] Adjust to volatility\n[Precise] Same as Accurate but more precise", options = ["Full", "Middle", "Accurate", "Precise"])
use_grayscale                   = input.bool        (true                            , "Grayscale"                   , inline = "6", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "Use gray as basic order blocks color")
use_show_metric                 = input.bool        (true                             , "Show Metrics"                , inline = "7", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "Show volume associated with the orderblock and his relevance")
use_middle_line                 = input.bool        (false                             , "Show Middle-Line"            , inline = "8", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "Show mid-line order blocks")
use_overlap                     = input.bool        (true                             , "Hide Overlap"                , inline = "9", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "Hide overlapping order blocks")
use_overlap_method              = input.string      ("Previous"                       , "Overlap Method    "          , inline = "Z", group = "VOLUMETRIC ORDER BLOCKS"         , tooltip = "[Recent] Preserve the most recent volumetric order blocks\n\n[Previous] Preserve the previous volumetric order blocks", options = ["Recent", "Previous"])
ob_bull_css                     = input.color       (color.new(#089981 ,  90)       , ""                            , inline = "1", group = "VOLUMETRIC ORDER BLOCKS")
ob_bear_css                     = input.color       (color.new(#f23645 ,  90)       , ""                            , inline = "1", group = "VOLUMETRIC ORDER BLOCKS")


show_lbl                        = input.bool        (false                            , "Show swing point"            , inline = "1", group = "High and Low"                    , tooltip = "Display swing point")
show_mtb                        = input.bool        (false                            , "Show High/Low/Equilibrium"   , inline = "2", group = "High and Low"                    , tooltip = "Display Strong/Weak High And Low and Equilibrium")
toplvl                          = input.color       (color.red                      , "Premium Zone   "             , inline = "3", group = "High and Low")
midlvl                          = input.color       (color.white                    , "Equilibrium Zone"            , inline = "4", group = "High and Low")
btmlvl                          = input.color       (#089981                        , "Discount Zone    "           , inline = "5", group = "High and Low")

t                               = color.t           (ob_bull_css)
invcol                          = color.new         (color.white                    , 100)
obtxt                           = input.string("Small"            , "Metric Size"                    , ["Tiny", "Small", "Normal", "Large", "Huge"], inline = "7", group = "VOLUMETRIC ORDER BLOCKS" )



method txSz(string s) =>
    out = switch s
        "Tiny"   => size.tiny
        "Small"  => size.small
        "Normal" => size.normal
        "Large"  => size.large
        "Huge"   => size.huge
    out


type bar
    float   o = open
    float   c = close
    float   h = high
    float   l = low
    float   v = volume
    int     n = bar_index
    int     t = time

type Zphl
    line   top
    line   bottom
    label  top_label
    label  bottom_label
    bool   stopcross
    bool   sbottomcross
    bool   itopcross
    bool   ibottomcross
    string txtup
    string txtdn
    float  topy
    float  bottomy
    float  topx
    float  bottomx
    float  tup
    float  tdn
    int    tupx
    int    tdnx
    float  itopy
    float  itopx
    float  ibottomy
    float  ibottomx
    float  uV
    float  dV

type FVG
    box [] box
    line[] ln
    bool   bull
    float  top
    float  btm
    int    left
    int    right

type ms
    float[] p
    int  [] n
    float[] l

type msDraw
    int    n
    float  p
    color  css
    string txt
    bool   bull

type obC 
    float[] top
    float[] btm
    int  [] left
    float[] avg
    float[] dV 
    float[] cV 
    int  [] wM 
    int  [] blVP 
    int  [] brVP 
    int  [] dir  
    float[] h
    float[] l
    int  [] n

type obD 
    box [] ob 
    box [] eOB
    box [] blB 
    box [] brB 
    line[] mL

type zone
    chart.point points
    float p
    int   c
    int   t

type hqlzone
    box   pbx
    box   ebx
    box   lbx
    label plb
    label elb
    label lbl

type ehl
    float pt
    int   t
    float pb
    int   b

type pattern
    string found = "None"
    bool isfound = false
    int   period = 0
    bool  bull   = false

type alerts
    bool chochswing     = false
    bool chochplusswing = false
    bool swingbos       = false
    bool chochplus      = false
    bool choch          = false
    bool bos            = false
    bool equal          = false
    bool ob             = false
    bool swingob        = false
    bool zone           = false
    bool fvg            = false
    bool obtouch        = false


bar         b      = bar.new()
var pattern p      = pattern.new()

alerts      blalert = alerts.new()
alerts      bralert = alerts.new()

if p.isfound

    p.period += 1

if p.period == 50

    p.period  := 0
    p.found   := "None"
    p.isfound := false
    p.bull    := na

switch

    b.c > b.o => boolean.set(green_candle, true)
    b.c < b.o => boolean.set(red_candle  , true)

f_zscore(src, lookback) =>

    (src - ta.sma(src, lookback)) / ta.stdev(src, lookback)

var int iLen = internal_r_lookback
var int sLen = swing_r_lookback

vv = f_zscore(((close - close[iLen]) / close[iLen]) * 100,iLen)

if ms_mode == "Dynamic"

    switch

        vv >= 1.5 or vv <= -1.5 => iLen := 10
        vv >= 1.6 or vv <= -1.6 => iLen := 9
        vv >= 1.7 or vv <= -1.7 => iLen := 8
        vv >= 1.8 or vv <= -1.8 => iLen := 7
        vv >= 1.9 or vv <= -1.9 => iLen := 6
        vv >= 2.0 or vv <= -2.0 => iLen := 5
        =>                         iLen

var msline = array.new<line>(0)

iH = ta.pivothigh(high, iLen, iLen)
sH = ta.pivothigh(high, sLen, sLen)
iL = ta.pivotlow (low , iLen, iLen)
sL = ta.pivotlow (low , sLen, sLen)

hl  () => [high, low]

[pdh, pdl] = request.security(syminfo.tickerid , 'D'  , hl() , lookahead = barmerge.lookahead_on)
[pwh, pwl] = request.security(syminfo.tickerid , 'W'  , hl() , lookahead = barmerge.lookahead_on)
[pmh, pml] = request.security(syminfo.tickerid , 'M'  , hl() , lookahead = barmerge.lookahead_on)
[pyh, pyl] = request.security(syminfo.tickerid , '12M', hl() , lookahead = barmerge.lookahead_on)

lstyle(style) =>

    out = switch style

        '⎯⎯⎯'  => line.style_solid
        '----' => line.style_dashed
        '····' => line.style_dotted

mtfphl(h, l ,tf ,css, pdhl_style) =>

    var line hl = line.new(
       na
     , na
     , na
     , na
     , xloc      = xloc.bar_time
     , color     = css
     , style     = lstyle(pdhl_style)
     )

    var line ll   = line.new(
       na
     , na
     , na
     , na
     , xloc      = xloc.bar_time
     , color     = css
     , style     = lstyle(pdhl_style)
     )

    var label lbl = label.new(
       na
     , na
     , xloc      = xloc.bar_time
     , text      = str.format('P{0}L', tf)
     , color     = invcol
     , textcolor = css
     , size      = size.small
     , style     = label.style_label_left
     )

    var label hlb = label.new(
       na
     , na
     , xloc      = xloc.bar_time
     , text      = str.format('P{0}H', tf)
     , color     = invcol
     , textcolor = css
     , size      = size.small
     , style     = label.style_label_left
     )

    hy = ta.valuewhen(h != h[1] , h    , 1)
    hx = ta.valuewhen(h == high , time , 1)
    ly = ta.valuewhen(l != l[1] , l    , 1)
    lx = ta.valuewhen(l == low  , time , 1)

    if barstate.islast

        extension = time + (time - time[1]) * 50
    
        line.set_xy1(hl , hx        , hy)
        line.set_xy2(hl , extension , hy)
        label.set_xy(hlb, extension , hy)
        line.set_xy1(ll , lx        , ly)
        line.set_xy2(ll , extension , ly)
        label.set_xy(lbl, extension , ly)


//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{ - End                                                                                                                                        }
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}



//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{ - Market Structure                                                                                                                           }
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}

method darkcss(color css, float factor, bool bull) =>

    blue  = color.b(css) * (1 - factor)
    red   = color.r(css) * (1 - factor)
    green = color.g(css) * (1 - factor)

    color.rgb(red, green, blue, 0)

method f_line(msDraw d, size, style) =>

    var line  id  = na
    var label lbl = na

    id := line.new(
       d.n
     , d.p
     , b.n
     , d.p
     , color = d.css
     , width = 1
     , style = style
     )

    if msline.size() >= 250

        line.delete(msline.shift())

    msline.push(id)

    lbl := label.new(
       int(math.avg(d.n, b.n))
     , d.p
     , d.txt
     , color            = invcol
     , textcolor        = d.css
     , style            = d.bull ? label.style_label_down : label.style_label_up
     , size             = size
     )

structure(bool mtf) =>

    msDraw drw     = na

    bool isdrw     = false
    bool isdrwS   = false

    var color css  = na
    var color icss = na

    var int itrend = 0
    var int  trend = 0

    bool bull_ob   = false
    bool bear_ob   = false

    bool s_bull_ob = false
    bool s_bear_ob = false

    n = bar_index
    
    var ms up = ms.new(
           array.new<float>()
         , array.new< int >()
         , array.new<float>()
         )

    var ms dn = ms.new(
           array.new<float>()
         , array.new< int >()
         , array.new<float>()
         )

    var ms sup = ms.new(
           array.new<float>()
         , array.new< int >()
         , array.new<float>()
         )

    var ms sdn = ms.new(
           array.new<float>()
         , array.new< int >()
         , array.new<float>()
         )

    switch show_swing_ms

        "All"      =>  boolean.set(s_BOS , true ),  boolean.set(s_CHoCH, true ) , boolean.set(s_CHoCHP, true  )  
        "CHoCH"    =>  boolean.set(s_BOS , false),  boolean.set(s_CHoCH, true ) , boolean.set(s_CHoCHP, false )   
        "CHoCH+"   =>  boolean.set(s_BOS , false),  boolean.set(s_CHoCH, false) , boolean.set(s_CHoCHP, true  )  
        "BOS"      =>  boolean.set(s_BOS , true ),  boolean.set(s_CHoCH, false) , boolean.set(s_CHoCHP, false )  
        "None"     =>  boolean.set(s_BOS , false),  boolean.set(s_CHoCH, false) , boolean.set(s_CHoCHP, false )  
        => na

    switch show_internal_ms

        "All"      =>  boolean.set(i_BOS, true ),  boolean.set(i_CHoCH, true  ),  boolean.set(i_CHoCHP, true )
        "CHoCH"    =>  boolean.set(i_BOS, false),  boolean.set(i_CHoCH, true  ),  boolean.set(i_CHoCHP, false) 
        "CHoCH+"   =>  boolean.set(i_BOS, false),  boolean.set(i_CHoCH, false ),  boolean.set(i_CHoCHP, true ) 
        "BOS"      =>  boolean.set(i_BOS, true ),  boolean.set(i_CHoCH, false ),  boolean.set(i_CHoCHP, false) 
        "None"     =>  boolean.set(i_BOS, false),  boolean.set(i_CHoCH, false ),  boolean.set(i_CHoCHP, false) 
        => na
        
    switch
        iH =>

            up.p.unshift(b.h[iLen])
            up.l.unshift(b.h[iLen])
            up.n.unshift(n  [iLen])

        iL =>

            dn.p.unshift(b.l[iLen])
            dn.l.unshift(b.l[iLen])
            dn.n.unshift(n  [iLen])

        sL =>

            sdn.p.unshift(b.l[sLen])
            sdn.l.unshift(b.l[sLen])
            sdn.n.unshift(n  [sLen])

        sH =>

            sup.p.unshift(b.h[sLen])
            sup.l.unshift(b.h[sLen])
            sup.n.unshift(n  [sLen])

    // INTERNAL BULLISH STRUCTURE
    if up.p.size() > 0 and dn.l.size() > 1

        if ta.crossover(b.c, up.p.first())

            bool CHoCH = na
            string txt = na

            if itrend < 0

                CHoCH := true

            switch

                not CHoCH =>

                    txt := "BOS"
                    css := i_ms_up_BOS

                    blalert.bos := true

                    if boolean.get(i_BOS) and mtf == false and na(drw)

                        isdrw := true
                        drw := msDraw.new(
                               up.n.first()
                             , up.p.first()
                             , i_ms_up_BOS
                             , txt
                             , true
                             )    

                CHoCH => 

                    dn.l.first() > dn.l.get(1) ? blalert.chochplus : blalert.choch

                    txt := dn.l.first() > dn.l.get(1) ? "CHoCH+" : "CHoCH"
                    css := i_ms_up_BOS.darkcss(0.25, true)

                    if (dn.l.first() > dn.l.get(1) ? boolean.get(i_CHoCHP) : boolean.get(i_CHoCH)) and mtf == false and na(drw)

                        isdrw := true
                        drw := msDraw.new(
                               up.n.first()
                             , up.p.first()
                             , i_ms_up_BOS.darkcss(0.25, true)
                             , txt
                             , true
                             )                

            if mtf == false

                switch

                    ob_filter == "None"                         => bull_ob := true
                    ob_filter == "BOS"    and txt == "BOS"      => bull_ob := true
                    ob_filter == "CHoCH"  and txt == "CHoCH"    => bull_ob := true
                    ob_filter == "CHoCH+" and txt == "CHoCH+"   => bull_ob := true

            itrend := 1
            up.n.clear()
            up.p.clear()

    // INTERNAL BEARISH STRUCTURE
    if dn.p.size() > 0 and up.l.size() > 1

        if ta.crossunder(b.c, dn.p.first())
            
            bool CHoCH = na
            string txt = na

            if itrend > 0

                CHoCH := true

            switch

                not CHoCH =>

                    bralert.bos := true

                    txt := "BOS"
                    css := i_ms_dn_BOS

                    if boolean.get(i_BOS) and mtf == false and na(drw)

                        isdrw := true
                        drw := msDraw.new(
                               dn.n.first()
                             , dn.p.first()
                             , i_ms_dn_BOS
                             , txt
                             , false
                             )    

                CHoCH => 

                    if up.l.first() < up.l.get(1)
                        bralert.chochplus := true
                    else 
                        bralert.choch := true

                    txt := up.l.first() < up.l.get(1) ? "CHoCH+" : "CHoCH"
                    css := i_ms_dn_BOS.darkcss(0.25, false)

                    if (up.l.first() < up.l.get(1) ? boolean.get(i_CHoCHP) : boolean.get(i_CHoCH)) and mtf == false and na(drw)

                        isdrw := true
                        drw := msDraw.new(
                               dn.n.first()
                             , dn.p.first()
                             , i_ms_dn_BOS.darkcss(0.25, false)
                             , txt
                             , false
                             )            

            if mtf == false

                switch

                    ob_filter == "None"                         => bear_ob := true
                    ob_filter == "BOS"    and txt == "BOS"      => bear_ob := true
                    ob_filter == "CHoCH"  and txt == "CHoCH"    => bear_ob := true
                    ob_filter == "CHoCH+" and txt == "CHoCH+"   => bear_ob := true

            itrend := -1
            dn.n.clear()
            dn.p.clear()

    // SWING BULLISH STRUCTURE
    if sup.p.size() > 0 and sdn.l.size() > 1

        if ta.crossover(b.c, sup.p.first())

            bool CHoCH = na
            string txt = na

            if trend < 0

                CHoCH := true

            switch

                not CHoCH =>

                    blalert.swingbos := true

                    txt := "BOS"
                    icss := s_ms_up_BOS

                    if boolean.get(s_BOS) and mtf == false and na(drw)

                        isdrwS := true
                        drw := msDraw.new(
                               sup.n.first()
                             , sup.p.first()
                             , s_ms_up_BOS
                             , txt
                             , true
                             )    

                CHoCH => 

                    if sdn.l.first() > sdn.l.get(1)
                        blalert.chochplusswing := true
                    else 
                        blalert.chochswing := true

                    txt := sdn.l.first() > sdn.l.get(1) ? "CHoCH+" : "CHoCH"
                    icss := s_ms_up_BOS.darkcss(0.25, true)

                    if (sdn.l.first() > sdn.l.get(1) ? boolean.get(s_CHoCHP) : boolean.get(s_CHoCH)) and mtf == false and na(drw)

                        isdrwS := true
                        drw := msDraw.new(
                               sup.n.first()
                             , sup.p.first()
                             , s_ms_up_BOS.darkcss(0.25, true)
                             , txt
                             , true
                             )    

            if mtf == false

                switch
                
                    ob_filter == "None"                       => s_bull_ob := true
                    ob_filter == "BOS"    and txt == "BOS"    => s_bull_ob := true
                    ob_filter == "CHoCH"  and txt == "CHoCH"  => s_bull_ob := true
                    ob_filter == "CHoCH+" and txt == "CHoCH+" => s_bull_ob := true

            trend := 1
            sup.n.clear()
            sup.p.clear()

    // SWING BEARISH STRUCTURE
    if sdn.p.size() > 0 and sup.l.size() > 1

        if ta.crossunder(b.c, sdn.p.first())

            bool CHoCH = na
            string txt = na

            if trend > 0

                CHoCH := true

            switch

                not CHoCH =>

                    bralert.swingbos := true

                    txt := "BOS"
                    icss := s_ms_dn_BOS

                    if boolean.get(s_BOS) and mtf == false and na(drw)

                        isdrwS := true
                        drw := msDraw.new(
                               sdn.n.first()
                             , sdn.p.first()
                             , s_ms_dn_BOS
                             , txt
                             , false
                             )    

                CHoCH => 

                    if sup.l.first() < sup.l.get(1)
                        bralert.chochplusswing := true
                    else
                        bralert.chochswing := true

                    txt := sup.l.first() < sup.l.get(1) ? "CHoCH+" : "CHoCH"
                    icss := s_ms_dn_BOS.darkcss(0.25, false)

                    if (sup.l.first() < sup.l.get(1) ? boolean.get(s_CHoCHP) : boolean.get(s_CHoCH)) and mtf == false and na(drw)

                        isdrwS := true
                        drw := msDraw.new(
                               sdn.n.first()
                             , sdn.p.first()
                             , s_ms_dn_BOS.darkcss(0.25, false)
                             , txt
                             , false
                             )        

            if mtf == false

                switch

                    ob_filter == "None"                        => s_bear_ob := true
                    ob_filter == "BOS"     and txt == "BOS"    => s_bear_ob := true
                    ob_filter == "CHoCH"   and txt == "CHoCH"  => s_bear_ob := true
                    ob_filter == "CHoCH+"  and txt == "CHoCH+" => s_bear_ob := true

            trend := -1
            sdn.n.clear()
            sdn.p.clear()

    [css, bear_ob, bull_ob, itrend, drw, isdrw, s_bear_ob, s_bull_ob, trend, icss, isdrwS]


[css, bear_ob, bull_ob, itrend, drw, isdrw, s_bear_ob, s_bull_ob, trend, icss, isdrwS] = structure(false)

if isdrw
    f_line(drw, size.small, line.style_dashed)

if isdrwS
    f_line(drw, size.small, line.style_solid)

[_, _, _, itrend5, _, _, _, _, _, _, _]  = request.security("", "5"      , structure(true))
[_, _, _, itrend15, _, _, _, _, _, _, _] = request.security("", "15"     , structure(true))
[_, _, _, itrend30, _, _, _, _, _, _, _] = request.security("", "30"     , structure(true))
[_, _, _, itrend1H, _, _, _, _, _, _, _] = request.security("", "60"     , structure(true))
[_, _, _, itrend4H, _, _, _, _, _, _, _] = request.security("", "240"    , structure(true))
[_, _, _, itrend1D, _, _, _, _, _, _, _] = request.security("", "1440"   , structure(true))
[_, _, _, itrend1W, _, _, _, _, _, _, _] = request.security("", "1W"     , structure(true))



var phl = Zphl.new(
   na
 , na
 , label.new(na , na , color = invcol , textcolor = i_ms_dn_BOS , style = label.style_label_down , size = size.tiny , text = "")
 , label.new(na , na , color = invcol , textcolor = i_ms_up_BOS , style = label.style_label_up   , size = size.tiny , text = "")
 , true
 , true
 , true
 , true
 , ""
 , ""
 , 0
 , 0
 , 0
 , 0
 , high
 , low
 , 0
 , 0
 , 0
 , 0
 , 0
 , 0
 , na
 , na
 )

zhl(len)=>    

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

    var float out = 0
    out := b.h[len] > upper ? 0 : b.l[len] < lower ? 1 : out[1]

    top = out == 0 and out[1] != 0 ? b.h[len] : 0
    btm = out == 1 and out[1] != 1 ? b.l[len] : 0

    [top, btm]

[top , btm ] = zhl(sLen)
[itop, ibtm] = zhl(iLen)

upphl(trend) =>

    var label lbl = label.new(
       na
     , na
     , color     = invcol
     , textcolor = toplvl
     , style     = label.style_label_down
     , size      = size.small
     )

    if top

        phl.stopcross := true
        phl.txtup     := top > phl.topy ? "HH" : "HL"

        if show_lbl

            topl = label.new(
               b.n - swing_r_lookback
             , top
             , phl.txtup
             , color     = invcol
             , textcolor = toplvl
             , style     = label.style_label_down
             , size      = size.small
             )

        line.delete(phl.top[1])

        phl.top := line.new(
               b.n - sLen
             , top
             , b.n
             , top
             , color = toplvl)

        phl.topy      := top
        phl.topx      := b.n - sLen
        phl.tup       := top
        phl.tupx      := b.n - sLen

    if itop

        phl.itopcross := true
        phl.itopy     := itop
        phl.itopx     := b.n - iLen

    phl.tup           := math.max(high, phl.tup)
    phl.tupx          := phl.tup == high ? b.n : phl.tupx
    phl.uV            := phl.tup != phl.tup[1] ? b.v : phl.uV

    if barstate.islast 

        line.set_xy1(
               phl.top
             , phl.tupx
             , phl.tup
             )

        line.set_xy2(
               phl.top
             , b.n + 50
             , phl.tup
             )

        label.set_x(
               lbl
             , b.n + 50
             )

        label.set_y(
               lbl
             , phl.tup
             )

        dist = math.abs(phl.uV / (phl.uV + phl.dV)) * 100
        label.set_text (lbl, trend < 0 
             ? "Strong High | " + str.tostring(phl.uV, format.volume) + " (" + str.tostring(math.round(dist,0)) + "%)" 
             : "Weak High | "   + str.tostring(phl.uV, format.volume) + " (" + str.tostring(math.round(dist,0)) + "%)")

dnphl(trend) =>

    var label lbl = label.new(
       na
     , na
     , color     = invcol
     , textcolor = btmlvl
     , style     = label.style_label_up
     , size      = size.small
     )

    if btm

        phl.sbottomcross := true
        phl.txtdn        := btm > phl.bottomy ? "LH" : "LL"

        if show_lbl

            btml = label.new(
               b.n - swing_r_lookback
             , btm, phl.txtdn
             , color = invcol
             , textcolor = btmlvl
             , style = label.style_label_up
             , size = size.small
             )

        line.delete(phl.bottom[1])
        
        phl.bottom := line.new(
           b.n - sLen
         , btm
         , b.n
         , btm
         , color = btmlvl
         )

        phl.bottomy      := btm
        phl.bottomx      := b.n - sLen
        phl.tdn          := btm
        phl.tdnx         := b.n - sLen

    if ibtm

        phl.ibottomcross := true
        phl.ibottomy     := ibtm
        phl.ibottomx     := b.n - iLen

    phl.tdn              := math.min(low, phl.tdn)
    phl.tdnx             := phl.tdn == low ? b.n : phl.tdnx
    phl.dV               := phl.tdn != phl.tdn[1] ? b.v : phl.dV

    if barstate.islast

        line.set_xy1(
           phl.bottom
         , phl.tdnx
         , phl.tdn
         )

        line.set_xy2(
           phl.bottom
         , b.n + 50
         , phl.tdn
         )

        label.set_x(
           lbl
         , b.n + 50
         )

        label.set_y(
           lbl
         , phl.tdn
         )
         
        dist = math.abs(phl.dV / (phl.uV + phl.dV)) * 100
        label.set_text (lbl, trend > 0 
             ? "Strong Low | " + str.tostring(phl.dV, format.volume) + " (" + str.tostring(math.round(dist,0)) + "%)" 
             : "Weak Low | "   + str.tostring(phl.uV, format.volume) + " (" + str.tostring(math.round(dist,0)) + "%)")

midphl() =>

    avg = math.avg(phl.bottom.get_y2(), phl.top.get_y2())
    
    var line l = line.new(
       y1 = avg
     , y2 = avg
     , x1 = b.n - sLen
     , x2 = b.n + 50
     , color = midlvl
     , style = line.style_solid
     )

    var label lbl = label.new(
       x = b.n + 50
     , y = avg
     , text = "Equilibrium"
     , style = label.style_label_left
     , color = invcol
     , textcolor = midlvl
     , size = size.small
     )
     
    if barstate.islast

        more = (phl.bottom.get_x1() + phl.bottom.get_x2()) > (phl.top.get_x1() + phl.top.get_x2()) ? phl.top.get_x1() : phl.bottom.get_x1()
        line.set_xy1(l   , more    , avg)
        line.set_xy2(l   , b.n + 50, avg)
        label.set_x (lbl , b.n + 50     )
        label.set_y (lbl , avg          )
        dist = math.abs((l.get_y2() - close) / close) * 100
        label.set_text (lbl, "Equilibrium (" + str.tostring(math.round(dist,0)) + "%)")     
          
hqlzone() =>

    if barstate.islast

        var hqlzone dZone = hqlzone.new(
           box.new(
               na
             , na
             , na
             , na
             , bgcolor = color.new(toplvl, 70)
             , border_color = na
             )
         , box.new(
               na
             , na
             , na
             , na
             , bgcolor = color.new(midlvl, 70)
             , border_color = na
             )
         , box.new(
               na
             , na
             , na
             , na
             , bgcolor = color.new(btmlvl, 70)
             , border_color = na
             )

         , label.new(na, na, text = "Premium"    , color = invcol, textcolor = toplvl, style = label.style_label_down, size = size.small)
         , label.new(na, na, text = "Equilibrium", color = invcol, textcolor = midlvl, style = label.style_label_left, size = size.small)
         , label.new(na, na, text = "Discount"   , color = invcol, textcolor = btmlvl, style = label.style_label_up  , size = size.small)
         )

        dZone.pbx.set_lefttop(int(math.max(phl.topx, phl.bottomx))                          , phl.tup)
        dZone.pbx.set_rightbottom(b.n + 50                        , 0.95  * phl.tup + 0.05  * phl.tdn)

        dZone.ebx.set_lefttop(int(math.max(phl.topx, phl.bottomx)), 0.525 * phl.tup + 0.475 * phl.tdn)
        dZone.ebx.set_rightbottom(b.n + 50                        , 0.525 * phl.tdn + 0.475 * phl.tup)

        dZone.lbx.set_lefttop(int(math.max(phl.topx, phl.bottomx)), 0.95  * phl.tdn + 0.05  * phl.tup)
        dZone.lbx.set_rightbottom(b.n + 50                                                  , phl.tdn)

        dZone.plb.set_xy( int(math.avg(math.max(phl.topx, phl.bottomx), int(b.n + 50))) , phl.tup)
        dZone.elb.set_xy( int(b.n + 50)                                                 , math.avg(phl.tup, phl.tdn))
        dZone.lbl.set_xy( int(math.avg(math.max(phl.topx, phl.bottomx), int(b.n + 50))) , phl.tdn)

             

if show_mtb

    upphl (trend)
    dnphl (trend)
    hqlzone()

//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{ - End                                                                                                                                        }
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}




//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{ - Volumetric Order Block                                                                                                                     }
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//---------------------------------------------------------------------------------------------------------------------}
//UDT's
//---------------------------------------------------------------------------------------------------------------------{




method eB(box[] b, bool ext, color css, bool swing) =>
    b.unshift(
         box.new(
               na
             , na
             , na
             , na
             , xloc             = xloc.bar_time
             , extend           = ext ? extend.right : extend.none
             , border_color     = swing ? color.new(css, 0) : color.new(color.white,100)
             , bgcolor          = css
             , border_width     = 1
              )
             )

method eL(line[] l, bool ext, bool solid, color css) =>
    l.unshift(
         line.new(
               na
             , na
             , na
             , na
             , width  = 1
             , color  = css
             , xloc   = xloc.bar_time
             , extend = ext   ? extend.right     : extend.none
             , style  = solid ? line.style_solid : line.style_dashed
              )
             )

method drawVOB(bool cdn, bool bull, color css, int loc, bool swing) =>

    [cC, oO, hH, lL, vV] = request.security(
         syminfo.tickerid
         , ""

         ,   [

               close
             , open
             , high
             , low
             , volume

             ]

         , lookahead = barmerge.lookahead_off
                                           )
    var obC obj  = obC.new(
                   array.new<float>()
                 , array.new<float>()
                 , array.new< int >()
                 , array.new<float>()
                 , array.new<float>()
                 , array.new<float>()
                 , array.new< int >()
                 , array.new< int >()
                 , array.new< int >()
                 , array.new< int >()
                 , array.new<float>()
                 , array.new<float>()
                 , array.new< int >()
                 )

    var obD draw = obD.new(
                   array.new<box >()
                 , array.new<box >()
                 , array.new<box >()
                 , array.new<box >()
                 , array.new<line>()
                 )

    if barstate.isfirst

        for i = 0 to ob_num - 1

            draw.mL .eL(false, false, use_grayscale ? color.new(color.gray, 0) : color.new(css,0))
            draw.ob .eB(false, use_grayscale ? color.new(color.gray, 90) : css, swing)
            draw.blB.eB(false, css_metric_up                                  , swing)
            draw.brB.eB(false, css_metric_dn                                  , swing)
            draw.eOB.eB(true , use_grayscale ? color.new(color.gray, 90) : css, swing)

    float pos = ob_pos == "Full" 
         ? (bull ? high : low) 
         : ob_pos == "Middle" 
             ? ohlc4 
             : ob_pos == "Accurate" 
                 ? hl2 
                 : hl2

    if cdn

        obj.h.clear()
        obj.l.clear()
        obj.n.clear()

        for i = 1 to math.abs((loc - b.n)) - 1

            obj.h.push(hH[i])
            obj.l.push(lL[i])
            obj.n.push(b.t[i])

        // obj.h.reverse()
        // obj.l.reverse()

        int iU = obj.l.indexof(obj.l.min()) + 1
        int iD = obj.h.indexof(obj.h.max()) + 1

        obj.dir.unshift(
             bull 
                 ? (b.c[iU] > b.o[iU] ? 1 : -1) 
                 : (b.c[iD] > b.o[iD] ? 1 : -1)
             )

        obj.top.unshift(
             bull 
                 ? pos[iU] 
                 : obj.h.max()
             )

        obj.btm.unshift(
             bull 
                 ? obj.l.min() 
                 : pos[iD]
             )

        obj.left.unshift(
             bull 
                 ? obj.n.get(obj.l.indexof(obj.l.min())) 
                 : obj.n.get(obj.h.indexof(obj.h.max()))
             )

        obj.avg.unshift(
             math.avg(obj.top.first(), obj.btm.first())
             )

        obj.cV.unshift(
             bull 
                 ? b.v[iU] 
                 : b.v[iD]
             )

        if ob_pos == "Precise"

            switch bull
                true =>
                    if obj.avg.get(0) < (b.c[iU] < b.o[iU] ? b.c[iU] : b.o[iU]) and obj.top.get(0) > hlcc4[iU]
                        obj.top.set(0, obj.avg.get(0))
                        obj.avg.set(0, math.avg(obj.top.first(), obj.btm.first()))
                false =>
                    if obj.avg.get(0) > (b.c[iU] < b.o[iU] ? b.o[iD] : b.c[iD]) and obj.btm.get(0) < hlcc4[iD]
                        obj.btm.set(0, obj.avg.get(0))
                        obj.avg.set(0, math.avg(obj.top.first(), obj.btm.first()))

        obj.blVP.unshift ( 0 )
        obj.brVP.unshift ( 0 )
        obj.wM  .unshift ( 1 )

        if use_overlap

            int rmP = use_overlap_method == "Recent" ? 1 : 0

            if obj.avg.size() > 1

                if bull 

                     ? obj.btm.first() < obj.top.get(1) 
                     : obj.top.first() > obj.btm.get(1)
                    obj.wM   .remove(rmP)
                    obj.cV   .remove(rmP)
                    obj.dir  .remove(rmP)
                    obj.top  .remove(rmP)
                    obj.avg  .remove(rmP) 
                    obj.btm  .remove(rmP)
                    obj.left .remove(rmP)
                    obj.blVP .remove(rmP)
                    obj.brVP .remove(rmP)

    if barstate.isconfirmed

        for x = 0 to ob_num - 1

            tg = switch ob_mitigation
                "Middle"   => obj.avg
                "Absolute" => bull ? obj.btm : obj.top

            for [idx, pt] in tg

                if (bull ? cC < pt : cC > pt)
                    obj.wM   .remove(idx)
                    obj.cV   .remove(idx)
                    obj.dir  .remove(idx)
                    obj.top  .remove(idx)
                    obj.avg  .remove(idx) 
                    obj.btm  .remove(idx)
                    obj.left .remove(idx)
                    obj.blVP .remove(idx)
                    obj.brVP .remove(idx)
            
    
    if barstate.islast

        if obj.avg.size() > 0

            // Alert

            if bull 
                 ? ta.crossunder(low , obj.top.get(0)) 
                 : ta.crossover (high, obj.btm.get(0)) 
                switch bull 
                    true  => blalert.obtouch := true 
                    false => bralert.obtouch := true


            float tV = 0
            obj.dV.clear()
            seq = math.min(ob_num - 1, obj.avg.size() - 1)

            for j = 0 to seq

                tV += obj.cV.get(j)

                if j == seq

                    for y = 0 to seq

                        obj.dV.unshift(
                             math.floor(
                                 (obj.cV.get(y) / tV) * 100)
                         )

                obj.dV.reverse()

            for i = 0 to math.min(ob_num - 1, obj.avg.size() - 1)

                dmL   = draw.mL .get(i)
                dOB   = draw.ob .get(i)
                dblB  = draw.blB.get(i)
                dbrB  = draw.brB.get(i)
                deOB  = draw.eOB.get(i)

                dOB.set_lefttop     (obj.left .get(i)           , obj.top.get(i))
                deOB.set_lefttop    (b.t                        , obj.top.get(i))
                dOB.set_rightbottom (b.t                        , obj.btm.get(i))
                deOB.set_rightbottom(b.t + (b.t - b.t[1]) * 100 , obj.btm.get(i))

                if use_middle_line

                    dmL.set_xy1(obj.left.get(i), obj.avg.get(i))
                    dmL.set_xy2(b.t            , obj.avg.get(i))

                if ob_metrics_show

                    dblB.set_lefttop    (obj.left.get(i), obj.top.get(i))
                    dbrB.set_lefttop    (obj.left.get(i), obj.avg.get(i))
                    dblB.set_rightbottom(obj.left.get(i), obj.avg.get(i))
                    dbrB.set_rightbottom(obj.left.get(i), obj.btm.get(i))

                    rpBL = dblB.get_right()
                    rpBR = dbrB.get_right()
                    dbrB.set_right(rpBR + (b.t - b.t[1]) * obj.brVP.get(i))
                    dblB.set_right(rpBL + (b.t - b.t[1]) * obj.blVP.get(i))

                if use_show_metric

                    txt = switch

                        obj.cV.get(i) >= 1000000000 => str.tostring(math.round(obj.cV.get(i) / 1000000000,3)) + "B"
                        obj.cV.get(i) >= 1000000    => str.tostring(math.round(obj.cV.get(i) / 1000000,3))    + "M"
                        obj.cV.get(i) >= 1000       => str.tostring(math.round(obj.cV.get(i) / 1000,3))       + "K"
                        obj.cV.get(i) <  1000       => str.tostring(math.round(obj.cV.get(i)))

                    deOB.set_text(
                         str.tostring(
                         txt + " (" + str.tostring(obj.dV.get(i)) + "%)")
                         )

                    deOB.set_text_size (obtxt.txSz())
                    deOB.set_text_halign(text.align_left)
                    deOB.set_text_color (use_grayscale ? color.silver : color.new(css, 0))

    if ob_metrics_show and barstate.isconfirmed

        if obj.wM.size() > 0
            
            for i = 0 to obj.avg.size() - 1

                switch obj.dir.get(i)

                    1  =>

                        switch obj.wM.get(i)

                            1 => obj.blVP.set(i, obj.blVP.get(i) + 1), obj.wM.set(i, 2)
                            2 => obj.blVP.set(i, obj.blVP.get(i) + 1), obj.wM.set(i, 3)
                            3 => obj.brVP.set(i, obj.brVP.get(i) + 1), obj.wM.set(i, 1)
                    -1 =>

                        switch obj.wM.get(i)

                            1 => obj.brVP.set(i, obj.brVP.get(i) + 1), obj.wM.set(i, 2)
                            2 => obj.brVP.set(i, obj.brVP.get(i) + 1), obj.wM.set(i, 3)
                            3 => obj.blVP.set(i, obj.blVP.get(i) + 1), obj.wM.set(i, 1)

var hN = array.new<int>(1, b.n)
var lN = array.new<int>(1, b.n)
var hS = array.new<int>(1, b.n)
var lS = array.new<int>(1, b.n)

if iH

    hN.pop()
    hN.unshift(int(b.n[iLen]))

if iL

    lN.pop()
    lN.unshift(int(b.n[iLen]))

if sH

    hS.pop()
    hS.unshift(int(b.n[sLen]))

if sL

    lS.pop()
    lS.unshift(int(b.n[sLen]))

if ob_show

    bull_ob.drawVOB(true , ob_bull_css, hN.first(), false)
    bear_ob.drawVOB(false, ob_bear_css, lN.first(), false)


if ob_swings

    s_bull_ob.drawVOB(true , css_swing_up, hS.first(), true)
    s_bear_ob.drawVOB(false, css_swing_dn, lS.first(), true)

if bull_ob
    blalert.ob := true

if bear_ob
    bralert.ob := true

if s_bull_ob
    blalert.swingob := true

if s_bear_ob
    blalert.swingob := true

// Plotting buy and sell arrows for bull and bear order blocks 
plotshape(series=bull_ob and ob_show, style=shape.triangleup, location=location.belowbar,offset=-1, color=color.rgb(3, 63, 226), size=size.tiny,text = "Add", textcolor = color.rgb(3, 63, 226))
plotshape(series=bear_ob and ob_show, style=shape.triangledown, location=location.abovebar,offset=-1, color=color.rgb(156, 3, 3), size=size.tiny,text = "Add", textcolor = color.red)
plotshape(series=s_bull_ob and ob_swings, style=shape.triangleup, location=location.belowbar, offset=-1,color=color.rgb(3, 63, 226), size=size.tiny,text = "Add", textcolor = color.rgb(3, 63, 226))
plotshape(series=s_bear_ob and ob_swings, style=shape.triangledown, location=location.abovebar,offset=-1, color=color.rgb(156, 3, 3), size=size.tiny,text = "Add", textcolor = color.red)

//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{ - End                                                                                                                                        }
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}


//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{ - Master Pattern & Liquidity                                                                                                                      }
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}


Major_Box_Color = input.color(color.rgb(159, 159, 160, 69),"Major Box Color")
show_minor_boxes = input.bool(false,"Show Minor Boxes")
Minor_Box_Color = input.color(color.rgb(190, 186, 186, 64),"Minor Box Color")
Major_Expansion_Line_Color = input.color(color.rgb(116, 115, 115),"Major Expansion Line Color")
Major_Expansion_Line_Style = input.string("Solid","Major Expansion Line Style",["Solid","Dotted","Dashed"])
Major_Expansion_Line_Thickness = input.int(2,"Major Expansion Line Thickness")
show_minor_expansion = input.bool(true,"Show Minor Expansion Lines")
Minor_Expansion_Line_Color = input.color(color.rgb(145, 143, 144),"Minor Expansion Line Color")
Minor_Expansion_Line_Style = input.string("Dashed","Minor Expansion Line Style",["Solid","Dotted","Dashed"])
Minor_Expansion_Line_Thickness = input.int(1,"Minor Expansion Line Thickness")
Sell_Line_Color = input.color(color.red,"Sell Side Liquidity Line Color")
Sell_Line_Style = input.string("Dashed","Sell Side Liquidity Line Style",["Solid","Dotted","Dashed"])
Sell_Line_Thickness = input.int(1,"Sell Side Liquidity Line Thickness")
Buy_Line_Color = input.color(color.green,"Buy Side Liquidity Line Color")
Buy_Line_Style = input.string("Dashed","Buy Side Liquidity Line Style",["Solid","Dotted","Dashed"])
Buy_Line_Thickness = input.int(1,"Buy Side Liquidity Line Thickness")
max_bars = input.int(150,"Max Bars Back")
indi_type = input.int(1,"Type")
//n = input.int(title="Fractals Periods", defval=2, minval=2)
repaint = true


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

// upFractal = (upflagDownFrontier and flagUpFrontier)


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

// downFractal = (downflagDownFrontier and flagDownFrontier)

// 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 last_h = 1, last_h := last_h + 1
var last_l = 1, last_l := last_l + 1
var lw = 1, var hg = 1
lw := lw + 1, hg := hg + 1
p_lw = -ta.lowestbars(Depth), p_hg = -ta.highestbars(Depth)
lowing = lw == p_lw or low - low[p_lw] > Deviation*syminfo.mintick
highing = hg == p_hg or high[p_hg] - high > Deviation*syminfo.mintick
lh = ta.barssince(not highing[1]), ll = ta.barssince(not lowing[1])
downn = ta.barssince(not (lh > ll)) >= Backstep, lower = low[lw] > low[p_lw], higher = high[hg] < high[p_hg]
if lw != p_lw and (not downn[1] or lower)
    lw := p_lw < hg ? p_lw : 0
if hg != p_hg and (downn[1] or higher)
    hg := p_hg < lw ? p_hg : 0

var zz = array.new_float()
var yy = array.new_int()
x1 = downn ? lw : hg
y1 = downn ? low[lw] : high[hg]

if downn == downn[1]
    if repaint
        if(array.size(zz)>0)
            array.pop(zz)
            array.pop(yy)
    downn
if downn != downn[1]
    if downn
        last_h := hg
    else
        last_l := lw
    if not repaint
        nx = downn?last_h:last_l
        array.push(zz, (downn ? low[last_l] : high[last_h]))
        array.push(yy,bar_index-(downn?last_l:last_h))
    downn
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]

var minorBoxes = array.new_box() 
var minorBoxNames = array.new_string()
var minorCrossedHigh = array.new_bool() 
var minorCrossedLow = array.new_bool()
var expansionLines = array.new_line()
var minorExpansionLines = array.new_line()
[RES,Val1,Val2,POS] = checkTrigger()
if(RES and allowPlot())
    array.push(minorBoxes, box.new(time[bar_index-POS],Val1,time,Val2,xloc=xloc.bar_time,border_color=(show_minor_boxes?Minor_Box_Color:na),bgcolor=(show_minor_boxes?Minor_Box_Color:na)))
    array.push(minorBoxNames, "Active Box")
    array.push(minorCrossedHigh, false), array.push(minorCrossedLow, false)

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)

var check = array.new_int()
var checkMinor = array.new_int()

updateExpansionLines(time,expansionLines,false,check)
updateExpansionLines(time,minorExpansionLines,false,checkMinor)

var majorBoxLines = array.new_line() 
var majorBoxLineType = array.new_int() 
var majorBoxLineRef = array.new_int()
var Crossed = array.new_bool()

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
    
    if(array.size(minorBoxes)>0 and array.size(minorCrossedHigh)>0 and array.size(minorCrossedLow)>0 and array.size(minorBoxNames)>0)
        x = array.size(minorBoxes)-1
        if array.get(minorBoxNames,x)!="NULL"
            top = box.get_top(array.get(minorBoxes,x)), bottom = box.get_bottom(array.get(minorBoxes,x))
            time1 = box.get_left(array.get(minorBoxes,x))
            time2 = box.get_right(array.get(minorBoxes,x)), ppp = bottom+(top-bottom)/2
            origCrossedHigh = array.get(minorCrossedHigh,x)
            origCrossedLow = array.get(minorCrossedLow,x)
            if(not array.get(minorCrossedHigh,x) and not array.get(minorCrossedLow,x))
                if(not barstate.islast or barstate.isconfirmed)
                    if(price>top)
                        array.set(minorCrossedHigh,x,true)
                    if(price<bottom)
                        array.set(minorCrossedLow,x,true)
            else 
                if(hi_price>top)
                    array.set(minorCrossedHigh,x,true)
                if(lo_price<bottom)
                    array.set(minorCrossedLow,x,true)
            if(array.get(minorCrossedHigh,x) and array.get(minorCrossedLow,x))
                box.set_bgcolor(array.get(minorBoxes,x),Major_Box_Color)
                array.set(minorBoxNames,x,"NULL")
                updateExpansionLines(time2,expansionLines,true,check)
                confirm := true
                if(show_minor_expansion)
                    updateExpansionLines(time2,minorExpansionLines,true,checkMinor)           
                array.push(expansionLines,line.new(time2,ppp,time,ppp,xloc.bar_time,extend.none,Major_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.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.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.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.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) 


// Inputs
lookback = input(100, "Lookback Period", tooltip = "The number of previous candles to check for volume")
bullishcolor = input(color.blue, "Bullish Color")
bearishcolor = input(color.yellow, "Bearish Color")


// Variables
highestvolume = ta.highest(volume, lookback)
bullish1 = (close>=open)
bearish1 = (close<open)
bullishvolume = false
bearishvolume = false

// Calculations
if volume >= highestvolume and bullish1
    bullishvolume := true
if volume >= highestvolume and bearish1
    bearishvolume := true

// Plot volume indication
barcolor(bullishvolume ? bullishcolor : bearishvolume ? bearishcolor : na)


//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{ - END                                                                                                                                        }
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}
//{----------------------------------------------------------------------------------------------------------------------------------------------}


//Trendlines


// User input for trendlines visibility
showTrendlines = input(false, "Show Trendlines", inline = "a", group = "SETTINGS")

trelen = input.int(7, "Period ", tooltip = "Lookback period", inline = "b", group = "SETTINGS")
cup = input.color(#089981, "", "")
cdn = input.color(#ff0000, "", "")
space = input.float(0.5, "Padding", tooltip = "Padding distance", inline = "c", group = "SETTINGS", step = 0.1)
shs = input.bool(true, "Show Breakouts", inline = "z", group = "SETTINGS")

ph = ta.pivothigh(high, trelen, trelen)
pl = ta.pivotlow(low, trelen, trelen)

type store
    float src
    int n


type draw
    line[] upln
    line[] dnln

var store[] upbin = array.new<store>()
var store[] dnbin = array.new<store>()

var draw d = draw.new(array.new<line>(), array.new<line>())


atr = ta.atr(200)

method slope(line ln) =>
    x = ln.get_x2() - ln.get_x1()
    y = ln.get_y2() - ln.get_y1()
    y / x

vol() =>
    math.min(atr * 0.1, close * (0.1 / 100))

var bool broken = false
color active = na
bool plup = false
bool pldn = false

if ph
    bool remove = false
    var bool valid = false

    upbin.unshift(store.new(b.h[trelen], b.n[trelen]))
    if upbin.size() > 1
        current = upbin.get(0)
        before = upbin.get(1)
        if current.src < before.src
            if broken
                valid := true
            else
                valid := false
                if upbin.size() > 3
                    pastold = upbin.get(3)
                    pastcur = upbin.get(2)
                    now = upbin.get(1)
                    late = upbin.get(0)
                    if now.src < pastcur.src and now.src < pastold.src and late.src < pastcur.src and late.src < pastold.src
                        valid := true
                    else
                        valid := false
                else
                    valid := false

            if valid
                if showTrendlines
                    d.upln.unshift(line.new(x1 = before.n, x2 = current.n, y1 = before.src, y2 = current.src, color = cdn))
                    d.upln.unshift(line.new(x1 = before.n, x2 = current.n, y1 = before.src - vol() * space, y2 = current.src - vol() * space, color = cdn))
                    ln = d.upln.get(1)
                    for i = 0 to (b.n - before.n)
                        slope = ln.slope()
                        ln.set_x2(b.n[i])
                        ln.set_y2(ln.get_y2() - slope)
                        if low[i] > ln.get_y2()
                            remove := true
                            break

                    if remove
                        d.upln.get(0).delete()
                        d.upln.get(1).delete()
                        d.upln.clear()
                        upbin.clear()
                        broken := true
                    else
                        d.upln.get(0).delete()
                        d.upln.get(1).delete()
                        d.upln.clear()

                        d.upln.unshift(line.new(x1 = before.n, x2 = current.n, y1 = before.src, y2 = current.src, color = cdn))
                        d.upln.unshift(line.new(x1 = before.n, x2 = current.n, y1 = before.src - vol() * space, y2 = current.src - vol() * space, color = cdn))

                        linefill.new(d.upln.get(0), d.upln.get(1), color = color.new(cdn, 75))
                        upbin.clear()
                        broken := false

if d.upln.size() > 1

    btm = d.upln.get(0)
    top = d.upln.get(1)

    if b.l > top.get_y2()
        d.upln.clear()
        broken := true
        upbin.clear()
        plup := true

    if d.upln.size() > 1

        slup = top.slope()
        sldn = btm.slope()

        top.set_x2(b.n)
        top.set_y2(top.get_y2() + slup)

        btm.set_x2(b.n)
        btm.set_y2(btm.get_y2() + sldn)

if pl
    bool remove = false
    var bool valid = false

    dnbin.unshift(store.new(b.l[trelen], b.n[trelen]))
    if dnbin.size() > 1
        current = dnbin.get(0)
        before = dnbin.get(1)
        if current.src > before.src
            if broken
                valid := true
            else
                valid := false
                if dnbin.size() > 3
                    pastold = dnbin.get(3)
                    pastcur = dnbin.get(2)
                    now = dnbin.get(1)
                    late = dnbin.get(0)

                    if now.src > pastcur.src and now.src > pastold.src and late.src > pastcur.src and late.src > pastold.src
                        valid := true
                    else
                        valid := false
                else
                    valid := false

            if valid
                if showTrendlines
                    d.dnln.unshift(line.new(x1 = before.n, x2 = current.n, y1 = before.src, y2 = current.src, color = cup))
                    d.dnln.unshift(line.new(x1 = before.n, x2 = current.n, y1 = before.src + vol() * space, y2 = current.src + vol() * space, color = cup))

                    ln = d.dnln.get(1)
                    for i = 0 to (b.n - before.n)
                        slope = ln.slope()
                        ln.set_x2(b.n[i])
                        ln.set_y2(ln.get_y2() - slope)
                        if high[i] < ln.get_y2()
                            remove := true
                            break

                    if remove
                        d.dnln.get(0).delete()
                        d.dnln.get(1).delete()
                        d.dnln.clear()
                        dnbin.clear()
                        broken := true
                    else
                        d.dnln.get(0).delete()
                        d.dnln.get(1).delete()
                        d.dnln.clear()

                        d.dnln.unshift(line.new(x1 = before.n, x2 = current.n, y1 = before.src, y2 = current.src, color = cup))
                        d.dnln.unshift(line.new(x1 = before.n, x2 = current.n, y1 = before.src + vol() * space, y2 = current.src + vol() * space, color = cup))

                        linefill.new(d.dnln.get(0), d.dnln.get(1), color = color.new(cup, 75))
                        dnbin.clear()
                        broken := false

if d.dnln.size() > 1

    btm = d.dnln.get(0)
    top = d.dnln.get(1)

    if b.h < btm.get_y2()
        d.dnln.clear()
        broken := true
        dnbin.clear()
        pldn := true

    if d.dnln.size() > 1

        slup = top.slope()
        sldn = btm.slope()

        top.set_x2(b.n)
        top.set_y2(top.get_y2() + slup)

        btm.set_x2(b.n)
        btm.set_y2(btm.get_y2() + sldn)

plotshape(pldn and shs ? b.h[1] : na, "Breaking Down", shape.labeldown, location = location.abovebar, color = cdn, offset = -1, size = size.tiny,text = "Br", textcolor = color.white)
plotshape(plup and shs ? b.l[1] : na, "Breaking Up", shape.labelup, location = location.belowbar, color = cup, offset = -1, size = size.tiny,text = "Br", textcolor = color.white)

//------------------- HSN Algo SR |  ----------------------//
// Get user input
enableSR   = input(true, "SR On/Off", group="SR")
colorSup   = input(#9598a1, "Support Color", group="SR")
colorRes   = input(#9598a1, "Resistance Color", group="SR")
strengthSR = input.int(6, "S/R Strength", 1, group="SR")
lineStyle  = input.string("Dotted", "Line Style", ["Solid", "Dotted", "Dashed"], group="SR")
lineWidth  = input.int(2, "S/R Line Width", 1, group="SR")
useZones   = input(true, "Zones On/Off", group="SR")
useHLZones = input(true, "High Low Zones On/Off", group="SR")
zoneWidth  = input.int(1, "Zone Width %", 0, tooltip="it's calculated using % of the distance between highest/lowest in last 300 bars", group="SR")
expandSR   = input(true, "Expand SR")
// Functions
percWidth(len, perc) => (ta.highest(len) - ta.lowest(len)) * perc / 100
// Get components
rb            = 10
prd           = 284
ChannelW      = 10
label_loc     = 55
style         = lineStyle == "Solid" ? line.style_solid : lineStyle == "Dotted" ? line.style_dotted : line.style_dashed
phs            = ta.pivothigh(rb, rb)
pls            = ta.pivotlow (rb, rb)
sr_levels     = array.new_float(21, na)
prdhighest    = ta.highest(prd)
prdlowest     = ta.lowest(prd)
cwidth        = percWidth(prd, ChannelW)
zonePerc      = percWidth(300, zoneWidth)
aas           = array.new_bool(41, true)
u1            = 0.0, u1 := nz(u1[1])
d1            = 0.0, d1 := nz(d1[1])
highestph     = 0.0, highestph := highestph[1]
lowestpl      = 0.0, lowestpl := lowestpl[1]
var sr_levs   = array.new_float(21, na)
label hlabel  = na, label.delete(hlabel[1])
label llabel  = na, label.delete(llabel[1])
var sr_lines  = array.new_line(21, na)
var sr_linesH = array.new_line(21, na)
var sr_linesL = array.new_line(21, na)
var sr_linesF = array.new_linefill(21, na)
var sr_labels = array.new_label(21, na)
if phs or pls
    for x = 0 to array.size(sr_levels) - 1
        array.set(sr_levels, x, na)
    highestph := prdlowest
    lowestpl := prdhighest
    countpp = 0
    for x = 0 to prd
        if na(close[x])
            break
        if not na(phs[x]) or not na(pls[x])
            highestph := math.max(highestph, nz(phs[x], prdlowest), nz(pls[x], prdlowest))
            lowestpl := math.min(lowestpl, nz(phs[x], prdhighest), nz(pls[x], prdhighest))
            countpp += 1
            if countpp > 40
                break
            if array.get(aas, countpp)
                upl = (phs[x] ? high[x + rb] : low[x + rb]) + cwidth
                dnl = (phs[x] ? high[x + rb] : low[x + rb]) - cwidth
                u1 := countpp == 1 ? upl : u1
                d1 := countpp == 1 ? dnl : d1
                tmp = array.new_bool(41, true)
                cnt = 0
                tpoint = 0
                for xx = 0 to prd
                    if na(close[xx])
                        break
                    if not na(phs[xx]) or not na(pls[xx])
                        chg = false
                        cnt += 1
                        if cnt > 40
                            break
                        if array.get(aas, cnt)
                            if not na(phs[xx])
                                if high[xx + rb] <= upl and high[xx + rb] >= dnl
                                    tpoint += 1
                                    chg := true
                            if not na(pls[xx])
                                if low[xx + rb] <= upl and low[xx + rb] >= dnl
                                    tpoint += 1
                                    chg := true
                        if chg and cnt < 41
                            array.set(tmp, cnt, false)
                if tpoint >= strengthSR
                    for g = 0 to 40 by 1
                        if not array.get(tmp, g)
                            array.set(aas, g, false)
                    if phs[x] and countpp < 21
                        array.set(sr_levels, countpp, high[x + rb])
                    if pls[x] and countpp < 21
                        array.set(sr_levels, countpp, low[x + rb])
// Plot
var line highest_ = na, line.delete(highest_)
var line lowest_  = na, line.delete(lowest_)
var line highest_fill1 = na, line.delete(highest_fill1)
var line highest_fill2 = na, line.delete(highest_fill2)
var line lowest_fill1  = na, line.delete(lowest_fill1)
var line lowest_fill2  = na, line.delete(lowest_fill2)
hi_col = close >= highestph ? colorSup : colorRes
lo_col = close >= lowestpl  ? colorSup : colorRes
if enableSR
    highest_ := line.new(bar_index - 311, highestph, bar_index, highestph, xloc.bar_index, expandSR ? extend.both : extend.right, hi_col, style, lineWidth)
    lowest_  := line.new(bar_index - 311, lowestpl , bar_index, lowestpl , xloc.bar_index, expandSR ? extend.both : extend.right, lo_col, style, lineWidth)
    if useHLZones
        highest_fill1 := line.new(bar_index - 311, highestph + zonePerc, bar_index, highestph + zonePerc, xloc.bar_index, expandSR ? extend.both : extend.right, na)
        highest_fill2 := line.new(bar_index - 311, highestph - zonePerc, bar_index, highestph - zonePerc, xloc.bar_index, expandSR ? extend.both : extend.right, na)
        lowest_fill1  := line.new(bar_index - 311, lowestpl + zonePerc , bar_index, lowestpl + zonePerc , xloc.bar_index, expandSR ? extend.both : extend.right, na)
        lowest_fill2  := line.new(bar_index - 311, lowestpl - zonePerc , bar_index, lowestpl - zonePerc , xloc.bar_index, expandSR ? extend.both : extend.right, na)
        linefill.new(highest_fill1, highest_fill2, color.new(hi_col, 80))
        linefill.new(lowest_fill1 , lowest_fill2 , color.new(lo_col, 80))
if phs or pls
    for x = 0 to array.size(sr_lines) - 1
        array.set(sr_levs, x, array.get(sr_levels, x))
for x = 0 to array.size(sr_lines) - 1
    line.delete(array.get(sr_lines, x))
    line.delete(array.get(sr_linesH, x))
    line.delete(array.get(sr_linesL, x))
    linefill.delete(array.get(sr_linesF, x))
    if array.get(sr_levs, x) and enableSR
        line_col = close >= array.get(sr_levs, x) ? colorSup : colorRes
        array.set(sr_lines, x, line.new(bar_index - 355, array.get(sr_levs, x), bar_index, array.get(sr_levs, x), xloc.bar_index, expandSR ? extend.both : extend.right, line_col, style, lineWidth))
        if useZones
            array.set(sr_linesH, x, line.new(bar_index - 355, array.get(sr_levs, x) + zonePerc, bar_index, array.get(sr_levs, x) + zonePerc, xloc.bar_index, expandSR ? extend.both : extend.right, na))
            array.set(sr_linesL, x, line.new(bar_index - 355, array.get(sr_levs, x) - zonePerc, bar_index, array.get(sr_levs, x) - zonePerc, xloc.bar_index, expandSR ? extend.both : extend.right, na))
            array.set(sr_linesF, x, linefill.new(array.get(sr_linesH, x), array.get(sr_linesL, x), color.new(line_col, 80)))



//////////////////////////////////////////////////////////////////////////////////////////
//Main Algo Settings
//------------------- HSN Algo Signal |  ----------------------//


Multiplier = input.float(title='Sensitivity', step=0.1, defval=3.2,group="Signal")
showsignals = input(title='Show Buy/Sell Signals ?', defval=true,group="Signal")
Periods = 40

src = hl2



changeATR = true




atr2 = ta.sma(ta.tr, Periods)

atrs = changeATR ? ta.atr(Periods) : atr2

up = src - Multiplier * atrs

up1 = nz(up[1], up)

up := close[1] > up1 ? math.max(up, up1) : up

dn = src + Multiplier * atrs

dn1 = nz(dn[1], dn)

dn := close[1] < dn1 ? math.min(dn, dn1) : dn

trends = 1

trends := nz(trends[1], trends)

trends := trends == -1 and close > dn1 ? 1 : trends == 1 and close < up1 ? -1 : trends



buySignal = trends == 1 and trends[1] == -1

plotshape(buySignal and showsignals ? up : na, title='Buy', text='Buy', location=location.absolute, style=shape.labelup, size=size.small, color=#049108 , textcolor=color.new(color.white, 0))



sellSignal = trends == -1 and trends[1] == 1

plotshape(sellSignal and showsignals ? dn : na, title='Sell', text='Sell', location=location.absolute, style=shape.labeldown, size=size.small, color=color.rgb(187, 3, 3), textcolor=color.new(color.white, 0))

mPlot = plot(ohlc4, title='', style=plot.style_circles, linewidth=0)



alertcondition(buySignal, title='HSN Trend Buy', message='HSN Trend Buy!')

alertcondition(sellSignal, title='HSN Trend Sell', message='HSN Trend Sell!')




//////////////////////////////////////////////////////////////////////////////////////////
// Color Scheme

//Trend Cloud 
bullcolor = #089981 
bearcolor = #f23645 
plotRibsw = input(title='Show Trend Ribbon', defval=true , inline = "RIBBON" , group = "Chart Features")
xfixtf = input(title='MTF', defval=false , inline = "RIBBON", group = "Chart Features")
plotRibbonPos = input.string(title='Ribbon Position', options=['Top', 'Bottom'], defval='Bottom', group = "Chart Features")
xtf = input.timeframe(title='Select MTF Ribbon', defval='D', group = "Chart Features")

//////////////////////////////////////////////////////////////////////////////////////////


////////////

tst(x)=> str.tostring(x)
var int dec = str.length(str.tostring(syminfo.mintick))-2
trc(number) =>
    factor = math.pow(10, dec)
    int(number * factor) / factor
trc_(number) =>
    factor = math.pow(10, 0)
    int(number * factor) / factor

xsrc = close
xprd1 = 12
xsrc2 = close
xprd2 = 26
xsmooth = 1

xPrice = ta.ema(xsrc, xsmooth)
FastMA = xfixtf ? ta.ema(request.security(syminfo.tickerid, xtf, ta.ema(xsrc, xprd1)), xsmooth) : ta.ema(xPrice, xprd1)
xPrice2 = ta.ema(xsrc2, xsmooth)
SlowMA = xfixtf ? ta.ema(request.security(syminfo.tickerid, xtf, ta.ema(xsrc2, xprd2)), xsmooth) : ta.ema(xPrice2, xprd2)
BullTribbon = FastMA > SlowMA
Tribbon = FastMA < SlowMA

//****************************************************************************//
// Define Color Zones

Green = BullTribbon and xPrice > FastMA  // Buy
Blue = Tribbon and xPrice > FastMA and xPrice > SlowMA  //Pre Buy 2 (Strong dip) Consider adding long position
LBlue = Tribbon and xPrice > FastMA and xPrice < SlowMA  //Pre Buy 1 (Weak Dip)

Red = Tribbon and xPrice < FastMA  // Sell
Orange = BullTribbon and xPrice < FastMA and xPrice < SlowMA  // Pre Sell 2 (Strong Rally) Consider adding short position
Yellow = BullTribbon and xPrice < FastMA and xPrice > SlowMA  // Pre Sell 1 (Weak Rally)


//****************************************************************************//
// Define Buy and Sell condition
// This is only for thebasic usage of CDC Actionzone (EMA Crossover) 
// ie. Buy on first green bar and sell on first red bar

buycond = Green and Green[1] == 0
sellcond = Red and Red[1] == 0

bullTribbonish = ta.barssince(buycond) < ta.barssince(sellcond)
Tribbonish = ta.barssince(sellcond) < ta.barssince(buycond)


bColor_BullTribbonTribbon = bullTribbonish ? bullcolor : Tribbonish ? bearcolor : na


plotshape(plotRibsw ? plotRibbonPos == 'Top' ? close : na : na, style=shape.square, title='Buy/Sell Ribbon', location=location.top, color=bColor_BullTribbonTribbon , editable = false)
plotshape(plotRibsw ? plotRibbonPos == 'Bottom' ? close : na : na, style=shape.square, title='Buy/Sell Ribbon', location=location.bottom, color=bColor_BullTribbonTribbon , editable = false)


len2 = 20  //input(20, minval=1, title="Smooth")
src6 = close
out = ta.vwma(src6, len2)


buy = Tribbonish[1] and buycond
sell = bullTribbonish[1] and sellcond


//****************************************************************************//


// RSI Settings
rsi_len = 14
rsi_overbought = 75
rsi_oversold = 25

// RSI Calculation
rsi = ta.rsi(close, rsi_len)

// Detection of the first occurrence of overbought (RSI > 75)
first_overbought = ta.crossover(rsi, rsi_overbought)

// Detection of the first occurrence of oversold (RSI < 25)
first_oversold = ta.crossunder(rsi, rsi_oversold)

// Show Triangles Checkbox
show_triangles = input.bool(true, "Show Reversal Print", group = "Reversal 📊")

// Showing shapes conditionally based on checkbox value
plotshape(show_triangles and first_overbought, style=shape.circle, color=color.red, size=size.tiny, location=location.abovebar, text = "Reversal down", textcolor = color.red)
plotshape(show_triangles and first_oversold, style=shape.circle, color=color.green, size=size.tiny, location=location.belowbar, text = "Reversal up", textcolor = color.green)

// Alerts
alertcondition(show_triangles and first_overbought, title="Reversal Down", message="Reversal down")
alertcondition(show_triangles and first_oversold, title="Reversal Up", message="Reversl up")


type Candle
    float           o
    float           c
    float           h
    float           l
    int             o_idx
    int             c_idx
    int             h_idx
    int             l_idx
    box             body
    line            wick_up
    line            wick_down


type Imbalance
    box             b
    int             idx

type CandleSettings
    bool            show
    string          htf
    int             max_display

type Settings
    int             max_sets
    color           bull_body
    color           bull_border
    color           bull_wick
    color           bear_body
    color           bear_border
    color           bear_wick
    int             offset
    int             buffer
    int             htf_buffer
    int             width
    bool            trace_show
    color           trace_o_color
    string          trace_o_style
    int             trace_o_size
    color           trace_c_color
    string          trace_c_style
    int             trace_c_size
    color           trace_h_color
    string          trace_h_style
    int             trace_h_size
    color           trace_l_color
    string          trace_l_style
    int             trace_l_size
    string          trace_anchor
    bool            label_show
    color           label_color
    string          label_size
    bool            htf_label_show
    color           htf_label_color
    string          htf_label_size
    bool            htf_timer_show
    color           htf_timer_color
    string          htf_timer_size

type CandleSet
    Candle[]        candles
    Imbalance[]     imbalances
    CandleSettings  settings
    label           tfName
    label           tfTimer

type Helper
    string name             = "Helper"

Settings settings           = Settings.new()

var CandleSettings SettingsHTF1 = CandleSettings.new()
var CandleSettings SettingsHTF2 = CandleSettings.new()
var CandleSettings SettingsHTF3 = CandleSettings.new()



var Candle[] candles_1        = array.new<Candle>(0)
var Candle[] candles_2        = array.new<Candle>(0)
var Candle[] candles_3        = array.new<Candle>(0)


var CandleSet htf1          = CandleSet.new()
htf1.settings               := SettingsHTF1
htf1.candles                := candles_1


var CandleSet htf2          = CandleSet.new()
htf2.settings               := SettingsHTF2
htf2.candles                := candles_2


var CandleSet htf3          = CandleSet.new()
htf3.settings               := SettingsHTF3
htf3.candles                := candles_3



//+------------------------------------------------------------------------------------------------------------+//
//+--- Settings                                                                                             ---+//
//+------------------------------------------------------------------------------------------------------------+//

htf1.settings.show          := input.bool(true, "HTF 1      ", inline="htf1")
htf_1                       = input.timeframe("15", "", inline="htf1")
htf1.settings.htf           := htf_1
htf1.settings.max_display   := input.int(4, "", inline="htf1")

htf2.settings.show          := input.bool(true, "HTF 2      ", inline="htf2")
htf_2                       = input.timeframe("60", "", inline="htf2")
htf2.settings.htf           := htf_2
htf2.settings.max_display   := input.int(4, "", inline="htf2")

htf3.settings.show          := input.bool(true, "HTF 3      ", inline="htf3")
htf_3                       = input.timeframe("1D", "", inline="htf3")
htf3.settings.htf           := htf_3
htf3.settings.max_display   := input.int(4, "", inline="htf3")


settings.max_sets        := input.int(6, "Limit to next HTFs only", minval=1, maxval=6)

settings.bull_body       := input.color(color.new(color.green, 10), "Body  ", inline="body")
settings.bear_body       := input.color(color.new(color.red, 10), "", inline="body")
settings.bull_border     := input.color(color.new(color.black, 10), "Borders", inline="borders")
settings.bear_border     := input.color(color.new(color.black, 10), "", inline="borders")
settings.bull_wick       := input.color(color.new(color.black, 10), "Wick  ", inline="wick")
settings.bear_wick       := input.color(color.new(color.black, 10), "", inline="wick")

settings.offset          := input.int(25, "padding from current candles", minval = 1)
settings.buffer          := input.int(1, "space between candles", minval = 1, maxval = 4)
settings.htf_buffer      := input.int(10, "space between Higher Timeframes", minval = 1, maxval = 10)
settings.width           := input.int(1, "Candle Width", minval = 1, maxval = 4)*2

settings.htf_label_show  := input.bool(true, "HTF Label           ", inline="HTFlabel")
settings.htf_label_color := input.color(color.new(color.black, 10), "", inline='HTFlabel')
settings.htf_label_size  := input.string(size.large, "", [size.tiny, size.small, size.normal, size.large, size.huge], inline="HTFlabel")



//+------------------------------------------------------------------------------------------------------------+//
//+--- Variables                                                                                            ---+//
//+------------------------------------------------------------------------------------------------------------+//

Helper    helper        = Helper.new()

color color_transparent = #ffffff00

//+------------------------------------------------------------------------------------------------------------+//
//+--- Internal Functions                                                                                   ---+//
//+------------------------------------------------------------------------------------------------------------+//

method LineStyle(Helper helper, string style) =>
    helper.name := style
    out = switch style
        '----' => line.style_dashed
        '····' => line.style_dotted
        => line.style_solid


method ValidTimeframe(Helper helper, string HTF) =>
    helper.name := HTF
    if timeframe.in_seconds(HTF) >= timeframe.in_seconds("D") and timeframe.in_seconds(HTF) > timeframe.in_seconds()
        true
    else
        n1 = timeframe.in_seconds()
        n2 = timeframe.in_seconds(HTF)
        n3 = n1 % n2
        (n1 < n2 and math.round(n2/n1) == n2/n1)



method HTFName(Helper helper, string HTF) =>
    helper.name := "HTFName"
    formatted = HTF

    seconds = timeframe.in_seconds(HTF)
    if seconds < 60
        formatted := str.tostring(seconds) + "s"
    else if (seconds / 60) < 60
        formatted := str.tostring((seconds/60)) + "m"
    else if (seconds/60/60) < 24
        formatted := str.tostring((seconds/60/60)) + "H" 
    formatted

method HTFEnabled(Helper helper) =>
    helper.name := "HTFEnabled"
    int enabled =0
    enabled += htf1.settings.show ? 1 : 0
    enabled += htf2.settings.show ? 1 : 0
    enabled += htf3.settings.show ? 1 : 0

    int last = math.min(enabled, settings.max_sets)

    last

method CandleSetHigh(Helper helper, Candle[] candles, float h) =>
    helper.name := "CandlesSetHigh"
    float _h = h
    if array.size(candles) > 0
        for i = 0 to array.size(candles)-1
            Candle c = array.get(candles, i)
            if c.h > _h
                _h := c.h
    _h

method CandlesHigh(Helper helper, Candle[] candles) =>
    helper.name := "CandlesHigh"
    h   = 0.0
    int cnt = 0
    int last = helper.HTFEnabled()

    if htf1.settings.show and helper.ValidTimeframe(htf1.settings.htf)
        h := helper.CandleSetHigh(htf1.candles, h)
        cnt += 1
    if htf2.settings.show and helper.ValidTimeframe(htf2.settings.htf) and cnt < last
        h := helper.CandleSetHigh(htf2.candles, h)
        cnt +=1
    if htf3.settings.show and helper.ValidTimeframe(htf3.settings.htf) and cnt < last
        h := helper.CandleSetHigh(htf3.candles, h)
        cnt += 1
  

    if array.size(candles) > 0
        for i = 0 to array.size(candles)-1
            Candle c = array.get(candles, i)
            if c.h > h
                h := c.h
    h

method Reorder(CandleSet candleSet, int offset) =>
    size = candleSet.candles.size()

    if size > 0
        for i = size-1 to 0
            Candle candle = candleSet.candles.get(i)
            t_buffer = offset + ((settings.width+settings.buffer)*(size-i-1))
            box.set_left(candle.body, bar_index + t_buffer)
            box.set_right(candle.body, bar_index + settings.width + t_buffer)
            line.set_x1(candle.wick_up, bar_index+((settings.width)/2) + t_buffer)
            line.set_x2(candle.wick_up, bar_index+((settings.width)/2) + t_buffer)
            line.set_x1(candle.wick_down, bar_index+((settings.width)/2) + t_buffer)
            line.set_x2(candle.wick_down, bar_index+((settings.width)/2) + t_buffer)
    candleSet

    top     = helper.CandlesHigh(candleSet.candles)
    left    = bar_index + offset + ((settings.width+settings.buffer)*(size-1))/2

    if settings.htf_label_show
        var label l = candleSet.tfName

        string lbl = helper.HTFName(candleSet.settings.htf)
        if settings.htf_timer_show
            lbl += "\n"
   
        if not na(l)
            label.set_xy(l, left, top)            
        else
            l := label.new(left, top, lbl, color=color_transparent, textcolor = settings.htf_label_color, style=label.style_label_down, size = settings.htf_label_size)

    if settings.htf_timer_show
        var label t = candleSet.tfTimer
        
        if not na(t)
            label.set_xy(t, left, top)            
       

    candleSet

method FindImbalance(CandleSet candleSet) =>
    if barstate.isrealtime or barstate.islast
        if candleSet.imbalances.size() > 0
            for i = candleSet.imbalances.size()-1 to 0
                Imbalance del = candleSet.imbalances.get(i)
                box.delete(del.b)
                candleSet.imbalances.pop()

        if candleSet.candles.size() > 3 
            for i = 1 to candleSet.candles.size() -3
                candle1 = candleSet.candles.get(i)
                candle2 = candleSet.candles.get(i+2)
                candle3 = candleSet.candles.get(i+1)

             

method Monitor(CandleSet candleSet) =>
    HTFBarTime = time(candleSet.settings.htf)
    isNewHTFCandle = ta.change(HTFBarTime)

    if isNewHTFCandle 
        Candle candle = Candle.new()
        candle.o        := open
        candle.c        := close
        candle.h        := high
        candle.l        := low
        candle.o_idx    := bar_index
        candle.c_idx    := bar_index
        candle.h_idx    := bar_index
        candle.l_idx    := bar_index

        bull = candle.c > candle.o

        candle.body         := box.new(bar_index, math.max(candle.o, candle.c), bar_index+2, math.min(candle.o, candle.c), bull ? settings.bull_border : settings.bear_border, 1, bgcolor = bull ? settings.bull_body : settings.bear_body)
        candle.wick_up      := line.new(bar_index+1, candle.h, bar_index, math.max(candle.o, candle.c), color=bull ? settings.bull_wick : settings.bear_wick)
        candle.wick_down    := line.new(bar_index+1, math.min(candle.o, candle.c), bar_index, candle.l, color=bull ? settings.bull_wick : settings.bear_wick)

        candleSet.candles.unshift(candle)

        if candleSet.candles.size() > candleSet.settings.max_display
            Candle delCandle = array.pop(candleSet.candles)
            box.delete(delCandle.body)
            line.delete(delCandle.wick_up)
            line.delete(delCandle.wick_down)

    candleSet

method Update(CandleSet candleSet, int offset, bool showTrace) =>
    if candleSet.candles.size() > 0
        Candle candle   = candleSet.candles.first()
        candle.h_idx    := high > candle.h ? bar_index : candle.h_idx
        candle.h        := high > candle.h ? high : candle.h
        candle.l_idx    := low < candle.l ? bar_index : candle.l_idx
        candle.l        := low < candle.l ? low : candle.l
        candle.c        := close
        candle.c_idx   := bar_index

        bull = candle.c > candle.o

        box.set_top(candle.body, candle.o)
        box.set_bottom(candle.body, candle.c)
        box.set_bgcolor(candle.body, bull ? settings.bull_body : settings.bear_body)
        box.set_border_color(candle.body, bull ? settings.bull_border : settings.bear_border)
        line.set_color(candle.wick_up, bull ? settings.bull_wick : settings.bear_wick)
        line.set_color(candle.wick_down, bull ? settings.bull_wick : settings.bear_wick)
        line.set_y1(candle.wick_up, candle.h)
        line.set_y2(candle.wick_up, math.max(candle.o, candle.c))
        line.set_y1(candle.wick_down, candle.l)
        line.set_y2(candle.wick_down, math.min(candle.o, candle.c))

        if barstate.isrealtime or barstate.islast
            candleSet.Reorder(offset)
            
    candleSet

int cnt = 0
int last = helper.HTFEnabled()

int offset = settings.offset
if htf1.settings.show and helper.ValidTimeframe(htf1.settings.htf)
    bool showTrace = false
    if settings.trace_anchor == "First Timeframe"
        showTrace := true
    if settings.trace_anchor == "Last Timeframe" and settings.max_sets == 1
        showTrace := true
    htf1.Monitor().Update(offset, showTrace)
    cnt +=1
    offset += cnt > 0 ? (htf1.candles.size() * settings.width) + (htf1.candles.size() > 0 ? htf1.candles.size()-1 * settings.buffer : 0) +  settings.htf_buffer : 0
if htf2.settings.show and helper.ValidTimeframe(htf2.settings.htf) and cnt < last
    bool showTrace = false
    if settings.trace_anchor == "First Timeframe" and cnt == 0
        showTrace := true
    if settings.trace_anchor == "Last Timeframe" and cnt == last-1
        showTrace := true
    htf2.Monitor().Update(offset, showTrace)
    cnt+=1
    offset += cnt > 0 ? (htf2.candles.size() * settings.width) + (htf2.candles.size() > 0 ? htf2.candles.size()-1 * settings.buffer : 0) +  settings.htf_buffer : 0
if htf3.settings.show and helper.ValidTimeframe(htf3.settings.htf) and cnt < last
    bool showTrace = false
    if settings.trace_anchor == "First Timeframe" and cnt == 0
        showTrace := true
    if settings.trace_anchor == "Last Timeframe" and cnt == last-1
        showTrace := true
    htf3.Monitor().Update(offset, showTrace)
    cnt+=1
    offset += cnt > 0 ? (htf3.candles.size() * settings.width) + (htf3.candles.size() > 0 ? htf3.candles.size()-1 * settings.buffer : 0) +  settings.htf_buffer : 0

// Alerts

alertcondition(blalert.bos           , "Bullish BOS", "Bullish BOS")
alertcondition(blalert.choch         , "Bullish CHOCH", "Bullish CHOCH")
alertcondition(blalert.chochplus     , "Bullish CHOCH+", "Bullish CHOCH+")
alertcondition(blalert.chochplusswing, "Bullish Swing CHOCH+", "Bullish Swing CHOCH+")
alertcondition(blalert.chochswing    , "Bullish Swing CHOCH", "Bullish CHOCH")
alertcondition(blalert.swingbos      , "Bullish Swing BOS", "Bullish Swing BOS")
alertcondition(blalert.ob            , "Bullish Order Block", "Bullish Order Block")
alertcondition(blalert.swingob       , "Bullish Swing Order Block", "Bullish Swing Order Block")
alertcondition(blalert.obtouch       , "Candle Entering in a Bullish Order Block", "Candle Entering in a Bullish Order Block")
alertcondition(bralert.bos           , "Bearish BOS", "Bearish BOS")
alertcondition(bralert.choch         , "Bearish CHOCH", "Bearish CHOCH")
alertcondition(bralert.chochplus     , "Bearish CHOCH+", "Bearish CHOCH+")
alertcondition(bralert.chochplusswing, "Bearish Swing CHOCH+", "Bearish Swing CHOCH+")
alertcondition(bralert.chochswing    , "Bearish Swing CHOCH", "Bearish CHOCH")
alertcondition(bralert.swingbos      , "Bearish Swing BOS", "Bearish Swing BOS")
alertcondition(bralert.ob            , "Bearish Order Block", "Bearish Order Block")
alertcondition(bralert.swingob       , "Bearish Swing Order Block", "Bearish Swing Order Block")
alertcondition(bralert.obtouch       , "Candle Entering in a Bearish Order Block", "Candle Entering in a Bearish Order Block")

if barstate.isfirst
    var table errorBox = table.new(position.bottom_right, 1, 1, bgcolor = color.new(#363a45, 100))
    table.cell(errorBox,  0,  0,  "© HSN",   text_color = color.gray, text_halign = text.align_center, text_size = size.normal)
    


// ==========================================================================================

// === Dashboard with Telegram Link ===
var table myTable = table.new(position.top_center, 1, 1, border_width=1, frame_color=color.black, bgcolor=color.white)

// Add Telegram Message to Dashboard
table.cell(myTable, 0, 0, "ATOMIC TRADES", bgcolor=color.rgb(73, 73, 73), text_color=color.white, text_size=size.normal)

Overview

Supply and demand zones track price rejections using box drawings and configurable swing sensitivity. Users can adjust the multi-timeframe resolution, order block mitigation style, zone widths, and display filters. Multi-timeframe security requests introduce potential lookahead risk if misconfigured.

Details

Published by

IAMATOMIC001 on GitHub

Draws

On the price chart

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

  • Reads higher-timeframe data with lookahead on, so the history can show signals that were not there in real time

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Show Supply & Demandbooltrueshowsr
Sensitivityint8swing_length
Zone Widthfloat4box_width
Extend BoxstringRightbox_extend_option
Time Frametimeframeres
Supply & Demand Colorcolor#08998148demand_color
supply_colorcolor#f2364648supply_color
Swing        stringAllshow_swing_ms
Internal     stringNoneshow_internal_ms
internal_r_lookbackint5internal_r_lookback
swing_r_lookbackint50swing_r_lookback
Market Structure ModestringManualms_mode
Show all 40 settings
SettingTypeDefaultVariable
i_ms_up_BOScolor#089981i_ms_up_BOS
i_ms_dn_BOScolor#f23645i_ms_dn_BOS
s_ms_up_BOScolor#089981s_ms_up_BOS
s_ms_dn_BOScolor#f23645s_ms_dn_BOS
Show Last    booltrueob_show
ob_numint5ob_num
Internal Buy/Sell Activitybooltrueob_metrics_show
         colorcolor.new(#047c32, 50)css_metric_up
css_metric_dncolorcolor.new(#cf041b, 50)css_metric_dn
Swing Order Blocksboolfalseob_swings
                 colorcolor.new(color.gray , 90)css_swing_up
css_swing_dncolorcolor.new(color.silver, 90)css_swing_dn
Filtering             stringNoneob_filter
Mitigation           stringAbsoluteob_mitigation
Positioning          stringPreciseob_pos
Grayscalebooltrueuse_grayscale
Show Metricsbooltrueuse_show_metric
Show Middle-Lineboolfalseuse_middle_line
Hide Overlapbooltrueuse_overlap
Overlap Method    stringPrevioususe_overlap_method
ob_bull_csscolorcolor.new(#089981 , 90)ob_bull_css
ob_bear_csscolorcolor.new(#f23645 , 90)ob_bear_css
Show swing pointboolfalseshow_lbl
Show High/Low/Equilibriumboolfalseshow_mtb
Premium Zone   colorcolor.redtoplvl
Equilibrium Zonecolorcolor.whitemidlvl
Discount Zone    color#089981btmlvl
Metric SizestringSmallobtxt
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

ICT Equal Highs and Lows

by ArunKBhaskar
575 stars

This overlay indicator finds pivot highs and lows on the price chart and compares the last two highs and the last two lows. When the percentage difference between a pair is below the Equal HL threshold, it treats them as equal levels and draws a box. Left and

Indicator v5 SMC / ICT / price actionSupport & resistance
Updated 1 year ago · MPL-2.0 GitHub repository of ICT Equal Highs and Lows

DE-tracker

by Allen1212
303 stars

This indicator plots labels on the TradingView price chart to mark ARK Invest's buy and sell trades for the DE stock. Buy transactions appear in green with X1 or X2 multipliers showing the number of ARK ETFs involved on the same day; sells appear in red. The m

Indicator v4 Support & resistanceSMC / ICT / price action
Updated 2 years ago · None stated GitHub repository of DE-tracker

This Pine Script indicator plots a ZigZag on the price chart. It identifies reversal points when price moves more than a set percentage from the last pivot. The script calculates forecasts using zigzag data and labels detected geometric patterns including harm

Indicator v4 TrendSupport & resistance

Golden Bullet Strategy

by TradersPost
228 stars

The Golden Bullet Strategy is an overlay signal indicator based on Smart Money Concepts and time-based liquidity models. It identifies liquidity sweeps of a designated reference session range during a specified hunt window. It then confirms Market Structure Sh

Indicator v6 SMC / ICT / price actionSessions & time
Updated 3 months ago · None stated GitHub repository of Golden Bullet Strategy

Open Source Fractal

by cantolab
183 stars

This indicator implements the Fractal Model concept to plot market structure shifts, liquidity sweeps, and Change in State of Delivery (CISD) levels. It overlays custom higher-timeframe candle previews, open prices, and time markers directly on the price chart

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 2 months ago · MIT GitHub repository of Open Source Fractal

Swing Failure Signals

by Ganador1
154 stars

This indicator calculates pivot highs and pivot lows to detect liquidity sweeps and Swing Failure Patterns. It identifies when price breaks past recent key swing highs or lows within a configurable historical window, then looks for a quick reversal or change i

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 2 months ago · Apache-2.0 GitHub repository of Swing Failure Signals

More SMC / ICT scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers