SMC Indicator With Webhook
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © sunwoo101

//@version=5
indicator("Simple SMC Indicator", overlay = true)

// Settings
// Price Action
onlyDrawInSession = input(false, "Only Draw In Session", group = "Price Action")

drawFractals = input(true, "Draw Fractal Highs/Lows", group = "Price Action")
fractalPeriod = input.int(title="Fractal Periods", defval=2, minval=1)
fractalHighColor = input(color.new(color.white, 50), "Fractal High Color", group = "Price Action")
fractalLowColor = input(color.new(color.white, 50), "Fractal Low Color", group = "Price Action")

drawLQSweeps = input(true, "Draw Liquidity Sweeps", group = "Price Action")
sweepColor = input(color.white, "Sweep Color", group = "Price Action")

drawMSS = input(true, "Draw MSS", group = "Price Action")
bullishMSSColor = input(color.blue, "Bullish MSS Color", group = "Price Action")
bearishMSSColor = input(color.red, "Bearish MSS Color", group = "Price Action")

drawFVG = input(true, "Draw FVG", group = "Price Action")
bullishFVGColor = input(color.new(color.white, 50), "Bullish FVG Color", group = "Price Action")
bearishFVGColor = input(color.new(color.white, 50), "Bearish FVG Color", group = "Price Action")

// Alerts
alertName = input("1m XAUUSD", "Alert Name")
sweepAlerts = input(true, "Sweep Alerts", group = "Alerts")
MSSAlerts = input(true, "MSS Alerts", group = "Alerts")
FVGAlerts = input(true, "FVG Alerts", group = "Alerts")

// Sessions
drawSession1 = input(true, "Draw Session 1", group = "Session")
session1 = input.session("2100-0100", "Session 1", group = "Session")
session1Color = input(color.new(color.purple, 80), "Session 1 Color", group = "Session")
drawSession2 = input(true, "Draw Session 2", group = "Session")
session2 = input.session("0300-0600", "Session 2", group = "Session")
session2Color = input(color.new(color.yellow, 80), "Session 2 Color", group = "Session")
drawSession3 = input(true, "Draw Session 3", group = "Session")
session3 = input.session("0800-1000", "Session 3", group = "Session")
session3Color = input(color.new(color.blue, 80), "Session 3 Color", group = "Session")
drawSession4 = input(true, "Draw Session 4", group = "Session")
session4 = input.session("1100-1300", "Session 4", group = "Session")
session4Color = input(color.new(color.orange, 80), "Session 4 Color", group = "Session")

is_session(sess) =>
    not na(time(timeframe.period, sess, "America/New_York"))

isSession1 = is_session(session1)
isSession2 = is_session(session2)
isSession3 = is_session(session3)
isSession4 = is_session(session4)

backgroundColor = isSession1 ? session1Color : isSession2 ? session2Color : isSession3 ? session3Color : isSession4 ? session4Color : color.new(color.blue, 90)

isSession = isSession1 or isSession2 or isSession3 or isSession4
drawSession = isSession1 and drawSession1 or isSession2 and drawSession2 or isSession3 and drawSession3 or isSession4 and drawSession4
bgcolor(isSession and drawSession ? backgroundColor : na)

sessionDraw = not onlyDrawInSession or onlyDrawInSession and drawSession

// Fractal highs and lows
var fractalHighBarIndex = int(na)
var fractalLowBarIndex = int(na)
n = fractalPeriod

// Fractal high
bool upflagDownFrontier = true
bool upflagUpFrontier0 = true
bool upflagUpFrontier1 = true
bool upflagUpFrontier2 = true
bool upflagUpFrontier3 = true
bool upflagUpFrontier4 = true

highFound = false
lowFound = false

if barstate.isconfirmed
    for i = 1 to n
        upflagDownFrontier := upflagDownFrontier and (high[n-i] < high[n])
        upflagUpFrontier0 := upflagUpFrontier0 and (high[n+i] < high[n])
        upflagUpFrontier1 := upflagUpFrontier1 and (high[n+1] <= high[n] and high[n+i + 1] < high[n])
        upflagUpFrontier2 := upflagUpFrontier2 and (high[n+1] <= high[n] and high[n+2] <= high[n] and high[n+i + 2] < high[n])
        upflagUpFrontier3 := upflagUpFrontier3 and (high[n+1] <= high[n] and high[n+2] <= high[n] and high[n+3] <= high[n] and high[n+i + 3] < high[n])
        upflagUpFrontier4 := upflagUpFrontier4 and (high[n+1] <= high[n] and high[n+2] <= high[n] and high[n+3] <= high[n] and high[n+4] <= high[n] and high[n+i + 4] < high[n])
    flagUpFrontier = upflagUpFrontier0 or upflagUpFrontier1 or upflagUpFrontier2 or upflagUpFrontier3 or upflagUpFrontier4

    highFound := (upflagDownFrontier and flagUpFrontier)

    if highFound
        fractalHighBarIndex := bar_index[fractalPeriod]

    // Fractal low
    bool downflagDownFrontier = true
    bool downflagUpFrontier0 = true
    bool downflagUpFrontier1 = true
    bool downflagUpFrontier2 = true
    bool downflagUpFrontier3 = true
    bool downflagUpFrontier4 = true

    for i = 1 to n
        downflagDownFrontier := downflagDownFrontier and (low[n-i] > low[n])
        downflagUpFrontier0 := downflagUpFrontier0 and (low[n+i] > low[n])
        downflagUpFrontier1 := downflagUpFrontier1 and (low[n+1] >= low[n] and low[n+i + 1] > low[n])
        downflagUpFrontier2 := downflagUpFrontier2 and (low[n+1] >= low[n] and low[n+2] >= low[n] and low[n+i + 2] > low[n])
        downflagUpFrontier3 := downflagUpFrontier3 and (low[n+1] >= low[n] and low[n+2] >= low[n] and low[n+3] >= low[n] and low[n+i + 3] > low[n])
        downflagUpFrontier4 := downflagUpFrontier4 and (low[n+1] >= low[n] and low[n+2] >= low[n] and low[n+3] >= low[n] and low[n+4] >= low[n] and low[n+i + 4] > low[n])
    flagDownFrontier = downflagUpFrontier0 or downflagUpFrontier1 or downflagUpFrontier2 or downflagUpFrontier3 or downflagUpFrontier4

    lowFound := (downflagDownFrontier and flagDownFrontier)

    if lowFound
        fractalLowBarIndex := bar_index[fractalPeriod]

    // MSS vars
    var bullishMSSTargetBarIndex = int(na)
    var bearishMSSTargetBarIndex = int(na)

    // Sweeps
    // BSL sweep
    if fractalHighBarIndex
        if high > high[bar_index - fractalHighBarIndex]
            // Draw sweep
            if drawLQSweeps and sessionDraw
                line.new(x1 = fractalHighBarIndex, y1 = high[bar_index - fractalHighBarIndex], x2 = bar_index, y2 = high[bar_index - fractalHighBarIndex], color = sweepColor, width = 1)
                label.new(fractalHighBarIndex, na, "Swept", yloc = yloc.abovebar, style = label.style_none, textcolor = sweepColor, size = size.small)

                if sweepAlerts and sessionDraw
                    message = '{"content": "@everyone \\n['+alertName+'] Buy side $$$ swept @ '+str.tostring(high[bar_index - fractalHighBarIndex])+'"}'
                    alert(message)

            // Find MSS target
            lowestLowOffset = 1
            for i = 1 to bar_index - fractalHighBarIndex
                if low[i] < low[lowestLowOffset]
                    lowestLowOffset := i
            bearishMSSTargetBarIndex := bar_index[lowestLowOffset]

            fractalHighBarIndex := int(na)

    // SSL sweep
    if fractalLowBarIndex
        if low < low[bar_index - fractalLowBarIndex]
            // Draw sweep
            if drawLQSweeps and sessionDraw
                line.new(x1 = fractalLowBarIndex, y1 = low[bar_index - fractalLowBarIndex], x2 = bar_index, y2 = low[bar_index - fractalLowBarIndex], color = sweepColor, width = 1)
                label.new(fractalLowBarIndex, na, "Swept", yloc = yloc.belowbar, style = label.style_none, textcolor = sweepColor, size = size.small)

                if sweepAlerts and sessionDraw
                    message = '{"content": "@everyone \\n['+alertName+'] Sell side $$$ swept @ '+str.tostring(low[bar_index - fractalLowBarIndex])+'"}'
                    alert(message)

            // Find MSS target
            highestHighOffset = 1
            for i = 1 to bar_index - fractalLowBarIndex
                if high[i] > high[highestHighOffset]
                    highestHighOffset := i
            bullishMSSTargetBarIndex := bar_index[highestHighOffset]

            fractalLowBarIndex := int(na)

    // MSS
    // Bearish MSS
    if bearishMSSTargetBarIndex
        if close < low[bar_index - bearishMSSTargetBarIndex]
            if drawMSS and sessionDraw
                line.new(x1 = bearishMSSTargetBarIndex, y1 = low[bar_index - bearishMSSTargetBarIndex], x2 = bar_index, y2 = low[bar_index - bearishMSSTargetBarIndex], color = bearishMSSColor, width = 2)
                label.new(bar_index, na, "MSS", yloc = yloc.abovebar, style = label.style_none, textcolor = bearishMSSColor, size = size.normal)

            if MSSAlerts and sessionDraw
                message = '{"content": "@everyone \\n['+alertName+'] Bearish MSS through '+str.tostring(low[bar_index - bearishMSSTargetBarIndex])+'"}'
                alert(message)

            bearishMSSTargetBarIndex := int(na)

    // Bullish MSS
    if bullishMSSTargetBarIndex
        if close > high[bar_index - bullishMSSTargetBarIndex]
            if drawMSS and sessionDraw
                line.new(x1 = bullishMSSTargetBarIndex, y1 = high[bar_index - bullishMSSTargetBarIndex], x2 = bar_index, y2 = high[bar_index - bullishMSSTargetBarIndex], color = bullishMSSColor, width = 2)
                label.new(bar_index, na, "MSS", yloc = yloc.belowbar, style = label.style_none, textcolor = bullishMSSColor, size = size.normal)

            if MSSAlerts and sessionDraw
                message = '{"content": "@everyone \\n['+alertName+'] Bullish MSS through '+str.tostring(high[bar_index - bullishMSSTargetBarIndex])+'"}'
                alert(message)

            bullishMSSTargetBarIndex := int(na)

    // FVG
    // Bullish FVG
    if low > high[2] and close[1] > open[1] and sessionDraw
        if drawFVG and sessionDraw
            box.new(left=bar_index[2], top=low, right=bar_index, bottom=high[2], bgcolor=bullishFVGColor, border_color = bullishFVGColor)

        if FVGAlerts and sessionDraw
            message = '{"content": "@everyone \\n['+alertName+'] Bullish FVG ('+str.tostring(high[2])+' - '+str.tostring(low)+')"}'
            alert(message)

    // Bearish FVG
    if high < low[2] and close[1] < open[1] and sessionDraw
        if drawFVG and sessionDraw
            box.new(left=bar_index[2], top=high, right=bar_index, bottom=low[2], bgcolor=bearishFVGColor, border_color = bearishFVGColor)

        if FVGAlerts and sessionDraw
            message = '{"content": "@everyone \\n['+alertName+'] Bearish FVG ('+str.tostring(low[2])+' - '+str.tostring(high)+')"}'
            alert(message)

plotshape(drawFractals and highFound and sessionDraw, style=shape.triangledown, location=location.abovebar, offset=-fractalPeriod, color=fractalHighColor, size = size.tiny)
plotshape(drawFractals and lowFound and sessionDraw, style=shape.triangleup, location=location.belowbar, offset=-fractalPeriod, color=fractalLowColor, size = size.tiny)