Indicator · Pine Script v6 · On the chart

Mahi_varma PA

by manthenamahendravarma-IO

This indicator maps market structure and price action levels directly on the price chart.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code2,229
Settings40inputs
LicenceMIT
Last update3 days ago25 Oct 2026

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,229 lines of Pine Script v6 from price_action_indicator.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

price_action_indicator.pine
//@version=6
indicator("Mahi_varma PA", overlay=true, max_lines_count=500, max_labels_count=500, max_boxes_count=500)

// ==================================================================
// PRICE ACTION STRUCTURE DISPLAY
// ==================================================================
showStructureMarking = true

// ==================================================================
// INPUTS
// ==================================================================
grpMain = "Main"
inpStartTime         = input.time(timestamp("2026-01-01T00:00:00"), "Start Time",         group=grpMain)
inpMaxBars           = input.int(12000, "Max Bars", minval=20,                           group=grpMain)

grpDisp = "Structure Display"
inpShowSwings        = input.bool(true,  "Show Swings",                                   group=grpDisp)
inpShowBOS           = input.bool(true,  "Show BOS",                                      group=grpDisp)
inpShowCHOCH         = input.bool(true,  "Show CHOCH",                                    group=grpDisp)
inpShowLevels        = input.bool(true,  "Show Levels",                                   group=grpDisp)
inpShowTJL           = input.bool(true,  "Show TJL",                                      group=grpDisp)
inpShowISS           = input.bool(true,  "Show ISS",                                      group=grpDisp)
inpKeepOnlyLastCHOCH = input.bool(false, "Keep Only Last CHOCH",                         group=grpDisp)

grpIndiv = "Individual Level Visibility"
inpShowTJL1         = input.bool(true, "Show TJL 1",                                    group=grpIndiv)
inpShowTJL2         = input.bool(true, "Show TJL 2",                                    group=grpIndiv)
inpShowQML          = input.bool(true, "Show QML",                                      group=grpIndiv)
inpShowSBR          = input.bool(true, "Show SBR",                                      group=grpIndiv)
inpShowRBS          = input.bool(true, "Show RBS",                                      group=grpIndiv)
inpShowDB           = input.bool(true, "Show DB",                                       group=grpIndiv)
inpShowDT           = input.bool(true, "Show DT",                                       group=grpIndiv)
inpShowBestQML      = input.bool(true, "Show Best Levels",                              group=grpIndiv)
inpShowISS1         = input.bool(false, "Show ISS 1",                                   group=grpIndiv)
inpShowISS2         = input.bool(true, "Show ISS 2",                                    group=grpIndiv)
inpShowISS3         = input.bool(true, "Show ISS 3",                                    group=grpIndiv)
inpShowISS4         = input.bool(true, "Show ISS 4",                                    group=grpIndiv)

grpAPlus = "A+ Levels"
inpShowOnlyAPlus    = input.bool(false, "Show Only A+ Levels (TJL2, QML, D-CHOCH QML, ISS4)", group=grpAPlus)

grpISS = "ISS Controls"
inpEnableISS           = input.bool(true, "Enable ISS Logic",                            group=grpISS)
inpShowISSLabel       = input.bool(true, "Show ISS Label",                              group=grpISS)
inpShowISSBOS         = input.bool(true, "Show ISS BOS",                                group=grpISS)
inpStopISS34ByWickTap = input.bool(true, "Stop ISS 3/4 on Wick Tap",                    group=grpISS)
inpISSScenario         = input.string("1", "ISS Scenario", options=["1", "2"],          group=grpISS, tooltip="1 = Original ISS logic (7 July build). 2 = Alternate ISS logic (new build). Only affects how ISS base/shift/confirmation is tracked internally.")

grpCol = "Level Colors"
inpCHColor           = input.color(color.white,              "CH Color",                  group=grpCol)
inpCLColor           = input.color(color.orange,            "CL Color",                  group=grpCol)
inpBullBOSColor      = input.color(color.green,              "Bull BOS Color",            group=grpCol)
inpBearBOSColor      = input.color(color.red,                "Bear BOS Color",            group=grpCol)
inpBullTJLColor      = input.color(color.green,              "Bull TJL Color",            group=grpCol)
inpBearTJLColor      = input.color(color.orange,             "Bear TJL Color",            group=grpCol)
inpSBRColor          = input.color(color.red,                "SBR Color",                 group=grpCol)
inpRBSColor          = input.color(color.green,              "RBS Color",                 group=grpCol)
inpQMLColor          = input.color(color.rgb(186, 85, 211), "QML Color",                 group=grpCol)
inpDTDBColor         = input.color(color.blue,              "DT/DB Color",               group=grpCol)
inpISSColor          = input.color(color.yellow,            "ISS Color",                 group=grpCol)
inpBestQMLColor      = input.color(color.rgb(255, 215, 0),  "Best QML Color",            group=grpCol)

grpSt = "Style"
inpLineWidth         = input.int(2,   "Line Width",      minval=1,                      group=grpSt)
inpMaxLiveLevels     = input.int(140, "Max Live Levels", minval=1,                      group=grpSt)
inpMaxLabels         = input.int(180, "Max Labels",      minval=1,                      group=grpSt)
inpMaxLines          = input.int(180, "Max Lines",       minval=1,                      group=grpSt)
inpZoneBodyPct       = input.float(1.0, "Zone Body %", minval=0.0, maxval=100.0, step=0.1, group=grpSt)
tapByWick  = "TapByWick"
tapByClose = "TapByClose"
inpStopOnTap = input.bool(true,        "Stop On Tap",                                    group=grpSt)
inpTapSource = input.string(tapByWick, "Tap Source", options=[tapByWick, tapByClose],   group=grpSt)
inpLevelTextVPos = input.string("Inside", "Level Text Vertical", options=["Top", "Inside", "Bottom"], group=grpSt)
inpLevelTextHPos = input.string("Right", "Level Text Horizontal", options=["Left", "Center", "Right"], group=grpSt)

grpSMC = "Smart Money Concepts (SMC)"
inpShowFVG         = input.bool(false, "Show FVG (Fair Value Gap / IPDA)",              group=grpSMC)
inpFVGDeleteOnTap  = input.bool(true, "Delete FVG on Tap",                              group=grpSMC)
inpMaxFVG           = input.int(30,    "Max FVG Levels",  minval=1, maxval=50,           group=grpSMC)
inpShowOB          = input.bool(false, "Show Order Blocks (Opposite Candle Before Move)",group=grpSMC)
inpOBDeleteOnTap   = input.bool(true, "Delete OB on Tap",                               group=grpSMC)
inpMaxOB           = input.int(20,    "Max Order Block Levels", minval=1, maxval=30,    group=grpSMC)
inpShowKZ          = input.bool(false, "Show Kill Zones (IST)",                         group=grpSMC)
inpBullFVGColor    = input.color(color.new(color.teal,    70), "Bull FVG Color",        group=grpSMC)
inpBearFVGColor    = input.color(color.new(color.maroon,  70), "Bear FVG Color",        group=grpSMC)
inpBullOBColor     = input.color(color.new(color.lime,    75), "Demand OB Color",       group=grpSMC)
inpBearOBColor     = input.color(color.new(color.red,      75), "Supply OB Color",       group=grpSMC)
inpLondonColor     = input.color(color.new(color.blue,    92), "London KZ Color",        group=grpSMC)
inpNYColor         = input.color(color.new(color.purple,  92), "NY KZ Color",            group=grpSMC)

grpDash = "Trend Dashboard"
inpShowTrendDash   = input.bool(false, "Show MTF Trend Dashboard",                      group=grpDash)
inpDashShowTf1     = input.bool(true, "Show Timeframe 1",                               group=grpDash)
inpDashTf1         = input.timeframe("1",   "Timeframe 1",                              group=grpDash)
inpDashShowTf2     = input.bool(true, "Show Timeframe 2",                               group=grpDash)
inpDashTf2         = input.timeframe("3",   "Timeframe 2",                              group=grpDash)
inpDashShowTf3     = input.bool(true, "Show Timeframe 3",                               group=grpDash)
inpDashTf3         = input.timeframe("5",   "Timeframe 3",                              group=grpDash)
inpDashShowTf4     = input.bool(true, "Show Timeframe 4",                               group=grpDash)
inpDashTf4         = input.timeframe("15",  "Timeframe 4",                              group=grpDash)
inpDashShowTf5     = input.bool(true, "Show Timeframe 5",                               group=grpDash)
inpDashTf5         = input.timeframe("30",  "Timeframe 5",                              group=grpDash)
inpDashShowTf6     = input.bool(true, "Show Timeframe 6",                               group=grpDash)
inpDashTf6         = input.timeframe("45",  "Timeframe 6",                              group=grpDash)
inpDashShowTf7     = input.bool(true, "Show Timeframe 7",                               group=grpDash)
inpDashTf7         = input.timeframe("60",  "Timeframe 7",                              group=grpDash)
inpDashShowTf8     = input.bool(true, "Show Timeframe 8",                               group=grpDash)
inpDashTf8         = input.timeframe("120", "Timeframe 8",                              group=grpDash)
inpDashShowTf9     = input.bool(true, "Show Timeframe 9",                               group=grpDash)
inpDashTf9         = input.timeframe("180", "Timeframe 9",                              group=grpDash)
inpDashShowTf10    = input.bool(true, "Show Timeframe 10",                              group=grpDash)
inpDashTf10        = input.timeframe("240", "Timeframe 10",                             group=grpDash)
inpDashShowTf11    = input.bool(true, "Show Timeframe 11",                              group=grpDash)
inpDashTf11        = input.timeframe("D",   "Timeframe 11",                             group=grpDash)
inpDashShowTf12    = input.bool(true, "Show Timeframe 12",                              group=grpDash)
inpDashTf12        = input.timeframe("W",   "Timeframe 12",                             group=grpDash)
inpDashShowTf13    = input.bool(true, "Show Timeframe 13",                              group=grpDash)
inpDashTf13        = input.timeframe("M",   "Timeframe 13",                             group=grpDash)

grpAnalyzer = "Level Analyzer"
inpShowLevelAnalyzer = input.bool(false, "Show Level Accuracy Analyzer",                 group=grpAnalyzer)
inpAnalyzerTargetPips = input.float(150.0, "Win Target (Pips)", minval=0.1, step=0.1,    group=grpAnalyzer)
inpAnalyzerLossPips = input.float(50.0, "Loss Target (Pips)", minval=0.1, step=0.1,      group=grpAnalyzer)
inpAnalyzerPipMode = input.string("Auto", "Pip Size Mode", options=["Auto", "Custom"],   group=grpAnalyzer)
inpAnalyzerCustomPipSize = input.float(0.0001, "Custom Pip Size", minval=0.00000001, step=0.00000001, group=grpAnalyzer)
inpAnalyzerMinDone = input.int(3, "Min Finished Tests To Rank", minval=1,                group=grpAnalyzer)
inpAnalyzerShowBuyTJL1 = input.bool(true, "Table: BUY TJL1",                             group=grpAnalyzer)
inpAnalyzerShowBuyTJL2 = input.bool(true, "Table: BUY TJL2",                             group=grpAnalyzer)
inpAnalyzerShowSellTJL1 = input.bool(true, "Table: SELL TJL1",                           group=grpAnalyzer)
inpAnalyzerShowSellTJL2 = input.bool(true, "Table: SELL TJL2",                           group=grpAnalyzer)
inpAnalyzerShowSBR = input.bool(true, "Table: SBR",                                      group=grpAnalyzer)
inpAnalyzerShowRBS = input.bool(true, "Table: RBS",                                      group=grpAnalyzer)
inpAnalyzerShowDT = input.bool(true, "Table: DT",                                        group=grpAnalyzer)
inpAnalyzerShowDB = input.bool(true, "Table: DB",                                        group=grpAnalyzer)
inpAnalyzerShowBuyQML = input.bool(true, "Table: BUY QML",                               group=grpAnalyzer)
inpAnalyzerShowSellQML = input.bool(true, "Table: SELL QML",                             group=grpAnalyzer)
inpAnalyzerShowISS4 = input.bool(true, "Table: ISS 4",                                    group=grpAnalyzer)
inpAnalyzerShowBestSBR = input.bool(true, "Table: D-CHOCH SBR",                          group=grpAnalyzer)
inpAnalyzerShowBestRBS = input.bool(true, "Table: D-CHOCH RBS",                          group=grpAnalyzer)
inpAnalyzerShowBestDT = input.bool(true, "Table: D-CHOCH DT",                            group=grpAnalyzer)
inpAnalyzerShowBestDB = input.bool(true, "Table: D-CHOCH DB",                            group=grpAnalyzer)
inpAnalyzerShowBestBuyQML = input.bool(true, "Table: D-CHOCH SELL QML",                  group=grpAnalyzer)
inpAnalyzerShowBestSellQML = input.bool(true, "Table: D-CHOCH BUY QML",                  group=grpAnalyzer)

grpDebug = "Debug"
inpShowDebugState = input.bool(false, "Show Debug State Labels", group=grpDebug)



// ==================================================================
// TYPES
// ==================================================================
type Snap
    int   t
    int   bar
    float o
    float c
    float h
    float l
    float lvl

type Level
    int    left
    int    right
    float  top
    float  bot
    color  col
    string txt
    int    kind
    int    dir
    bool   active
    bool   deleted
    bool   stopReady
    int    stopReadyBar
    int    bornBar
    box    bx
    label  lb
    bool   anaStarted
    bool   anaActive
    int    anaStartBar
    bool   anaWaitingConfirm
    float  anaTargetPrice
    float  anaLossPrice

type FVGLevel
    int    left
    int    right
    float top
    float bot
    bool   bull
    bool   active
    bool   deleted
    box    bx

type OBLevel
    int    left
    int    right
    float top
    float bot
    bool   bull
    bool   active
    bool   deleted
    box    bx

// ==================================================================
// HELPERS
// ==================================================================
f_initSnap() =>
    Snap.new(0, 0, 0.0, 0.0, 0.0, 0.0, 0.0)

f_makeSnapCurrent(float level) =>
    Snap.new(time, bar_index, open, close, high, low, level)

f_makeSnapAtBar(int srcBar, float level) =>
    off = bar_index - srcBar
    off >= 0 ? Snap.new(time[off], srcBar, open[off], close[off], high[off], low[off], level) : f_initSnap()

f_candleZone(float o, float c, float h, float l, bool isHigh) =>
    bodyTop = math.max(o, c)
    bodyBot = math.min(o, c)
    pad     = math.max(bodyTop - bodyBot, 0.0) * inpZoneBodyPct * 0.01
    top_    = isHigh ? h : bodyBot + pad
    bot_    = isHigh ? bodyTop - pad : l
    [top_, bot_]

f_isTapped(float rClose, float rHigh, float rLow, float top_, float bot_) =>
    if inpTapSource == tapByClose
        rClose <= top_ and rClose >= bot_
    else
        rHigh >= bot_ and rLow <= top_

f_levelDir(int kind, bool isHigh) =>
    if kind == 1 or kind == 2
        isHigh ? 1 : -1
    else if kind == 4 or kind == 6
        1
    else if kind == 3 or kind == 5
        -1
    else if kind == 7
        isHigh ? -1 : 1
    else if kind == 30 or kind == 31 or kind == 35
        1
    else if kind == 32 or kind == 33 or kind == 34
        -1
    else
        0

f_levelDisplayText(int kind, int dir, string txt) =>
    if kind == 1
        txt == "BUY TJL1" or txt == "SELL TJL1" ? txt : dir == 1 ? "BUY TJL1" : "SELL TJL1"
    else if kind == 2
        txt == "BUY TJL2" or txt == "SELL TJL2" ? txt : dir == 1 ? "BUY TJL2" : "SELL TJL2"
    else
        txt

f_analyzerSlot(string txt) =>
    if txt == "BUY TJL1"
        0
    else if txt == "BUY TJL2"
        1
    else if txt == "SELL TJL1"
        2
    else if txt == "SELL TJL2"
        3
    else if txt == "SBR"
        4
    else if txt == "RBS"
        5
    else if txt == "DT"
        6
    else if txt == "DB"
        7
    else if txt == "BUY QML"
        8
    else if txt == "SELL QML"
        9
    else if txt == "ISS 4"
        10
    else if txt == "D-CHOCH SBR"
        11
    else if txt == "D-CHOCH RBS"
        12
    else if txt == "D-CHOCH DT"
        13
    else if txt == "D-CHOCH DB"
        14
    else if txt == "D-CHOCH SELL QML"
        15
    else if txt == "D-CHOCH BUY QML"
        16
    else
        -1

f_analyzerLabel(int slot) =>
    switch slot
        0 => "BUY TJL1"
        1 => "BUY TJL2"
        2 => "SELL TJL1"
        3 => "SELL TJL2"
        4 => "SBR"
        5 => "RBS"
        6 => "DT"
        7 => "DB"
        8 => "BUY QML"
        9 => "SELL QML"
        10 => "ISS 4"
        11 => "D-CHOCH SBR"
        12 => "D-CHOCH RBS"
        13 => "D-CHOCH DT"
        14 => "D-CHOCH DB"
        15 => "D-CHOCH SELL QML"
        16 => "D-CHOCH BUY QML"
        => ""

f_analyzerShowSlot(int slot) =>
    switch slot
        0 => inpAnalyzerShowBuyTJL1
        1 => inpAnalyzerShowBuyTJL2
        2 => inpAnalyzerShowSellTJL1
        3 => inpAnalyzerShowSellTJL2
        4 => inpAnalyzerShowSBR
        5 => inpAnalyzerShowRBS
        6 => inpAnalyzerShowDT
        7 => inpAnalyzerShowDB
        8 => inpAnalyzerShowBuyQML
        9 => inpAnalyzerShowSellQML
        10 => inpAnalyzerShowISS4
        11 => inpAnalyzerShowBestSBR
        12 => inpAnalyzerShowBestRBS
        13 => inpAnalyzerShowBestDT
        14 => inpAnalyzerShowBestDB
        15 => inpAnalyzerShowBestBuyQML
        16 => inpAnalyzerShowBestSellQML
        => false

f_analyzerRateText(int wins, int losses) =>
    done = wins + losses
    done > 0 ? str.tostring((wins * 100.0) / done, "#.##") + "%" : "n/a"

f_analyzerPipSize() =>
    inpAnalyzerPipMode == "Custom" ? inpAnalyzerCustomPipSize : syminfo.type == "forex" ? syminfo.mintick * 10.0 : syminfo.mintick

f_analyzerBothHitResult(int dir, float o, float h, float l) =>
    highFirst = math.abs(o - h) < math.abs(o - l)
    int result = 0
    if dir == 1
        result := highFirst ? 1 : -1
    else
        result := highFirst ? -1 : 1
    result

f_analyzerResolveResult(int dir, float targetPrice, float lossPrice, bool chartWin, bool chartLoss, float rOpen, float rHigh, float rLow) =>
    int result = 0
    if chartWin and not chartLoss
        result := 1
    else if chartLoss and not chartWin
        result := -1
    else if chartWin and chartLoss
        result := f_analyzerBothHitResult(dir, rOpen, rHigh, rLow)
    result

f_bestAnalyzerSlot(array<int> wins, array<int> losses) =>
    int bestSlot = -1
    float bestRate = na
    for i = 0 to 16
        w = array.get(wins, i)
        l = array.get(losses, i)
        done = w + l
        if f_analyzerShowSlot(i) and done >= inpAnalyzerMinDone
            rate = (w * 1.0) / done
            if na(bestRate) or rate > bestRate
                bestRate := rate
                bestSlot := i
    bestSlot

f_updateLevelAnalyzer(Level lv, float rOpen, float rClose, float rHigh, float rLow, int barNum, array<int> tests, array<int> wins, array<int> losses) =>
    slot = f_analyzerSlot(lv.txt)
    if inpShowLevelAnalyzer and slot >= 0 and lv.dir != 0
        targetMove = inpAnalyzerTargetPips * f_analyzerPipSize()
        lossMove = inpAnalyzerLossPips * f_analyzerPipSize()
        tapped = f_isTapped(rClose, rHigh, rLow, lv.top, lv.bot)
        if not lv.anaStarted and barNum > lv.bornBar and tapped
            lv.anaStarted := true
            lv.anaWaitingConfirm := false
            lv.anaActive := true
            lv.anaStartBar := barNum
            lv.anaTargetPrice := lv.dir == 1 ? rClose + targetMove : rClose - targetMove
            lv.anaLossPrice := lv.dir == 1 ? rLow - lossMove : rHigh + lossMove
            array.set(tests, slot, array.get(tests, slot) + 1)
        if lv.anaActive and not na(lv.anaTargetPrice) and not na(lv.anaLossPrice)
            win = lv.dir == 1 ? rHigh >= lv.anaTargetPrice : rLow <= lv.anaTargetPrice
            loss = lv.dir == 1 ? rLow <= lv.anaLossPrice : rHigh >= lv.anaLossPrice
            result = f_analyzerResolveResult(lv.dir, lv.anaTargetPrice, lv.anaLossPrice, win, loss, rOpen, rHigh, rLow)
            if result == -1
                array.set(losses, slot, array.get(losses, slot) + 1)
                lv.anaActive := false
            else if result == 1
                array.set(wins, slot, array.get(wins, slot) + 1)
                lv.anaActive := false
    lv

f_levelTextHAlign() =>
    if inpLevelTextHPos == "Left"
        text.align_left
    else if inpLevelTextHPos == "Right"
        text.align_right
    else
        text.align_center

f_levelTextVAlign() =>
    if inpLevelTextVPos == "Top"
        text.align_top
    else if inpLevelTextVPos == "Bottom"
        text.align_bottom
    else
        text.align_center

f_applyLevelText(box bx, string txt, color col) =>
    box.set_text(bx, txt)
    box.set_text_color(bx, col)
    box.set_text_size(bx, size.small)
    box.set_text_halign(bx, f_levelTextHAlign())
    box.set_text_valign(bx, f_levelTextVAlign())

f_bestLevelText(int kind, int dir) =>
    if kind == 3
        "D-CHOCH SBR"
    else if kind == 4
        "D-CHOCH RBS"
    else if kind == 5
        "D-CHOCH DT"
    else if kind == 6
        "D-CHOCH DB"
    else if kind == 7 and dir == 1
        "D-CHOCH SELL QML"
    else if kind == 7 and dir == -1
        "D-CHOCH BUY QML"
    else
        "D-CHOCH QML"

f_bestLevelColor(int kind, color srcCol) =>
    kind == 7 ? inpBestQMLColor : srcCol

f_promoteLastChochLevelsToBest(array<Level> lvs, int qmlLeft) =>
    if not na(qmlLeft) and array.size(lvs) > 0
        int srcBornBar = na
        for i = array.size(lvs) - 1 to 0
            lv = array.get(lvs, i)
            if lv.kind == 7 and not lv.deleted and lv.left == qmlLeft
                srcBornBar := lv.bornBar
                break
        if not na(srcBornBar)
            for i = array.size(lvs) - 1 to 0
                srcLv = array.get(lvs, i)
                if srcLv.kind >= 3 and srcLv.kind <= 7 and not srcLv.deleted and srcLv.bornBar == srcBornBar
                    bestTxt = f_bestLevelText(srcLv.kind, srcLv.dir)
                    bestCol = f_bestLevelColor(srcLv.kind, srcLv.col)
                    srcLv.active := true
                    srcLv.right := bar_index
                    srcLv.bornBar := bar_index
                    srcLv.stopReady := false
                    srcLv.stopReadyBar := 0
                    srcLv.anaStarted := false
                    srcLv.anaActive := false
                    srcLv.anaStartBar := 0
                    srcLv.anaWaitingConfirm := false
                    srcLv.anaTargetPrice := na
                    srcLv.anaLossPrice := na
                    srcLv.txt := ""
                    if not na(srcLv.bx)
                        box.delete(srcLv.bx)
                        srcLv.bx := na
                    srcLv.deleted := true
                    srcLv.active  := false
                    if not na(srcLv.lb)
                        label.delete(srcLv.lb)
                        srcLv.lb := na
                    array.set(lvs, i, srcLv)

                    bool bestFound = false
                    for j = array.size(lvs) - 1 to 0
                        foundBestLv = array.get(lvs, j)
                        if foundBestLv.kind == 8 and not foundBestLv.deleted and foundBestLv.left == srcLv.left and foundBestLv.top == srcLv.top and foundBestLv.bot == srcLv.bot and foundBestLv.txt == bestTxt
                            foundBestLv.active := true
                            foundBestLv.right := bar_index
                            foundBestLv.bornBar := bar_index
                            foundBestLv.stopReady := false
                            foundBestLv.stopReadyBar := 0
                            foundBestLv.col := bestCol
                            foundBestLv.txt := bestTxt
                            foundBestLv.anaStarted := false
                            foundBestLv.anaActive := false
                            foundBestLv.anaStartBar := 0
                            foundBestLv.anaWaitingConfirm := false
                            foundBestLv.anaTargetPrice := na
                            foundBestLv.anaLossPrice := na
                            if not na(foundBestLv.bx)
                                box.delete(foundBestLv.bx)
                                foundBestLv.bx := na
                                bestSafeLeft = math.max(foundBestLv.left, bar_index - 4000)
                                foundBestLv.bx := box.new(bestSafeLeft, foundBestLv.top, bar_index, foundBestLv.bot, xloc=xloc.bar_index, border_color=bestCol, bgcolor=color.new(bestCol, 80), text=bestTxt, text_color=bestCol, text_size=size.small, text_halign=f_levelTextHAlign(), text_valign=f_levelTextVAlign())
                            if not na(foundBestLv.lb)
                                label.delete(foundBestLv.lb)
                                foundBestLv.lb := na
                            array.set(lvs, j, foundBestLv)
                            bestFound := true
                            break
                    if not bestFound
                        newBestLv = Level.new(srcLv.left, bar_index, srcLv.top, srcLv.bot, bestCol, bestTxt, 8, srcLv.dir, true, false, false, 0, bar_index, na, na, false, false, 0, false, na, na)
                        array.push(lvs, newBestLv)

f_addLevel(array<Level> lvs, int left_, float o, float c, float h, float l,
           bool isHigh, color col, string txt, int kind, int bornBar, int right_) =>
    [top_, bot_] = f_candleZone(o, c, h, l, isHigh)
    dir_ = f_levelDir(kind, isHigh)
    lv = Level.new(left_, right_, top_, bot_, col, f_levelDisplayText(kind, dir_, txt), kind, dir_, true, false, false, 0, bornBar, na, na, false, false, 0, false, na, na)
    array.push(lvs, lv)

f_addLevelFromBar(array<Level> lvs, int leftBar, int srcBar, bool isHigh, color col, string txt, int kind, int bornBar, int rightBar) =>
    off = bar_index - srcBar
    if off >= 0
        [top_, bot_] = f_candleZone(open[off], close[off], high[off], low[off], isHigh)
        dir_ = f_levelDir(kind, isHigh)
        lv = Level.new(leftBar, rightBar, top_, bot_, col, f_levelDisplayText(kind, dir_, txt), kind, dir_, true, false, false, 0, bornBar, na, na, false, false, 0, false, na, na)
        array.push(lvs, lv)

f_addLevelFromBarReady(array<Level> lvs, int leftBar, int srcBar, bool isHigh, color col, string txt, int kind, int bornBar, int rightBar, int readyBar) =>
    off = bar_index - srcBar
    if off >= 0
        [top_, bot_] = f_candleZone(open[off], close[off], high[off], low[off], isHigh)
        dir_ = f_levelDir(kind, isHigh)
        lv = Level.new(leftBar, rightBar, top_, bot_, col, f_levelDisplayText(kind, dir_, txt), kind, dir_, true, false, true, readyBar, bornBar, na, na, false, false, 0, false, na, na)
        array.push(lvs, lv)

f_deleteLatestTJL1ByLeft(array<Level> lvs, int srcLeftBar) =>
    if array.size(lvs) > 0
        for i = array.size(lvs) - 1 to 0
            lv = array.get(lvs, i)
            if not lv.deleted and lv.active and lv.kind == 1 and lv.left == srcLeftBar
                lv.deleted := true
                lv.active  := false
                if not na(lv.bx)
                    box.delete(lv.bx)
                if not na(lv.lb)
                    label.delete(lv.lb)
                array.set(lvs, i, lv)
                break

f_freezePreviousCHOCHLevels(array<Level> lvs) =>
    if array.size(lvs) > 0
        for i = 0 to array.size(lvs) - 1
            lv = array.get(lvs, i)
            if not lv.deleted and lv.active and lv.kind >= 3 and lv.kind <= 7
                lv.active := false
                array.set(lvs, i, lv)

f_updateLevels(array<Level> lvs, float rOpen, float rClose, float rHigh, float rLow, int barNum, array<int> anaTests, array<int> anaWins, array<int> anaLosses) =>
    if array.size(lvs) > 0
        for i = 0 to array.size(lvs) - 1
            lv = array.get(lvs, i)
            if lv.deleted
                continue
            lv := f_updateLevelAnalyzer(lv, rOpen, rClose, rHigh, rLow, barNum, anaTests, anaWins, anaLosses)
            if not lv.active
                array.set(lvs, i, lv)
                continue
            lv.right := barNum
            issWickLevel = lv.kind == 30 or lv.kind == 31 or lv.kind == 32 or lv.kind == 33 or lv.kind == 34 or lv.kind == 35
            if issWickLevel
                if inpStopISS34ByWickTap and barNum > lv.bornBar
                    crossed = lv.dir == 1 ? rClose > lv.top : rClose < lv.bot
                    if not lv.stopReady and crossed
                        lv.stopReady := true
                        lv.stopReadyBar := barNum
                    if lv.stopReady and barNum > lv.stopReadyBar
                        issTapped = rHigh >= lv.bot and rLow <= lv.top
                        if issTapped
                            lv.active := false
                            lv.right := barNum
            else
                if inpStopOnTap and barNum > lv.bornBar
                    stdTapped = f_isTapped(rClose, rHigh, rLow, lv.top, lv.bot)
                    if stdTapped
                        lv.active := false
                        lv.right := barNum
            array.set(lvs, i, lv)

f_trimLevels(array<Level> lvs) =>
    if array.size(lvs) > 0
        kept = 0
        for i = array.size(lvs) - 1 to 0
            lv = array.get(lvs, i)
            if lv.deleted
                continue
            kept += 1
            if kept > inpMaxLiveLevels
                lv.deleted := true
                if not na(lv.bx)
                    box.delete(lv.bx)
                if not na(lv.lb)
                    label.delete(lv.lb)
                array.set(lvs, i, lv)

f_compactDeletedLevels(array<Level> lvs) =>
    if array.size(lvs) > 0
        for i = array.size(lvs) - 1 to 0
            lv = array.get(lvs, i)
            if lv.deleted
                array.remove(lvs, i)

f_compactDeletedFVG(array<FVGLevel> arr) =>
    if array.size(arr) > 0
        for i = array.size(arr) - 1 to 0
            fv = array.get(arr, i)
            if fv.deleted
                array.remove(arr, i)

f_compactDeletedOB(array<OBLevel> arr) =>
    if array.size(arr) > 0
        for i = array.size(arr) - 1 to 0
            ob = array.get(arr, i)
            if ob.deleted
                array.remove(arr, i)

f_pushLine(array<line> arr, line ln) =>
    array.push(arr, ln)
    if array.size(arr) > inpMaxLines
        old = array.shift(arr)
        line.delete(old)

f_pushLabel(array<label> arr, label lb) =>
    array.push(arr, lb)
    if array.size(arr) > inpMaxLabels
        old = array.shift(arr)
        label.delete(old)

f_shouldShowLevel(int kind, string txt) =>
    isAPlus = kind == 2 or kind == 7 or kind == 31 or kind == 33 or (kind == 8 and str.contains(txt, "QML"))
    if inpShowOnlyAPlus and not isAPlus
        false
    else if kind == 1
        inpShowTJL1
    else if kind == 2
        inpShowTJL2
    else if kind == 3
        inpShowSBR
    else if kind == 4
        inpShowRBS
    else if kind == 5
        inpShowDT
    else if kind == 6
        inpShowDB
    else if kind == 7
        inpShowQML
    else if kind == 8
        inpShowBestQML
    else if kind == 29
        inpShowISS1
    else if kind == 34 or kind == 35
        inpShowISS2
    else if kind == 30 or kind == 32
        inpShowISS3
    else if kind == 31 or kind == 33
        inpShowISS4
    else
        true

f_mtfTrendCalc() =>
    var int mtfTrend = 0
    var int mtfStructureTrend = 0
    var int mtfPhase = 1
    var int mtfStartBarIndex = na
    var float mtfRunHigh = na
    var int mtfRunHighBar = na
    var float mtfRunLow = na
    var int mtfRunLowBar = na
    var float mtfLastCH = na
    var bool mtfLastCHSet = false
    var float mtfLastCL = na
    var bool mtfLastCLSet = false
    var int mtfTjl1Bar = na
    var bool mtfTjl1Set = false
    var int mtfLastChochSide = 0
    var bool mtfIssOrTjlSinceChoch = false
    var int mtfBullIssState = 0
    var bool mtfBullIssBaseConfirmed = false
    var float mtfBullIssBaseLow = na
    var int mtfBullIssBaseLowBar = na
    var float mtfBullIssRunHigh = na
    var int mtfBullIssRunHighBar = na
    var float mtfBullIss1Level = na
    var int mtfBullIss1Bar = na
    var float mtfBullIss2Level = na
    var int mtfBullIss2Bar = na
    var float mtfBullIssAfterBreakRunHigh = na
    var int mtfBullIssAfterBreakRunHighBar = na
    var float mtfBullIssAfterBreakRunLow = na
    var int mtfBullIssAfterBreakRunLowBar = na
    var int mtfBearIssState = 0
    var bool mtfBearIssBaseConfirmed = false
    var float mtfBearIssBaseHigh = na
    var int mtfBearIssBaseHighBar = na
    var float mtfBearIssRunLow = na
    var int mtfBearIssRunLowBar = na
    var float mtfBearIss1Level = na
    var int mtfBearIss1Bar = na
    var float mtfBearIss2Level = na
    var int mtfBearIss2Bar = na
    var float mtfBearIssAfterBreakRunLow = na
    var int mtfBearIssAfterBreakRunLowBar = na
    var float mtfBearIssAfterBreakRunHigh = na
    var int mtfBearIssAfterBreakRunHighBar = na

    if na(mtfStartBarIndex) and time >= inpStartTime
        mtfStartBarIndex := bar_index

    mtfInWindow = not na(mtfStartBarIndex) and bar_index >= mtfStartBarIndex and (bar_index - mtfStartBarIndex) <= inpMaxBars
    mtfEnoughBars = bar_index >= 2
    bool mtfQmlAlert = false
    bool mtfTjl2Alert = false
    bool mtfIss4Alert = false
    bool mtfDChochAlert = false

    if mtfInWindow and mtfEnoughBars
        if na(mtfRunHigh) or high > mtfRunHigh
            mtfRunHigh := high
            mtfRunHighBar := bar_index
        if na(mtfRunLow) or low < mtfRunLow
            mtfRunLow := low
            mtfRunLowBar := bar_index

        mtfRedP = close[1] < open[1]
        mtfGreenP = close[1] > open[1]
        mtfRedC = close < open
        mtfGreenC = close > open

        mtfBearishIssShift = mtfRedP and mtfRedC and close < low[1]
        mtfBullishIssShift = mtfGreenP and mtfGreenC and close > high[1]

        mtfBullRetracement = mtfBearishIssShift
        mtfBearRetracement = mtfBullishIssShift

        mtfBearChoch = mtfTrend == 1 and mtfLastCLSet and mtfRedP and close[1] < mtfLastCL and close < mtfLastCL
        mtfBullChoch = mtfTrend == -1 and mtfLastCHSet and mtfGreenP and close[1] > mtfLastCH and close > mtfLastCH

        if mtfBearChoch
            mtfBearDualChochHit = mtfLastChochSide == -1 and not mtfIssOrTjlSinceChoch
            if mtfBearDualChochHit
                mtfDChochAlert := true
            else if mtfTjl1Set
                mtfQmlAlert := true
            mtfTrend := -1
            mtfStructureTrend := -1
            mtfPhase := 1
            mtfLastCH := mtfRunHigh
            mtfLastCHSet := true
            mtfLastChochSide := 1
            mtfIssOrTjlSinceChoch := false
            mtfRunHigh := high
            mtfRunHighBar := bar_index
            mtfRunLow := low
            mtfRunLowBar := bar_index
            mtfBullIssState := 1
            mtfBullIssBaseConfirmed := false
            mtfBullIssBaseLow := low
            mtfBullIssBaseLowBar := bar_index
            mtfBullIssRunHigh := high
            mtfBullIssRunHighBar := bar_index
            mtfBullIss1Level := na
            mtfBullIss1Bar := na
            mtfBullIss2Level := na
            mtfBullIss2Bar := na
            mtfBullIssAfterBreakRunHigh := na
            mtfBullIssAfterBreakRunHighBar := na
            mtfBullIssAfterBreakRunLow := na
            mtfBullIssAfterBreakRunLowBar := na
            mtfBearIssState := 0
            mtfBearIssBaseConfirmed := false
            mtfBearIssBaseHigh := na
            mtfBearIssBaseHighBar := na
            mtfBearIssRunLow := na
            mtfBearIssRunLowBar := na
            mtfBearIss1Level := na
            mtfBearIss1Bar := na
            mtfBearIss2Level := na
            mtfBearIss2Bar := na
            mtfBearIssAfterBreakRunLow := na
            mtfBearIssAfterBreakRunLowBar := na
            mtfBearIssAfterBreakRunHigh := na
            mtfBearIssAfterBreakRunHighBar := na
        else if mtfBullChoch
            mtfBullDualChochHit = mtfLastChochSide == 1 and not mtfIssOrTjlSinceChoch
            if mtfBullDualChochHit
                mtfDChochAlert := true
            else if mtfTjl1Set
                mtfQmlAlert := true
            mtfTrend := 1
            mtfStructureTrend := 1
            mtfPhase := 1
            mtfLastCL := mtfRunLow
            mtfLastCLSet := true
            mtfLastChochSide := -1
            mtfIssOrTjlSinceChoch := false
            mtfRunHigh := high
            mtfRunHighBar := bar_index
            mtfRunLow := low
            mtfRunLowBar := bar_index
            mtfBearIssState := 1
            mtfBearIssBaseConfirmed := false
            mtfBearIssBaseHigh := high
            mtfBearIssBaseHighBar := bar_index
            mtfBearIssRunLow := low
            mtfBearIssRunLowBar := bar_index
            mtfBearIss1Level := na
            mtfBearIss1Bar := na
            mtfBearIss2Level := na
            mtfBearIss2Bar := na
            mtfBearIssAfterBreakRunLow := na
            mtfBearIssAfterBreakRunLowBar := na
            mtfBearIssAfterBreakRunHigh := na
            mtfBearIssAfterBreakRunHighBar := na
            mtfBullIssState := 0
            mtfBullIssBaseConfirmed := false
            mtfBullIssBaseLow := na
            mtfBullIssBaseLowBar := na
            mtfBullIssRunHigh := na
            mtfBullIssRunHighBar := na
            mtfBullIss1Level := na
            mtfBullIss1Bar := na
            mtfBullIss2Level := na
            mtfBullIss2Bar := na
            mtfBullIssAfterBreakRunHigh := na
            mtfBullIssAfterBreakRunHighBar := na
            mtfBullIssAfterBreakRunLow := na
            mtfBullIssAfterBreakRunLowBar := na
        else
            if mtfTrend == 1 and mtfPhase == 2 and mtfLastCHSet and close > mtfLastCH
                mtfLastCL := mtfRunLow
                mtfLastCLSet := true
                mtfTjl1Bar := mtfRunHighBar
                mtfTjl1Set := true
                mtfTjl2Alert := true
                mtfIssOrTjlSinceChoch := true
                mtfStructureTrend := 1
                mtfPhase := 1
                mtfRunHigh := high
                mtfRunHighBar := bar_index
                mtfRunLow := low
                mtfRunLowBar := bar_index
                mtfBearIssState := 1
                mtfBearIssBaseConfirmed := false
                mtfBearIssBaseHigh := high
                mtfBearIssBaseHighBar := bar_index
                mtfBearIssRunLow := low
                mtfBearIssRunLowBar := bar_index
                mtfBearIss1Level := na
                mtfBearIss1Bar := na
                mtfBearIss2Level := na
                mtfBearIss2Bar := na
                mtfBearIssAfterBreakRunLow := na
                mtfBearIssAfterBreakRunLowBar := na
                mtfBearIssAfterBreakRunHigh := na
                mtfBearIssAfterBreakRunHighBar := na
                mtfBullIssState := 0
                mtfBullIssBaseConfirmed := false
                mtfBullIssBaseLow := na
                mtfBullIssBaseLowBar := na
                mtfBullIssRunHigh := na
                mtfBullIssRunHighBar := na
                mtfBullIss1Level := na
                mtfBullIss1Bar := na
                mtfBullIss2Level := na
                mtfBullIss2Bar := na
                mtfBullIssAfterBreakRunHigh := na
                mtfBullIssAfterBreakRunHighBar := na
                mtfBullIssAfterBreakRunLow := na
                mtfBullIssAfterBreakRunLowBar := na
            else if mtfTrend == -1 and mtfPhase == 2 and mtfLastCLSet and close < mtfLastCL
                mtfLastCH := mtfRunHigh
                mtfLastCHSet := true
                mtfTjl1Bar := mtfRunLowBar
                mtfTjl1Set := true
                mtfTjl2Alert := true
                mtfIssOrTjlSinceChoch := true
                mtfStructureTrend := -1
                mtfPhase := 1
                mtfRunHigh := high
                mtfRunHighBar := bar_index
                mtfRunLow := low
                mtfRunLowBar := bar_index
                mtfBullIssState := 1
                mtfBullIssBaseConfirmed := false
                mtfBullIssBaseLow := low
                mtfBullIssBaseLowBar := bar_index
                mtfBullIssRunHigh := high
                mtfBullIssRunHighBar := bar_index
                mtfBullIss1Level := na
                mtfBullIss1Bar := na
                mtfBullIss2Level := na
                mtfBullIss2Bar := na
                mtfBullIssAfterBreakRunHigh := na
                mtfBullIssAfterBreakRunHighBar := na
                mtfBullIssAfterBreakRunLow := na
                mtfBullIssAfterBreakRunLowBar := na
                mtfBearIssState := 0
                mtfBearIssBaseConfirmed := false
                mtfBearIssBaseHigh := na
                mtfBearIssBaseHighBar := na
                mtfBearIssRunLow := na
                mtfBearIssRunLowBar := na
                mtfBearIss1Level := na
                mtfBearIss1Bar := na
                mtfBearIss2Level := na
                mtfBearIss2Bar := na
                mtfBearIssAfterBreakRunLow := na
                mtfBearIssAfterBreakRunLowBar := na
                mtfBearIssAfterBreakRunHigh := na
                mtfBearIssAfterBreakRunHighBar := na
            else if mtfPhase == 1
                if mtfTrend != -1 and mtfBullRetracement
                    mtfLastCH := mtfRunHigh
                    mtfLastCHSet := true
                    mtfTrend := 1
                    mtfPhase := 2
                    if low < low[1]
                        mtfRunLow := low
                        mtfRunLowBar := bar_index
                    else
                        mtfRunLow := low[1]
                        mtfRunLowBar := bar_index - 1
                else if mtfTrend != 1 and mtfBearRetracement
                    mtfLastCL := mtfRunLow
                    mtfLastCLSet := true
                    mtfTrend := -1
                    mtfPhase := 2
                    if high > high[1]
                        mtfRunHigh := high
                        mtfRunHighBar := bar_index
                    else
                        mtfRunHigh := high[1]
                        mtfRunHighBar := bar_index - 1

        if inpEnableISS
            mtfBullIssInvalidated = mtfBullIssState >= 2 and not na(mtfBullIssBaseLow) and close < mtfBullIssBaseLow
            mtfBearIssInvalidated = mtfBearIssState >= 2 and not na(mtfBearIssBaseHigh) and close > mtfBearIssBaseHigh

            if mtfBullIssInvalidated
                mtfBullIssState := 0
                mtfBullIssBaseConfirmed := false
                mtfBullIssBaseLow := na
                mtfBullIssBaseLowBar := na
                mtfBullIssRunHigh := na
                mtfBullIssRunHighBar := na
                mtfBullIss1Level := na
                mtfBullIss1Bar := na
                mtfBullIss2Level := na
                mtfBullIss2Bar := na
                mtfBullIssAfterBreakRunHigh := na
                mtfBullIssAfterBreakRunHighBar := na
                mtfBullIssAfterBreakRunLow := na
                mtfBullIssAfterBreakRunLowBar := na
            else if mtfBullIssState == 1
                if na(mtfBullIssBaseLow) or low < mtfBullIssBaseLow
                    mtfBullIssBaseLow := low
                    mtfBullIssBaseLowBar := bar_index
                    mtfBullIssRunHigh := high
                    mtfBullIssRunHighBar := bar_index
                    mtfBullIssBaseConfirmed := false
                if not mtfBullIssBaseConfirmed
                    if mtfBullishIssShift
                        mtfBullIssBaseConfirmed := true
                        mtfBullIssRunHigh := high
                        mtfBullIssRunHighBar := bar_index
                else
                    if na(mtfBullIssRunHigh) or high > mtfBullIssRunHigh
                        mtfBullIssRunHigh := high
                        mtfBullIssRunHighBar := bar_index
                    if mtfBearishIssShift and not na(mtfBullIssRunHighBar) and mtfBullIssRunHighBar < bar_index
                        mtfBullIss1Level := mtfBullIssRunHigh
                        mtfBullIss1Bar := mtfBullIssRunHighBar
                        mtfBullIssState := 2
                        mtfBullIss2Level := low
                        mtfBullIss2Bar := bar_index
            else if mtfBullIssState == 2
                if low < mtfBullIss2Level
                    mtfBullIss2Level := low
                    mtfBullIss2Bar := bar_index
                if not na(mtfBullIss1Level) and close > mtfBullIss1Level
                    mtfBullIssAfterBreakRunHigh := high
                    mtfBullIssAfterBreakRunHighBar := bar_index
                    mtfBullIssAfterBreakRunLow := low
                    mtfBullIssAfterBreakRunLowBar := bar_index
                    mtfBullIssState := 3
            else if mtfBullIssState == 3
                if low < mtfBullIss2Level
                    mtfBullIss2Level := low
                    mtfBullIss2Bar := bar_index
                if na(mtfBullIssAfterBreakRunHigh) or high > mtfBullIssAfterBreakRunHigh
                    mtfBullIssAfterBreakRunHigh := high
                    mtfBullIssAfterBreakRunHighBar := bar_index
                    mtfBullIssAfterBreakRunLow := low
                    mtfBullIssAfterBreakRunLowBar := bar_index
                else if na(mtfBullIssAfterBreakRunLow) or low < mtfBullIssAfterBreakRunLow
                    mtfBullIssAfterBreakRunLow := low
                    mtfBullIssAfterBreakRunLowBar := bar_index
                if mtfBearishIssShift and not na(mtfBullIssAfterBreakRunHighBar) and not na(mtfBullIssAfterBreakRunLowBar)
                    if inpISSScenario == "1"
                        mtfBullIssAfterBreakRunLow := low
                        mtfBullIssAfterBreakRunLowBar := bar_index
                    mtfBullIssState := 4
            else if mtfBullIssState == 4
                if na(mtfBullIssAfterBreakRunLow) or low < mtfBullIssAfterBreakRunLow
                    mtfBullIssAfterBreakRunLow := low
                    mtfBullIssAfterBreakRunLowBar := bar_index
                
                if not na(mtfBullIssAfterBreakRunLow) and not na(mtfBullIss2Level) and mtfBullIssAfterBreakRunLow < mtfBullIss2Level
                    mtfBullIssState := 0
                    mtfBullIssBaseConfirmed := false
                    mtfBullIssBaseLow := na
                    mtfBullIssBaseLowBar := na
                    mtfBullIssRunHigh := na
                    mtfBullIssRunHighBar := na
                    mtfBullIss1Level := na
                    mtfBullIss1Bar := na
                    mtfBullIss2Level := na
                    mtfBullIss2Bar := na
                    mtfBullIssAfterBreakRunHigh := na
                    mtfBullIssAfterBreakRunHighBar := na
                    mtfBullIssAfterBreakRunLow := na
                    mtfBullIssAfterBreakRunLowBar := na
                
                if mtfBullIssState == 4 and not na(mtfBullIssAfterBreakRunHigh) and not na(mtfBullIssAfterBreakRunLowBar) and close > mtfBullIssAfterBreakRunHigh
                    mtfTrend := 1
                    mtfStructureTrend := 1
                    mtfPhase := 1
                    mtfTjl1Bar := mtfBullIssAfterBreakRunHighBar
                    mtfTjl1Set := true
                    mtfIss4Alert := true
                    mtfIssOrTjlSinceChoch := true
                    mtfBullIssState := 0
                    mtfBullIssBaseConfirmed := false
                    mtfBullIssBaseLow := na
                    mtfBullIssBaseLowBar := na
                    mtfBullIssRunHigh := na
                    mtfBullIssRunHighBar := na
                    mtfBullIss1Level := na
                    mtfBullIss1Bar := na
                    mtfBullIss2Level := na
                    mtfBullIss2Bar := na
                    mtfBullIssAfterBreakRunHigh := na
                    mtfBullIssAfterBreakRunHighBar := na
                    mtfBullIssAfterBreakRunLow := na
                    mtfBullIssAfterBreakRunLowBar := na
                    mtfBearIssState := 0
                    mtfBearIssBaseConfirmed := false
                    mtfBearIssBaseHigh := na
                    mtfBearIssBaseHighBar := na
                    mtfBearIssRunLow := na
                    mtfBearIssRunLowBar := na
                    mtfBearIss1Level := na
                    mtfBearIss1Bar := na
                    mtfBearIss2Level := na
                    mtfBearIss2Bar := na
                    mtfBearIssAfterBreakRunLow := na
                    mtfBearIssAfterBreakRunLowBar := na
                    mtfBearIssAfterBreakRunHigh := na
                    mtfBearIssAfterBreakRunHighBar := na

            if mtfBearIssInvalidated
                mtfBearIssState := 0
                mtfBearIssBaseConfirmed := false
                mtfBearIssBaseHigh := na
                mtfBearIssBaseHighBar := na
                mtfBearIssRunLow := na
                mtfBearIssRunLowBar := na
                mtfBearIss1Level := na
                mtfBearIss1Bar := na
                mtfBearIss2Level := na
                mtfBearIss2Bar := na
                mtfBearIssAfterBreakRunLow := na
                mtfBearIssAfterBreakRunLowBar := na
                mtfBearIssAfterBreakRunHigh := na
                mtfBearIssAfterBreakRunHighBar := na
            else if mtfBearIssState == 1
                if na(mtfBearIssBaseHigh) or high > mtfBearIssBaseHigh
                    mtfBearIssBaseHigh := high
                    mtfBearIssBaseHighBar := bar_index
                    mtfBearIssRunLow := low
                    mtfBearIssRunLowBar := bar_index
                    mtfBearIssBaseConfirmed := false
                if not mtfBearIssBaseConfirmed
                    if mtfBearishIssShift
                        mtfBearIssBaseConfirmed := true
                        mtfBearIssRunLow := low
                        mtfBearIssRunLowBar := bar_index
                else
                    if na(mtfBearIssRunLow) or low < mtfBearIssRunLow
                        mtfBearIssRunLow := low
                        mtfBearIssRunLowBar := bar_index
                    if mtfBullishIssShift and not na(mtfBearIssRunLowBar) and mtfBearIssRunLowBar < bar_index
                        mtfBearIss1Level := mtfBearIssRunLow
                        mtfBearIss1Bar := mtfBearIssRunLowBar
                        mtfBearIssState := 2
                        mtfBearIss2Level := high
                        mtfBearIss2Bar := bar_index
            else if mtfBearIssState == 2
                if high > mtfBearIss2Level
                    mtfBearIss2Level := high
                    mtfBearIss2Bar := bar_index
                if not na(mtfBearIss1Level) and close < mtfBearIss1Level
                    mtfBearIssAfterBreakRunLow := low
                    mtfBearIssAfterBreakRunLowBar := bar_index
                    mtfBearIssAfterBreakRunHigh := high
                    mtfBearIssAfterBreakRunHighBar := bar_index
                    mtfBearIssState := 3
            else if mtfBearIssState == 3
                if high > mtfBearIss2Level
                    mtfBearIss2Level := high
                    mtfBearIss2Bar := bar_index
                if na(mtfBearIssAfterBreakRunLow) or low < mtfBearIssAfterBreakRunLow
                    mtfBearIssAfterBreakRunLow := low
                    mtfBearIssAfterBreakRunLowBar := bar_index
                    mtfBearIssAfterBreakRunHigh := high
                    mtfBearIssAfterBreakRunHighBar := bar_index
                else if na(mtfBearIssAfterBreakRunHigh) or high > mtfBearIssAfterBreakRunHigh
                    mtfBearIssAfterBreakRunHigh := high
                    mtfBearIssAfterBreakRunHighBar := bar_index
                if mtfBullishIssShift and not na(mtfBearIssAfterBreakRunLowBar) and not na(mtfBearIssAfterBreakRunHighBar)
                    if inpISSScenario == "1"
                        mtfBearIssAfterBreakRunHigh := high
                        mtfBearIssAfterBreakRunHighBar := bar_index
                    mtfBearIssState := 4
            else if mtfBearIssState == 4
                if na(mtfBearIssAfterBreakRunHigh) or high > mtfBearIssAfterBreakRunHigh
                    mtfBearIssAfterBreakRunHigh := high
                    mtfBearIssAfterBreakRunHighBar := bar_index
                
                if not na(mtfBearIssAfterBreakRunHigh) and not na(mtfBearIss2Level) and mtfBearIssAfterBreakRunHigh > mtfBearIss2Level
                    mtfBearIssState := 0
                    mtfBearIssBaseConfirmed := false
                    mtfBearIssBaseHigh := na
                    mtfBearIssBaseHighBar := na
                    mtfBearIssRunLow := na
                    mtfBearIssRunLowBar := na
                    mtfBearIss1Level := na
                    mtfBearIss1Bar := na
                    mtfBearIss2Level := na
                    mtfBearIss2Bar := na
                    mtfBearIssAfterBreakRunLow := na
                    mtfBearIssAfterBreakRunLowBar := na
                    mtfBearIssAfterBreakRunHigh := na
                    mtfBearIssAfterBreakRunHighBar := na
                
                if mtfBearIssState == 4 and not na(mtfBearIssAfterBreakRunLow) and not na(mtfBearIssAfterBreakRunHighBar) and close < mtfBearIssAfterBreakRunLow
                    mtfTrend := -1
                    mtfStructureTrend := -1
                    mtfPhase := 1
                    mtfTjl1Bar := mtfBearIssAfterBreakRunLowBar
                    mtfTjl1Set := true
                    mtfIss4Alert := true
                    mtfIssOrTjlSinceChoch := true
                    mtfBearIssState := 0
                    mtfBearIssBaseConfirmed := false
                    mtfBearIssBaseHigh := na
                    mtfBearIssBaseHighBar := na
                    mtfBearIssRunLow := na
                    mtfBearIssRunLowBar := na
                    mtfBearIss1Level := na
                    mtfBearIss1Bar := na
                    mtfBearIss2Level := na
                    mtfBearIss2Bar := na
                    mtfBearIssAfterBreakRunLow := na
                    mtfBearIssAfterBreakRunLowBar := na
                    mtfBearIssAfterBreakRunHigh := na
                    mtfBearIssAfterBreakRunHighBar := na
                    mtfBullIssState := 0
                    mtfBullIssBaseConfirmed := false
                    mtfBullIssBaseLow := na
                    mtfBullIssBaseLowBar := na
                    mtfBullIssRunHigh := na
                    mtfBullIssRunHighBar := na
                    mtfBullIss1Level := na
                    mtfBullIss1Bar := na
                    mtfBullIss2Level := na
                    mtfBullIss2Bar := na
                    mtfBullIssAfterBreakRunHigh := na
                    mtfBullIssAfterBreakRunHighBar := na
                    mtfBullIssAfterBreakRunLow := na
                    mtfBullIssAfterBreakRunLowBar := na

    [mtfStructureTrend, mtfQmlAlert, mtfTjl2Alert, mtfIss4Alert, mtfDChochAlert]

f_dashTfLabel(string tf) =>
    switch tf
        "1" => "1m"
        "3" => "3m"
        "5" => "5m"
        "15" => "15m"
        "30" => "30m"
        "45" => "45m"
        "60" => "1H"
        "120" => "2H"
        "180" => "3H"
        "240" => "4H"
        "D" => "1D"
        "1D" => "1D"
        "W" => "1W"
        "1W" => "1W"
        "M" => "1M"
        "1M" => "1M"
        => tf

f_dashTrendText(int dir) =>
    dir == 1 ? "BULLISH" : dir == -1 ? "BEARISH" : "NEUTRAL"

f_dashTrendColor(int dir) =>
    dir == 1 ? color.green : dir == -1 ? color.red : color.gray



// ==================================================================
// PERSISTENT STATE
// ==================================================================
var array<Level>    levels      = array.new<Level>()
var array<line>      drawnLines  = array.new<line>()
var array<label>    drawnLabels = array.new<label>()
var array<FVGLevel> fvgLevels   = array.new<FVGLevel>()
var array<OBLevel>  obLevels    = array.new<OBLevel>()
var line bullIssBos1Line = na
var line bearIssBos1Line = na

var int   trend = 0
var int   phase = 1
var table tfDashboard = table.new(position.top_right, 2, 14, border_width=1)

var table levelAnalyzerTable = table.new(position.bottom_right, 5, 19, border_width=1)

var array<int> levelAnalyzerTests  = array.new<int>(17, 0)
var array<int> levelAnalyzerWins   = array.new<int>(17, 0)
var array<int> levelAnalyzerLosses = array.new<int>(17, 0)

var Snap runHigh = f_initSnap()
var Snap runLow  = f_initSnap()
var Snap lastCH  = f_initSnap()
var Snap lastCL  = f_initSnap()
var Snap tjl1    = f_initSnap()
var Snap tjl2    = f_initSnap()
var bool runHighSet = false
var bool runLowSet  = false
var bool lastCHSet  = false
var bool lastCLSet  = false
var bool tjl1Set    = false

var int bullIssState = 0
var bool bullIssBaseConfirmed = false
var float bullIssBaseLow = na
var int bullIssBaseLowBar = na
var float bullIssRunHigh = na
var int bullIssRunHighBar = na
var float bullIss1Level = na
var int bullIss1Bar = na
var float bullIss2Level = na
var int bullIss2Bar = na
var float bullIssAfterBreakRunHigh = na
var int bullIssAfterBreakRunHighBar = na
var float bullIssAfterBreakRunLow = na
var int bullIssAfterBreakRunLowBar = na
var array<int> bullIssBosBars = array.new<int>()
var array<float> bullIssBosLvls = array.new<float>()

var int bearIssState = 0
var bool bearIssBaseConfirmed = false
var float bearIssBaseHigh = na
var int bearIssBaseHighBar = na
var float bearIssRunLow = na
var int bearIssRunLowBar = na
var float bearIss1Level = na
var int bearIss1Bar = na
var float bearIss2Level = na
var int bearIss2Bar = na
var float bearIssAfterBreakRunLow = na
var int bearIssAfterBreakRunLowBar = na
var float bearIssAfterBreakRunHigh = na
var int bearIssAfterBreakRunHighBar = na
var array<int> bearIssBosBars = array.new<int>()
var array<float> bearIssBosLvls = array.new<float>()

var int lastChochSide = 0
var bool issOrTjlSinceChoch = false
var int lastQmlLeft = na
var float lastQmlTop = na
var float lastQmlBot = na
var color lastQmlCol = na

var int startBarIndex = na
if na(startBarIndex) and time >= inpStartTime
    startBarIndex := bar_index
inWindow   = not na(startBarIndex) and bar_index >= startBarIndex and (bar_index - startBarIndex) <= inpMaxBars
enoughBars = bar_index >= 2

// ==================================================================
// KILL ZONES
// ==================================================================
utcH   = hour(time,   "UTC")
utcM   = minute(time, "UTC")
utcTot = utcH * 60 + utcM
isLondonKZ = utcTot >= 390 and utcTot < 480
isNYKZ     = utcTot >= 750 and utcTot < 870
bgcolor(showStructureMarking and inpShowKZ and isLondonKZ ? inpLondonColor : na, title="London Kill Zone")
bgcolor(showStructureMarking and inpShowKZ and isNYKZ     ? inpNYColor     : na, title="New York Kill Zone")

// ==================================================================
// MAIN LOGIC
// ==================================================================
if showStructureMarking
    if inWindow and enoughBars
        f_updateLevels(levels, open, close, high, low, bar_index, levelAnalyzerTests, levelAnalyzerWins, levelAnalyzerLosses)
    
        if inpShowFVG and array.size(fvgLevels) > 0
            for i = 0 to array.size(fvgLevels) - 1
                fv = array.get(fvgLevels, i)
                if fv.deleted
                    continue
                fv.right := bar_index
                if inpFVGDeleteOnTap and bar_index > fv.left
                    fvTapped = inpTapSource == tapByClose ? (close >= fv.bot and close <= fv.top) : (low <= fv.top and high >= fv.bot)
                    if fvTapped
                        fv.active  := false
                        fv.deleted := true
                        if not na(fv.bx)
                            box.delete(fv.bx)
                        array.set(fvgLevels, i, fv)
                        continue
                if not na(fv.bx)
                    box.set_right(fv.bx, bar_index)
                array.set(fvgLevels, i, fv)
    
        if inpShowOB and array.size(obLevels) > 0
            for i = 0 to array.size(obLevels) - 1
                ob = array.get(obLevels, i)
                if ob.deleted
                    continue
                ob.right := bar_index
                if inpOBDeleteOnTap and bar_index > ob.left
                    obTapped = inpTapSource == tapByClose ? (close >= ob.bot and close <= ob.top) : (low <= ob.top and high >= ob.bot)
                    if obTapped
                        ob.active  := false
                        ob.deleted := true
                        if not na(ob.bx)
                            box.delete(ob.bx)
                        array.set(obLevels, i, ob)
                        continue
                if not na(ob.bx)
                    box.set_right(ob.bx, bar_index)
                array.set(obLevels, i, ob)
    
        if not runHighSet or high > runHigh.lvl
            runHigh    := f_makeSnapCurrent(high)
            runHighSet := true
        if not runLowSet or low < runLow.lvl
            runLow     := f_makeSnapCurrent(low)
            runLowSet := true
    
        redP   = close[1] < open[1]
        greenP = close[1] > open[1]
        redC   = close < open
        greenC = close > open
    
        bearishIssShift = redP and redC and close < low[1]
        bullishIssShift = greenP and greenC and close > high[1]
    
        bullRetracement = bearishIssShift
        bearRetracement = bullishIssShift
    
        bearChoch = trend ==  1 and lastCLSet and redP   and close[1] < lastCL.lvl and close < lastCL.lvl
        bullChoch = trend == -1 and lastCHSet and greenP and close[1] > lastCH.lvl and close > lastCH.lvl
    
        if bearChoch
            dualChochHit = lastChochSide == -1 and not issOrTjlSinceChoch
            if inpShowCHOCH
                ln = line.new(lastCL.bar, lastCL.lvl, bar_index, lastCL.lvl, xloc=xloc.bar_index, extend=extend.none, color=inpCHColor, style=line.style_dashed, width=inpLineWidth)
                f_pushLine(drawnLines, ln)
            if tjl1Set
                f_deleteLatestTJL1ByLeft(levels, tjl1.bar)
            if dualChochHit
                f_promoteLastChochLevelsToBest(levels, lastQmlLeft)
                if inpShowLevels
                    rhOffset = bar_index - runHigh.bar
                    f_addLevel(levels, runHigh.bar, open[rhOffset], close[rhOffset], high[rhOffset], low[rhOffset], true, inpDTDBColor, "D-CHOCH DT", 5, bar_index, bar_index)
            else
                if inpKeepOnlyLastCHOCH
                    f_freezePreviousCHOCHLevels(levels)
                if inpShowLevels
                    clOffset = bar_index - lastCL.bar
                    rhOffset = bar_index - runHigh.bar
                    f_addLevel(levels, lastCL.bar, open[clOffset], close[clOffset], high[clOffset], low[clOffset], false, inpSBRColor, "SBR", 3, bar_index, bar_index)
                    if runHigh.bar != tjl1.bar
                        f_addLevel(levels, runHigh.bar, open[rhOffset], close[rhOffset], high[rhOffset], low[rhOffset], true, inpDTDBColor, "DT", 5, bar_index, bar_index)
                    if tjl1Set
                        tjOffset = bar_index - tjl1.bar
                        [tjTop, tjBot] = f_candleZone(open[tjOffset], close[tjOffset], high[tjOffset], low[tjOffset], true)
                        f_addLevel(levels, tjl1.bar, open[tjOffset], close[tjOffset], high[tjOffset], low[tjOffset], true, inpQMLColor, "SELL QML", 7, bar_index, bar_index)
                        lastQmlLeft := tjl1.bar
                        lastQmlTop := tjTop
                        lastQmlBot := tjBot
                        lastQmlCol := inpQMLColor
            if inpShowOB
                obOff = -1
                for i = 1 to 10
                    if close[i] > open[i]
                        obOff := i
                        break
                if obOff != -1
                    obBar = bar_index - obOff
                    obTop = high[obOff]
                    obBot = open[obOff]
                    if obTop > obBot
                        bx = box.new(obBar, obTop, bar_index, obBot, xloc=xloc.bar_index, border_color=inpBearOBColor, bgcolor=inpBearOBColor, text="S.OB", text_color=color.white, text_size=size.tiny, text_halign=text.align_right, text_valign=text.align_center)
                        ob = OBLevel.new(obBar, bar_index, obTop, obBot, false, true, false, bx)
                        array.push(obLevels, ob)
            trend      := -1
            phase      := 1
            lastCH     := f_makeSnapAtBar(runHigh.bar, runHigh.lvl)
            lastCHSet := true
            runHigh    := f_makeSnapCurrent(high)
            runLow     := f_makeSnapCurrent(low)
            lastChochSide := 1
            issOrTjlSinceChoch := false
    
            if not na(bullIssBos1Line)
                line.delete(bullIssBos1Line)
                bullIssBos1Line := na
            if not na(bearIssBos1Line)
                line.delete(bearIssBos1Line)
                bearIssBos1Line := na
            bullIssState := 1
            bullIssBaseConfirmed := false
            bullIssBaseLow := low
            bullIssBaseLowBar := bar_index
            bullIssRunHigh := high
            bullIssRunHighBar := bar_index
            bullIss1Level := na
            bullIss1Bar := na
            bullIss2Level := na
            bullIss2Bar := na
            bullIssAfterBreakRunHigh := na
            bullIssAfterBreakRunHighBar := na
            bullIssAfterBreakRunLow := na
            bullIssAfterBreakRunLowBar := na
            array.clear(bullIssBosBars)
            array.clear(bullIssBosLvls)
            bearIssState := 0
            bearIssBaseConfirmed := false
            bearIssBaseHigh := na
            bearIssBaseHighBar := na
            bearIssRunLow := na
            bearIssRunLowBar := na
            bearIss1Level := na
            bearIss1Bar := na
            bearIss2Level := na
            bearIss2Bar := na
            bearIssAfterBreakRunLow := na
            bearIssAfterBreakRunLowBar := na
            bearIssAfterBreakRunHigh := na
            bearIssAfterBreakRunHighBar := na
            array.clear(bearIssBosBars)
            array.clear(bearIssBosLvls)
    
        else if bullChoch
            dualChochHit = lastChochSide == 1 and not issOrTjlSinceChoch
            if inpShowCHOCH
                ln = line.new(lastCH.bar, lastCH.lvl, bar_index, lastCH.lvl, xloc=xloc.bar_index, extend=extend.none, color=inpCHColor, style=line.style_dashed, width=inpLineWidth)
                f_pushLine(drawnLines, ln)
            if tjl1Set
                f_deleteLatestTJL1ByLeft(levels, tjl1.bar)
            if dualChochHit
                f_promoteLastChochLevelsToBest(levels, lastQmlLeft)
                if inpShowLevels
                    rlOffset = bar_index - runLow.bar
                    f_addLevel(levels, runLow.bar, open[rlOffset], close[rlOffset], high[rlOffset], low[rlOffset], false, inpDTDBColor, "D-CHOCH DB", 6, bar_index, bar_index)
            else
                if inpKeepOnlyLastCHOCH
                    f_freezePreviousCHOCHLevels(levels)
                if inpShowLevels
                    chOffset = bar_index - lastCH.bar
                    rlOffset = bar_index - runLow.bar
                    f_addLevel(levels, lastCH.bar, open[chOffset], close[chOffset], high[chOffset], low[chOffset], true, inpRBSColor, "RBS", 4, bar_index, bar_index)
                    if runLow.bar != tjl1.bar
                        f_addLevel(levels, runLow.bar, open[rlOffset], close[rlOffset], high[rlOffset], low[rlOffset], false, inpDTDBColor, "DB", 6, bar_index, bar_index)
                    if tjl1Set
                        tjOffset = bar_index - tjl1.bar
                        [tjTop, tjBot] = f_candleZone(open[tjOffset], close[tjOffset], high[tjOffset], low[tjOffset], false)
                        f_addLevel(levels, tjl1.bar, open[tjOffset], close[tjOffset], high[tjOffset], low[tjOffset], false, inpQMLColor, "BUY QML", 7, bar_index, bar_index)
                        lastQmlLeft := tjl1.bar
                        lastQmlTop := tjTop
                        lastQmlBot := tjBot
                        lastQmlCol := inpQMLColor
            if inpShowOB
                obOff = -1
                for i = 1 to 10
                    if close[i] < open[i]
                        obOff := i
                        break
                if obOff != -1
                    obBar = bar_index - obOff
                    obTop = open[obOff]
                    obBot = low[obOff]
                    if obTop > obBot
                        bx = box.new(obBar, obTop, bar_index, obBot, xloc=xloc.bar_index, border_color=inpBullOBColor, bgcolor=inpBullOBColor, text="D.OB", text_color=color.white, text_size=size.tiny, text_halign=text.align_right, text_valign=text.align_center)
                        ob = OBLevel.new(obBar, bar_index, obTop, obBot, true, true, false, bx)
                        array.push(obLevels, ob)
            trend      := 1
            phase      := 1
            lastCL     := f_makeSnapAtBar(runLow.bar, runLow.lvl)
            lastCLSet := true
            runHigh    := f_makeSnapCurrent(high)
            runLow     := f_makeSnapCurrent(low)
            lastChochSide := -1
            issOrTjlSinceChoch := false
    
            if not na(bullIssBos1Line)
                line.delete(bullIssBos1Line)
                bullIssBos1Line := na
            if not na(bearIssBos1Line)
                line.delete(bearIssBos1Line)
                bearIssBos1Line := na
            bearIssState := 1
            bearIssBaseConfirmed := false
            bearIssBaseHigh := high
            bearIssBaseHighBar := bar_index
            bearIssRunLow := low
            bearIssRunLowBar := bar_index
            bearIss1Level := na
            bearIss1Bar := na
            bearIss2Level := na
            bearIss2Bar := na
            bearIssAfterBreakRunLow := na
            bearIssAfterBreakRunLowBar := na
            bearIssAfterBreakRunHigh := na
            bearIssAfterBreakRunHighBar := na
            array.clear(bearIssBosBars)
            array.clear(bearIssBosLvls)
            bullIssState := 0
            bullIssBaseConfirmed := false
            bullIssBaseLow := na
            bullIssBaseLowBar := na
            bullIssRunHigh := na
            bullIssRunHighBar := na
            bullIss1Level := na
            bullIss1Bar := na
            bullIss2Level := na
            bullIss2Bar := na
            bullIssAfterBreakRunHigh := na
            bullIssAfterBreakRunHighBar := na
            bullIssAfterBreakRunLow := na
            bullIssAfterBreakRunLowBar := na
            array.clear(bullIssBosBars)
            array.clear(bullIssBosLvls)
    
        else
            if trend == 1 and phase == 2 and lastCHSet and close > lastCH.lvl
                if inpShowBOS
                    ln = line.new(lastCH.bar, lastCH.lvl, bar_index, lastCH.lvl, xloc=xloc.bar_index, extend=extend.none, color=inpBullBOSColor, style=line.style_solid, width=inpLineWidth)
                    f_pushLine(drawnLines, ln)
                lastCL := f_makeSnapAtBar(runLow.bar, runLow.lvl)
                lastCLSet := true
                chOff2 = bar_index - lastCH.bar
                tjl1 := f_makeSnapAtBar(lastCH.bar, lastCH.lvl)
                tjl2 := f_makeSnapAtBar(lastCL.bar, lastCL.lvl)
                tjl1Set := true
                if inpShowTJL
                    f_addLevel(levels, tjl1.bar, open[chOff2], close[chOff2], high[chOff2], low[chOff2], true, inpBullTJLColor, "BUY TJL1", 1, bar_index, bar_index)
                    clOff2 = bar_index - lastCL.bar
                    f_addLevel(levels, tjl2.bar, open[clOff2], close[clOff2], high[clOff2], low[clOff2], false, inpBullTJLColor, "BUY TJL2", 2, bar_index, bar_index)
                    issOrTjlSinceChoch := true
                if inpShowOB
                    obOff = -1
                    for i = 1 to 10
                        if close[i] < open[i]
                            obOff := i
                            break
                    if obOff != -1
                        obBar = bar_index - obOff
                        obTop = open[obOff]
                        obBot = low[obOff]
                        if obTop > obBot
                            bx = box.new(obBar, obTop, bar_index, obBot, xloc=xloc.bar_index, border_color=inpBullOBColor, bgcolor=inpBullOBColor, text="D.OB", text_color=color.white, text_size=size.tiny, text_halign=text.align_right, text_valign=text.align_center)
                            ob = OBLevel.new(obBar, bar_index, obTop, obBot, true, true, false, bx)
                            array.push(obLevels, ob)
                phase   := 1
                runHigh := f_makeSnapCurrent(high)
                runLow  := f_makeSnapCurrent(low)
    
                if not na(bullIssBos1Line)
                    line.delete(bullIssBos1Line)
                    bullIssBos1Line := na
                if not na(bearIssBos1Line)
                    line.delete(bearIssBos1Line)
                    bearIssBos1Line := na
                bearIssState := 1
                bearIssBaseConfirmed := false
                bearIssBaseHigh := high
                bearIssBaseHighBar := bar_index
                bearIssRunLow := low
                bearIssRunLowBar := bar_index
                bearIss1Level := na
                bearIss1Bar := na
                bearIss2Level := na
                bearIss2Bar := na
                bearIssAfterBreakRunLow := na
                bearIssAfterBreakRunLowBar := na
                bearIssAfterBreakRunHigh := na
                bearIssAfterBreakRunHighBar := na
                array.clear(bearIssBosBars)
                array.clear(bearIssBosLvls)
                bullIssState := 0
                bullIssBaseConfirmed := false
                bullIssBaseLow := na
                bullIssBaseLowBar := na
                bullIssRunHigh := na
                bullIssRunHighBar := na
                bullIss1Level := na
                bullIss1Bar := na
                bullIss2Level := na
                bullIss2Bar := na
                bullIssAfterBreakRunHigh := na
                bullIssAfterBreakRunHighBar := na
                bullIssAfterBreakRunLow := na
                bullIssAfterBreakRunLowBar := na
                array.clear(bullIssBosBars)
                array.clear(bullIssBosLvls)
    
            else if trend == -1 and phase == 2 and lastCLSet and close < lastCL.lvl
                if inpShowBOS
                    ln = line.new(lastCL.bar, lastCL.lvl, bar_index, lastCL.lvl, xloc=xloc.bar_index, extend=extend.none, color=inpBearBOSColor, style=line.style_solid, width=inpLineWidth)
                    f_pushLine(drawnLines, ln)
                lastCH := f_makeSnapAtBar(runHigh.bar, runHigh.lvl)
                lastCHSet := true
                clOff2 = bar_index - lastCL.bar
                tjl1 := f_makeSnapAtBar(lastCL.bar, lastCL.lvl)
                tjl2 := f_makeSnapAtBar(lastCH.bar, lastCH.lvl)
                tjl1Set := true
                if inpShowTJL
                    f_addLevel(levels, tjl1.bar, open[clOff2], close[clOff2], high[clOff2], low[clOff2], false, inpBearTJLColor, "SELL TJL1", 1, bar_index, bar_index)
                    chOff2 = bar_index - lastCH.bar
                    f_addLevel(levels, tjl2.bar, open[chOff2], close[chOff2], high[chOff2], low[chOff2], true, inpBearTJLColor, "SELL TJL2", 2, bar_index, bar_index)
                    issOrTjlSinceChoch := true
                if inpShowOB
                    obOff = -1
                    for i = 1 to 10
                        if close[i] > open[i]
                            obOff := i
                            break
                    if obOff != -1
                        obBar = bar_index - obOff
                        obTop = high[obOff]
                        obBot = open[obOff]
                        if obTop > obBot
                            bx = box.new(obBar, obTop, bar_index, obBot, xloc=xloc.bar_index, border_color=inpBearOBColor, bgcolor=inpBearOBColor, text="S.OB", text_color=color.white, text_size=size.tiny, text_halign=text.align_right, text_valign=text.align_center)
                            ob = OBLevel.new(obBar, bar_index, obTop, obBot, false, true, false, bx)
                            array.push(obLevels, ob)
                phase   := 1
                runHigh := f_makeSnapCurrent(high)
                runLow  := f_makeSnapCurrent(low)
    
                if not na(bullIssBos1Line)
                    line.delete(bullIssBos1Line)
                    bullIssBos1Line := na
                if not na(bearIssBos1Line)
                    line.delete(bearIssBos1Line)
                    bearIssBos1Line := na
                bullIssState := 1
                bullIssBaseConfirmed := false
                bullIssBaseLow := low
                bullIssBaseLowBar := bar_index
                bullIssRunHigh := high
                bullIssRunHighBar := bar_index
                bullIss1Level := na
                bullIss1Bar := na
                bullIss2Level := na
                bullIss2Bar := na
                bullIssAfterBreakRunHigh := na
                bullIssAfterBreakRunHighBar := na
                bullIssAfterBreakRunLow := na
                bullIssAfterBreakRunLowBar := na
                array.clear(bullIssBosBars)
                array.clear(bullIssBosLvls)
                bearIssState := 0
                bearIssBaseConfirmed := false
                bearIssBaseHigh := na
                bearIssBaseHighBar := na
                bearIssRunLow := na
                bearIssRunLowBar := na
                bearIss1Level := na
                bearIss1Bar := na
                bearIss2Level := na
                bearIss2Bar := na
                bearIssAfterBreakRunLow := na
                bearIssAfterBreakRunLowBar := na
                bearIssAfterBreakRunHigh := na
                bearIssAfterBreakRunHighBar := na
                array.clear(bearIssBosBars)
                array.clear(bearIssBosLvls)
    
            else if phase == 1
                if trend != -1 and bullRetracement
                    lastCH := f_makeSnapAtBar(runHigh.bar, runHigh.lvl)
                    lastCHSet := true
                    trend := 1
                    phase := 2
                    if inpShowSwings
                        lb = label.new(lastCH.bar, lastCH.lvl, "CH", xloc=xloc.bar_index, style=label.style_label_down, textcolor=inpCHColor, color=color.new(color.white, 100), size=size.small)
                        f_pushLabel(drawnLabels, lb)
                    runLow := low < low[1] ? f_makeSnapCurrent(low) : f_makeSnapAtBar(bar_index - 1, low[1])
                else if trend != 1 and bearRetracement
                    lastCL := f_makeSnapAtBar(runLow.bar, runLow.lvl)
                    lastCLSet := true
                    trend := -1
                    phase := 2
                    if inpShowSwings
                        lb = label.new(lastCL.bar, lastCL.lvl, "CL", xloc=xloc.bar_index, style=label.style_label_up, textcolor=inpCLColor, color=color.new(color.white, 100), size=size.small)
                        f_pushLabel(drawnLabels, lb)
                    runHigh := high > high[1] ? f_makeSnapCurrent(high) : f_makeSnapAtBar(bar_index - 1, high[1])
    
        // ==================================================================
        // ISS STATE MACHINE
        // ==================================================================
        if inpEnableISS
            bullIssInvalidated = bullIssState >= 2 and not na(bullIssBaseLow) and close < bullIssBaseLow
            bearIssInvalidated = bearIssState >= 2 and not na(bearIssBaseHigh) and close > bearIssBaseHigh
    
            if bullIssInvalidated
                if not na(bullIssBos1Line)
                    line.delete(bullIssBos1Line)
                    bullIssBos1Line := na
                bullIssState := 0
                bullIssBaseConfirmed := false
                bullIssBaseLow := na
                bullIssBaseLowBar := na
                bullIssRunHigh := na
                bullIssRunHighBar := na
                bullIss1Level := na
                bullIss1Bar := na
                bullIss2Level := na
                bullIss2Bar := na
                bullIssAfterBreakRunHigh := na
                bullIssAfterBreakRunHighBar := na
                bullIssAfterBreakRunLow := na
                bullIssAfterBreakRunLowBar := na
                array.clear(bullIssBosBars)
                array.clear(bullIssBosLvls)
            else if bullIssState == 1
                if inpISSScenario == "1"
                    if bearishIssShift and not na(bullIssRunHighBar) and bullIssRunHighBar < bar_index and bullIssRunHighBar != bullIssBaseLowBar
                        bullIss1Level := bullIssRunHigh
                        bullIss1Bar := bullIssRunHighBar
                        bullIssState := 2
                        bullIss2Level := low
                        bullIss2Bar := bar_index
                    if bullIssState == 1
                        if na(bullIssBaseLow) or low < bullIssBaseLow
                            bullIssBaseLow := low
                            bullIssBaseLowBar := bar_index
                            bullIssRunHigh := high
                            bullIssRunHighBar := bar_index
                        else if na(bullIssRunHigh) or high > bullIssRunHigh
                            bullIssRunHigh := high
                            bullIssRunHighBar := bar_index
                else
                    if na(bullIssBaseLow) or low < bullIssBaseLow
                        bullIssBaseLow := low
                        bullIssBaseLowBar := bar_index
                        bullIssRunHigh := high
                        bullIssRunHighBar := bar_index
                        bullIssBaseConfirmed := false
                    if not bullIssBaseConfirmed
                        if bullishIssShift
                            bullIssBaseConfirmed := true
                            bullIssRunHigh := high
                            bullIssRunHighBar := bar_index
                    else
                        if na(bullIssRunHigh) or high > bullIssRunHigh
                            bullIssRunHigh := high
                            bullIssRunHighBar := bar_index
                        if bearishIssShift and not na(bullIssRunHighBar) and bullIssRunHighBar < bar_index
                            bullIss1Level := bullIssRunHigh
                            bullIss1Bar := bullIssRunHighBar
                            bullIssState := 2
                            bullIss2Level := low
                            bullIss2Bar := bar_index
            else if bullIssState == 2
                if low < bullIss2Level
                    bullIss2Level := low
                    bullIss2Bar := bar_index
                if not na(bullIss1Level) and close > bullIss1Level
                    if inpShowISSBOS
                        bullIssBos1Line := line.new(bullIss1Bar, bullIss1Level, bar_index, bullIss1Level, xloc=xloc.bar_index, extend=extend.none, color=inpISSColor, style=line.style_solid, width=inpLineWidth)
                        f_pushLine(drawnLines, bullIssBos1Line)
                    bullIssAfterBreakRunHigh := high
                    bullIssAfterBreakRunHighBar := bar_index
                    bullIssAfterBreakRunLow := low
                    bullIssAfterBreakRunLowBar := bar_index
                    bullIssState := 3
            else if bullIssState == 3
                if low < bullIss2Level
                    bullIss2Level := low
                    bullIss2Bar := bar_index
                if inpISSScenario == "1"
                    if na(bullIssAfterBreakRunHigh) or high > bullIssAfterBreakRunHigh
                        bullIssAfterBreakRunHigh := high
                        bullIssAfterBreakRunHighBar := bar_index
                    if na(bullIssAfterBreakRunLow) or low < bullIssAfterBreakRunLow
                        bullIssAfterBreakRunLow := low
                        bullIssAfterBreakRunLowBar := bar_index
                    if bearishIssShift and not na(bullIssAfterBreakRunHighBar) and not na(bullIssAfterBreakRunLowBar)
                        bullIssAfterBreakRunLow := low
                        bullIssAfterBreakRunLowBar := bar_index
                        bullIssState := 4
                else
                    if na(bullIssAfterBreakRunHigh) or high > bullIssAfterBreakRunHigh
                        bullIssAfterBreakRunHigh := high
                        bullIssAfterBreakRunHighBar := bar_index
                        bullIssAfterBreakRunLow := low
                        bullIssAfterBreakRunLowBar := bar_index
                    else if na(bullIssAfterBreakRunLow) or low < bullIssAfterBreakRunLow
                        bullIssAfterBreakRunLow := low
                        bullIssAfterBreakRunLowBar := bar_index
                    if bearishIssShift and not na(bullIssAfterBreakRunHighBar) and not na(bullIssAfterBreakRunLowBar)
                        bullIssState := 4
            else if bullIssState == 4
                if na(bullIssAfterBreakRunLow) or low < bullIssAfterBreakRunLow
                    bullIssAfterBreakRunLow := low
                    bullIssAfterBreakRunLowBar := bar_index
    
                if inpISSScenario == "1" and not na(bullIssAfterBreakRunLow) and not na(bullIss2Level) and bullIssAfterBreakRunLow < bullIss2Level
                    if not na(bullIssBos1Line)
                        line.delete(bullIssBos1Line)
                        bullIssBos1Line := na
                    if inpShowISS and inpShowISSLabel
                        lb = label.new(bullIssAfterBreakRunLowBar, bullIssAfterBreakRunLow, "ISS", xloc=xloc.bar_index, style=label.style_none, textcolor=inpISSColor, size=size.normal)
                        f_pushLabel(drawnLabels, lb)
                    bullIssState := 1
                    bullIssBaseConfirmed := false
                    bullIssBaseLow := bullIssAfterBreakRunLow
                    bullIssBaseLowBar := bullIssAfterBreakRunLowBar
                    bullIssRunHigh := high
                    bullIssRunHighBar := bar_index
                    bullIss1Level := na
                    bullIss1Bar := na
                    bullIss2Level := na
                    bullIss2Bar := na
                    bullIssAfterBreakRunHigh := na
                    bullIssAfterBreakRunHighBar := na
                    bullIssAfterBreakRunLow := na
                    bullIssAfterBreakRunLowBar := na
                    array.clear(bullIssBosBars)
                    array.clear(bullIssBosLvls)
    
                if bullIssState == 4 and not na(bullIssAfterBreakRunHigh) and not na(bullIssAfterBreakRunLowBar) and close > bullIssAfterBreakRunHigh
                    if inpShowISS and inpShowISSLabel
                        lb = label.new(bullIssBaseLowBar, bullIssBaseLow, "ISS", xloc=xloc.bar_index, style=label.style_none, textcolor=inpISSColor, size=size.normal)
                        f_pushLabel(drawnLabels, lb)
                        issOrTjlSinceChoch := true
                    if inpShowLevels and inpShowISS1
                        f_addLevelFromBarReady(levels, bullIss1Bar, bullIss1Bar, true, inpISSColor, "ISS 1", 29, bar_index, bar_index, bar_index)
                    if inpShowLevels and inpShowISS2
                        f_addLevelFromBarReady(levels, bullIss2Bar, bullIss2Bar, false, inpISSColor, "ISS 2", 34, bar_index, bar_index, bar_index)
                    if inpShowLevels and inpShowISS3
                        f_addLevelFromBarReady(levels, bullIssAfterBreakRunHighBar, bullIssAfterBreakRunHighBar, true, inpISSColor, "ISS 3", 30, bar_index, bar_index, bar_index)
                    if inpShowLevels and inpShowISS4
                        f_addLevelFromBarReady(levels, bullIssAfterBreakRunLowBar, bullIssAfterBreakRunLowBar, false, inpISSColor, "ISS 4", 31, bar_index, bar_index, bar_index)
                    trend := 1
                    phase := 1
                    lastCH := f_makeSnapAtBar(bullIssAfterBreakRunHighBar, bullIssAfterBreakRunHigh)
                    lastCL := f_makeSnapAtBar(bullIssAfterBreakRunLowBar, bullIssAfterBreakRunLow)
                    lastCHSet := true
                    lastCLSet := true
                    tjl1 := f_makeSnapAtBar(bullIssAfterBreakRunHighBar, bullIssAfterBreakRunHigh)
                    tjl2 := f_makeSnapAtBar(bullIssAfterBreakRunLowBar, bullIssAfterBreakRunLow)
                    tjl1Set := true
                    runHigh := f_makeSnapCurrent(high)
                    runLow := f_makeSnapCurrent(low)
                    issOrTjlSinceChoch := true
                    bullIssState := 0
                    bullIssBaseConfirmed := false
                    bullIssBaseLow := na
                    bullIssBaseLowBar := na
                    bullIssRunHigh := na
                    bullIssRunHighBar := na
                    bullIss1Level := na
                    bullIss1Bar := na
                    bullIss2Level := na
                    bullIss2Bar := na
                    bullIssAfterBreakRunHigh := na
                    bullIssAfterBreakRunHighBar := na
                    bullIssAfterBreakRunLow := na
                    bullIssAfterBreakRunLowBar := na
                    array.clear(bullIssBosBars)
                    array.clear(bullIssBosLvls)
                    bullIssBos1Line := na
                    bearIssState := 1
                    bearIssBaseConfirmed := false
                    bearIssBaseHigh := high
                    bearIssBaseHighBar := bar_index
                    bearIssRunLow := low
                    bearIssRunLowBar := bar_index
                    bearIss1Level := na
                    bearIss1Bar := na
                    bearIss2Level := na
                    bearIss2Bar := na
                    bearIssAfterBreakRunLow := na
                    bearIssAfterBreakRunLowBar := na
                    bearIssAfterBreakRunHigh := na
                    bearIssAfterBreakRunHighBar := na
                    array.clear(bearIssBosBars)
                    array.clear(bearIssBosLvls)
    
            if bearIssInvalidated
                if not na(bearIssBos1Line)
                    line.delete(bearIssBos1Line)
                    bearIssBos1Line := na
                bearIssState := 0
                bearIssBaseConfirmed := false
                bearIssBaseHigh := na
                bearIssBaseHighBar := na
                bearIssRunLow := na
                bearIssRunLowBar := na
                bearIss1Level := na
                bearIss1Bar := na
                bearIss2Level := na
                bearIss2Bar := na
                bearIssAfterBreakRunLow := na
                bearIssAfterBreakRunLowBar := na
                bearIssAfterBreakRunHigh := na
                bearIssAfterBreakRunHighBar := na
                array.clear(bearIssBosBars)
                array.clear(bearIssBosLvls)
            else if bearIssState == 1
                if inpISSScenario == "1"
                    if bullishIssShift and not na(bearIssRunLowBar) and bearIssRunLowBar < bar_index and bearIssRunLowBar != bearIssBaseHighBar
                        bearIss1Level := bearIssRunLow
                        bearIss1Bar := bearIssRunLowBar
                        bearIssState := 2
                        bearIss2Level := high
                        bearIss2Bar := bar_index
                    if bearIssState == 1
                        if na(bearIssBaseHigh) or high > bearIssBaseHigh
                            bearIssBaseHigh := high
                            bearIssBaseHighBar := bar_index
                            bearIssRunLow := low
                            bearIssRunLowBar := bar_index
                        else if na(bearIssRunLow) or low < bearIssRunLow
                            bearIssRunLow := low
                            bearIssRunLowBar := bar_index
                else
                    if na(bearIssBaseHigh) or high > bearIssBaseHigh
                        bearIssBaseHigh := high
                        bearIssBaseHighBar := bar_index
                        bearIssRunLow := low
                        bearIssRunLowBar := bar_index
                        bearIssBaseConfirmed := false
                    if not bearIssBaseConfirmed
                        if bearishIssShift
                            bearIssBaseConfirmed := true
                            bearIssRunLow := low
                            bearIssRunLowBar := bar_index
                    else
                        if na(bearIssRunLow) or low < bearIssRunLow
                            bearIssRunLow := low
                            bearIssRunLowBar := bar_index
                        if bullishIssShift and not na(bearIssRunLowBar) and bearIssRunLowBar < bar_index
                            bearIss1Level := bearIssRunLow
                            bearIss1Bar := bearIssRunLowBar
                            bearIssState := 2
                            bearIss2Level := high
                            bearIss2Bar := bar_index
            else if bearIssState == 2
                if high > bearIss2Level
                    bearIss2Level := high
                    bearIss2Bar := bar_index
                if not na(bearIss1Level) and close < bearIss1Level
                    if inpShowISSBOS
                        bearIssBos1Line := line.new(bearIss1Bar, bearIss1Level, bar_index, bearIss1Level, xloc=xloc.bar_index, extend=extend.none, color=inpISSColor, style=line.style_solid, width=inpLineWidth)
                        f_pushLine(drawnLines, bearIssBos1Line)
                    bearIssAfterBreakRunLow := low
                    bearIssAfterBreakRunLowBar := bar_index
                    bearIssAfterBreakRunHigh := high
                    bearIssAfterBreakRunHighBar := bar_index
                    bearIssState := 3
            else if bearIssState == 3
                if high > bearIss2Level
                    bearIss2Level := high
                    bearIss2Bar := bar_index
                if inpISSScenario == "1"
                    if na(bearIssAfterBreakRunLow) or low < bearIssAfterBreakRunLow
                        bearIssAfterBreakRunLow := low
                        bearIssAfterBreakRunLowBar := bar_index
                        bearIssAfterBreakRunHigh := high
                        bearIssAfterBreakRunHighBar := bar_index
                    else if na(bearIssAfterBreakRunHigh) or high > bearIssAfterBreakRunHigh
                        bearIssAfterBreakRunHigh := high
                        bearIssAfterBreakRunHighBar := bar_index
                    if bullishIssShift and not na(bearIssAfterBreakRunLowBar) and not na(bearIssAfterBreakRunHighBar)
                        bearIssAfterBreakRunHigh := high
                        bearIssAfterBreakRunHighBar := bar_index
                        bearIssState := 4
                else
                    if na(bearIssAfterBreakRunLow) or low < bearIssAfterBreakRunLow
                        bearIssAfterBreakRunLow := low
                        bearIssAfterBreakRunLowBar := bar_index
                        bearIssAfterBreakRunHigh := high
                        bearIssAfterBreakRunHighBar := bar_index
                    else if na(bearIssAfterBreakRunHigh) or high > bearIssAfterBreakRunHigh
                        bearIssAfterBreakRunHigh := high
                        bearIssAfterBreakRunHighBar := bar_index
                    if bullishIssShift and not na(bearIssAfterBreakRunLowBar) and not na(bearIssAfterBreakRunHighBar)
                        bearIssState := 4
            else if bearIssState == 4
                if na(bearIssAfterBreakRunHigh) or high > bearIssAfterBreakRunHigh
                    bearIssAfterBreakRunHigh := high
                    bearIssAfterBreakRunHighBar := bar_index
    
                if inpISSScenario == "1" and not na(bearIssAfterBreakRunHigh) and not na(bearIss2Level) and bearIssAfterBreakRunHigh > bearIss2Level
                    if not na(bearIssBos1Line)
                        line.delete(bearIssBos1Line)
                        bearIssBos1Line := na
                    if inpShowISS and inpShowISSLabel
                        lb = label.new(bearIssAfterBreakRunHighBar, bearIssAfterBreakRunHigh, "ISS", xloc=xloc.bar_index, style=label.style_none, textcolor=inpISSColor, size=size.normal)
                        f_pushLabel(drawnLabels, lb)
                    bearIssState := 1
                    bearIssBaseConfirmed := false
                    bearIssBaseHigh := bearIssAfterBreakRunHigh
                    bearIssBaseHighBar := bearIssAfterBreakRunHighBar
                    bearIssRunLow := low
                    bearIssRunLowBar := bar_index
                    bearIss1Level := na
                    bearIss1Bar := na
                    bearIss2Level := na
                    bearIss2Bar := na
                    bearIssAfterBreakRunLow := na
                    bearIssAfterBreakRunLowBar := na
                    bearIssAfterBreakRunHigh := na
                    bearIssAfterBreakRunHighBar := na
                    array.clear(bearIssBosBars)
                    array.clear(bearIssBosLvls)
    
                if bearIssState == 4 and not na(bearIssAfterBreakRunLow) and not na(bearIssAfterBreakRunHighBar) and close < bearIssAfterBreakRunLow
                    if inpShowISS and inpShowISSLabel
                        lb = label.new(bearIssBaseHighBar, bearIssBaseHigh, "ISS", xloc=xloc.bar_index, style=label.style_none, textcolor=inpISSColor, size=size.normal)
                        f_pushLabel(drawnLabels, lb)
                        issOrTjlSinceChoch := true
                    if inpShowLevels and inpShowISS1
                        f_addLevelFromBarReady(levels, bearIss1Bar, bearIss1Bar, false, inpISSColor, "ISS 1", 29, bar_index, bar_index, bar_index)
                    if inpShowLevels and inpShowISS2
                        f_addLevelFromBarReady(levels, bearIss2Bar, bearIss2Bar, true, inpISSColor, "ISS 2", 35, bar_index, bar_index, bar_index)
                    if inpShowLevels and inpShowISS3
                        f_addLevelFromBarReady(levels, bearIssAfterBreakRunLowBar, bearIssAfterBreakRunLowBar, false, inpISSColor, "ISS 3", 32, bar_index, bar_index, bar_index)
                    if inpShowLevels and inpShowISS4
                        f_addLevelFromBarReady(levels, bearIssAfterBreakRunHighBar, bearIssAfterBreakRunHighBar, true, inpISSColor, "ISS 4", 33, bar_index, bar_index, bar_index)
                    trend := -1
                    phase := 1
                    lastCH := f_makeSnapAtBar(bearIssAfterBreakRunHighBar, bearIssAfterBreakRunHigh)
                    lastCL := f_makeSnapAtBar(bearIssAfterBreakRunLowBar, bearIssAfterBreakRunLow)
                    lastCHSet := true
                    lastCLSet := true
                    tjl1 := f_makeSnapAtBar(bearIssAfterBreakRunLowBar, bearIssAfterBreakRunLow)
                    tjl2 := f_makeSnapAtBar(bearIssAfterBreakRunHighBar, bearIssAfterBreakRunHigh)
                    tjl1Set := true
                    runHigh := f_makeSnapCurrent(high)
                    runLow := f_makeSnapCurrent(low)
                    issOrTjlSinceChoch := true
                    bearIssState := 0
                    bearIssBaseConfirmed := false
                    bearIssBaseHigh := na
                    bearIssBaseHighBar := na
                    bearIssRunLow := na
                    bearIssRunLowBar := na
                    bearIss1Level := na
                    bearIss1Bar := na
                    bearIss2Level := na
                    bearIss2Bar := na
                    bearIssAfterBreakRunLow := na
                    bearIssAfterBreakRunLowBar := na
                    bearIssAfterBreakRunHigh := na
                    bearIssAfterBreakRunHighBar := na
                    array.clear(bearIssBosBars)
                    array.clear(bearIssBosLvls)
                    bearIssBos1Line := na
                    bullIssState := 1
                    bullIssBaseConfirmed := false
                    bullIssBaseLow := low
                    bullIssBaseLowBar := bar_index
                    bullIssRunHigh := high
                    bullIssRunHighBar := bar_index
                    bullIss1Level := na
                    bullIss1Bar := na
                    bullIss2Level := na
                    bullIss2Bar := na
                    bullIssAfterBreakRunHigh := na
                    bullIssAfterBreakRunHighBar := na
                    bullIssAfterBreakRunLow := na
                    bullIssAfterBreakRunLowBar := na
                    array.clear(bullIssBosBars)
                    array.clear(bullIssBosLvls)
    
        if inpShowFVG
            bullFVGForm = low > high[2]
            bearFVGForm = high < low[2]
            if bullFVGForm
                fvgTop = low
                fvgBot = high[2]
                if fvgTop > fvgBot
                    bx = box.new(bar_index - 2, fvgTop, bar_index, fvgBot, xloc=xloc.bar_index, border_color=inpBullFVGColor, bgcolor=inpBullFVGColor, text="FVG", text_color=color.white, text_size=size.tiny, text_halign=text.align_right, text_valign=text.align_center)
                    fv = FVGLevel.new(bar_index - 2, bar_index, fvgTop, fvgBot, true, true, false, bx)
                    array.push(fvgLevels, fv)
            if bearFVGForm
                fvgTop = low[2]
                fvgBot = high
                if fvgTop > fvgBot
                    bx = box.new(bar_index - 2, fvgTop, bar_index, fvgBot, xloc=xloc.bar_index, border_color=inpBearFVGColor, bgcolor=inpBearFVGColor, text="FVG", text_color=color.white, text_size=size.tiny, text_halign=text.align_right, text_valign=text.align_center)
                    fv = FVGLevel.new(bar_index - 2, bar_index, fvgTop, fvgBot, false, true, false, bx)
                    array.push(fvgLevels, fv)
    
        f_trimLevels(levels)
    
        if inpShowDebugState
            dbgTxt = "T" + str.tostring(trend) + "/" + str.tostring(phase) + " BU" + str.tostring(bullIssState) + " BE" + str.tostring(bearIssState)
            dbgBx = box.new(bar_index, low, bar_index, low * 0.999, xloc=xloc.bar_index, border_color=color.new(color.black, 100), bgcolor=color.new(color.yellow, 20), text=dbgTxt, text_color=color.new(color.black, 0), text_size=size.tiny, text_halign=text.align_center, text_valign=text.align_center)
    
    
        if inpShowFVG and array.size(fvgLevels) > 0
            kept = 0
            for i = array.size(fvgLevels) - 1 to 0
                fv = array.get(fvgLevels, i)
                if fv.deleted
                    continue
                kept += 1
                if kept > inpMaxFVG
                    fv.deleted := true
                    fv.active  := false
                    if not na(fv.bx)
                        box.delete(fv.bx)
                    array.set(fvgLevels, i, fv)
    
        if inpShowOB and array.size(obLevels) > 0
            kept = 0
            for i = array.size(obLevels) - 1 to 0
                ob = array.get(obLevels, i)
                if ob.deleted
                    continue
                kept += 1
                if kept > inpMaxOB
                    ob.deleted := true
                    ob.active  := false
                    if not na(ob.bx)
                        box.delete(ob.bx)
                    array.set(obLevels, i, ob)
    
        f_compactDeletedLevels(levels)
        f_compactDeletedFVG(fvgLevels)
        f_compactDeletedOB(obLevels)
    
        drawn = 0
        if array.size(levels) > 0
            for i = array.size(levels) - 1 to 0
                if drawn >= inpMaxLiveLevels
                    break
                lv = array.get(levels, i)
                if lv.deleted
                    continue
                if not f_shouldShowLevel(lv.kind, lv.txt)
                    continue
                safeLeft = math.max(lv.left, bar_index - 4000)
                if na(lv.bx)
                    lv.bx := box.new(safeLeft, lv.top, lv.right, lv.bot, xloc=xloc.bar_index, border_color=lv.col, bgcolor=color.new(lv.col, 75), text=lv.txt, text_color=lv.col, text_size=size.small, text_halign=f_levelTextHAlign(), text_valign=f_levelTextVAlign())
                else
                    box.set_lefttop(lv.bx, safeLeft, lv.top)
                    box.set_rightbottom(lv.bx, lv.right, lv.bot)
                    box.set_border_color(lv.bx, lv.col)
                    box.set_bgcolor(lv.bx, color.new(lv.col, 75))
                f_applyLevelText(lv.bx, lv.txt, lv.col)
                if not na(lv.lb)
                    label.delete(lv.lb)
                    lv.lb := na
                array.set(levels, i, lv)
                drawn += 1
    

[alertTrendM15, alertQmlM15, alertTjl2M15, alertIss4M15, alertDChochM15] = request.security(syminfo.tickerid, "15", f_mtfTrendCalc(), lookahead=barmerge.lookahead_off)
[alertTrendH1, alertQmlH1, alertTjl2H1, alertIss4H1, alertDChochH1] = request.security(syminfo.tickerid, "60", f_mtfTrendCalc(), lookahead=barmerge.lookahead_off)
[alertTrendH4, alertQmlH4, alertTjl2H4, alertIss4H4, alertDChochH4] = request.security(syminfo.tickerid, "240", f_mtfTrendCalc(), lookahead=barmerge.lookahead_off)

alertcondition(showStructureMarking and alertQmlM15, "M15 QML", "M15 QML level formed")
alertcondition(showStructureMarking and alertTjl2M15, "M15 TJL 2", "M15 TJL 2 level formed")
alertcondition(showStructureMarking and alertIss4M15, "M15 ISS 4", "M15 ISS 4 level formed")
alertcondition(showStructureMarking and alertDChochM15, "M15 D-CHOCH Level", "M15 D-CHOCH level formed")
alertcondition(showStructureMarking and alertQmlH1, "H1 QML", "H1 QML level formed")
alertcondition(showStructureMarking and alertTjl2H1, "H1 TJL 2", "H1 TJL 2 level formed")
alertcondition(showStructureMarking and alertIss4H1, "H1 ISS 4", "H1 ISS 4 level formed")
alertcondition(showStructureMarking and alertDChochH1, "H1 D-CHOCH Level", "H1 D-CHOCH level formed")
alertcondition(showStructureMarking and alertQmlH4, "H4 QML", "H4 QML level formed")
alertcondition(showStructureMarking and alertTjl2H4, "H4 TJL 2", "H4 TJL 2 level formed")
alertcondition(showStructureMarking and alertIss4H4, "H4 ISS 4", "H4 ISS 4 level formed")
alertcondition(showStructureMarking and alertDChochH4, "H4 D-CHOCH Level", "H4 D-CHOCH level formed")

table.clear(levelAnalyzerTable, 0, 0, 4, 18)
if inpShowLevelAnalyzer
    anaHeaderBg = color.rgb(30, 30, 30)
    anaCellBg = color.rgb(18, 18, 18)
    anaBestBg = color.rgb(0, 100, 0)
    bestSlot = f_bestAnalyzerSlot(levelAnalyzerWins, levelAnalyzerLosses)
    table.cell(levelAnalyzerTable, 0, 0, "LEVEL", text_color=color.white, bgcolor=anaHeaderBg, text_size=size.small)
    table.cell(levelAnalyzerTable, 1, 0, "TESTS", text_color=color.white, bgcolor=anaHeaderBg, text_size=size.small)
    table.cell(levelAnalyzerTable, 2, 0, "WINS", text_color=color.white, bgcolor=anaHeaderBg, text_size=size.small)
    table.cell(levelAnalyzerTable, 3, 0, "LOSS", text_color=color.white, bgcolor=anaHeaderBg, text_size=size.small)
    table.cell(levelAnalyzerTable, 4, 0, "ACC", text_color=color.white, bgcolor=anaHeaderBg, text_size=size.small)
    anaRow = 1
    for anaSlot = 0 to 16
        if f_analyzerShowSlot(anaSlot)
            tests = array.get(levelAnalyzerTests, anaSlot)
            wins = array.get(levelAnalyzerWins, anaSlot)
            losses = array.get(levelAnalyzerLosses, anaSlot)
            rowBg = anaSlot == bestSlot ? anaBestBg : anaCellBg
            table.cell(levelAnalyzerTable, 0, anaRow, f_analyzerLabel(anaSlot), text_color=color.white, bgcolor=rowBg, text_size=size.small)
            table.cell(levelAnalyzerTable, 1, anaRow, str.tostring(tests), text_color=color.white, bgcolor=rowBg, text_size=size.small)
            table.cell(levelAnalyzerTable, 2, anaRow, str.tostring(wins), text_color=color.white, bgcolor=rowBg, text_size=size.small)
            table.cell(levelAnalyzerTable, 3, anaRow, str.tostring(losses), text_color=color.white, bgcolor=rowBg, text_size=size.small)
            table.cell(levelAnalyzerTable, 4, anaRow, f_analyzerRateText(wins, losses), text_color=color.white, bgcolor=rowBg, text_size=size.small)
            anaRow += 1

Overview

Mahi_varma PA detects Break of Structure (BOS) and Change of Character (CHOCH) patterns alongside swing points. The script identifies key zones including Quasimodo Levels (QML), Support Becoming Resistance (SBR), Resistance Becoming Support (RBS), Double Tops and Bottoms (DT/DB), TJL, and ISS scenarios. Settings allow traders to toggle specific level visibility, isolate high-probability A+ setups, adjust ISS logic parameters, and customize visual display options.

Details

Published by

manthenamahendravarma-IO on GitHub

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

SMC / ICT / price action, Support & resistance, Trend

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

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

SettingTypeDefaultVariable
Start Timetimetimestamp("2026-01-01T00:00:00")inpStartTime
Max Barsint12000inpMaxBars
Show SwingsbooltrueinpShowSwings
Show BOSbooltrueinpShowBOS
Show CHOCHbooltrueinpShowCHOCH
Show LevelsbooltrueinpShowLevels
Show TJLbooltrueinpShowTJL
Show ISSbooltrueinpShowISS
Keep Only Last CHOCHboolfalseinpKeepOnlyLastCHOCH
Show TJL 1booltrueinpShowTJL1
Show TJL 2booltrueinpShowTJL2
Show QMLbooltrueinpShowQML
Show all 40 settings
SettingTypeDefaultVariable
Show SBRbooltrueinpShowSBR
Show RBSbooltrueinpShowRBS
Show DBbooltrueinpShowDB
Show DTbooltrueinpShowDT
Show Best LevelsbooltrueinpShowBestQML
Show ISS 1boolfalseinpShowISS1
Show ISS 2booltrueinpShowISS2
Show ISS 3booltrueinpShowISS3
Show ISS 4booltrueinpShowISS4
Show Only A+ Levels (TJL2, QML, D-CHOCH QML, ISS4)boolfalseinpShowOnlyAPlus
Enable ISS LogicbooltrueinpEnableISS
Show ISS LabelbooltrueinpShowISSLabel
Show ISS BOSbooltrueinpShowISSBOS
Stop ISS 3/4 on Wick TapbooltrueinpStopISS34ByWickTap
ISS Scenariostring1inpISSScenario
CH Colorcolorcolor.whiteinpCHColor
CL Colorcolorcolor.orangeinpCLColor
Bull BOS Colorcolorcolor.greeninpBullBOSColor
Bear BOS Colorcolorcolor.redinpBearBOSColor
Bull TJL Colorcolorcolor.greeninpBullTJLColor
Bear TJL Colorcolorcolor.orangeinpBearTJLColor
SBR Colorcolorcolor.redinpSBRColor
RBS Colorcolorcolor.greeninpRBSColor
QML Colorcolorcolor.rgb(186, 85, 211)inpQMLColor
DT/DB Colorcolorcolor.blueinpDTDBColor
ISS Colorcolorcolor.yellowinpISSColor
Best QML Colorcolorcolor.rgb(255, 215, 0)inpBestQMLColor
Line Widthint2inpLineWidth
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

575 stars

This indicator detects equal highs and lows by comparing prices within user-defined left and right bars using a tolerance percentage. It plots horizontal lines on the price chart for equal highs in one color and lows in another. A screener allows input of mult

Indicator v5 Support & resistanceTrend
Updated 1 year ago · MPL-2.0 GitHub repository of ICT Equal Highs and Lows with Screener

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
218 stars

This indicator plots market structure on the price chart by identifying swing highs and lows. It connects these points with lines to visualize trend direction and detect Break of Structure (BOS) when price breaks a prior swing in the current trend. Change of C

Indicator v6 TrendSupport & resistance
Updated 3 months ago · None stated GitHub repository of Market Structure - BOS & CHoCH

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
56 stars

BigBeluga Smart Money Concepts identifies and overlays market structure and volumetric order blocks directly on the price chart. It analyzes market swings, trend sweeps, and mapping structure using customizable pivot lengths and calculation modes. The indicato

Indicator v5 SMC / ICT / price actionSupport & resistance
Updated 2 months ago · None stated GitHub repository of BigBeluga - Smart Money Concepts
53 stars

Apex Trend & Liquidity Master calculates a trend cloud using customizable moving averages expanded by a volatility multiplier directly on the main price chart. It identifies dynamic support and resistance liquidity zones from swing high and low pivots, extendi

Indicator v6 TrendSupport & resistance
Updated 2 months ago · MPL-2.0 GitHub repository of Apex Trend & Liquidity Master

More indicators

Trade Your Charts With a Regulated Broker

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

Compare brokers