1Copy the scriptPress Copy script above, or the copy button on the code below.
2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
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.
Market structure mapping with BOS and CHOCH
Support and resistance zone detection including QML, SBR, and RBS
Configurable ISS logic scenarios and level filtering
Filter option for high-probability A+ price levels
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
Start Time
time
timestamp("2026-01-01T00:00:00")
inpStartTime
Max Bars
int
12000
inpMaxBars
Show Swings
bool
true
inpShowSwings
Show BOS
bool
true
inpShowBOS
Show CHOCH
bool
true
inpShowCHOCH
Show Levels
bool
true
inpShowLevels
Show TJL
bool
true
inpShowTJL
Show ISS
bool
true
inpShowISS
Keep Only Last CHOCH
bool
false
inpKeepOnlyLastCHOCH
Show TJL 1
bool
true
inpShowTJL1
Show TJL 2
bool
true
inpShowTJL2
Show QML
bool
true
inpShowQML
Show all 40 settings
Setting
Type
Default
Variable
Show SBR
bool
true
inpShowSBR
Show RBS
bool
true
inpShowRBS
Show DB
bool
true
inpShowDB
Show DT
bool
true
inpShowDT
Show Best Levels
bool
true
inpShowBestQML
Show ISS 1
bool
false
inpShowISS1
Show ISS 2
bool
true
inpShowISS2
Show ISS 3
bool
true
inpShowISS3
Show ISS 4
bool
true
inpShowISS4
Show Only A+ Levels (TJL2, QML, D-CHOCH QML, ISS4)
bool
false
inpShowOnlyAPlus
Enable ISS Logic
bool
true
inpEnableISS
Show ISS Label
bool
true
inpShowISSLabel
Show ISS BOS
bool
true
inpShowISSBOS
Stop ISS 3/4 on Wick Tap
bool
true
inpStopISS34ByWickTap
ISS Scenario
string
1
inpISSScenario
CH Color
color
color.white
inpCHColor
CL Color
color
color.orange
inpCLColor
Bull BOS Color
color
color.green
inpBullBOSColor
Bear BOS Color
color
color.red
inpBearBOSColor
Bull TJL Color
color
color.green
inpBullTJLColor
Bear TJL Color
color
color.orange
inpBearTJLColor
SBR Color
color
color.red
inpSBRColor
RBS Color
color
color.green
inpRBSColor
QML Color
color
color.rgb(186, 85, 211)
inpQMLColor
DT/DB Color
color
color.blue
inpDTDBColor
ISS Color
color
color.yellow
inpISSColor
Best QML Color
color
color.rgb(255, 215, 0)
inpBestQMLColor
Line Width
int
2
inpLineWidth
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.
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
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
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
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
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
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