Swing Failure Pattern by EmreKb
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © EmreKb

//@version=5
indicator("Swing Failure Pattern", "SFP", overlay=true, max_bars_back=4900)

lookback = 4899
is_opposite = input.bool(false, "Candle should be opposite direction", group="settings")
plen = input.int(21, "Pivot Lenght", 1, 99, group="settings")
textcolor = input.color(color.orange, "Text Color", group="display")
position = input.string(position.top_right, "Table Position", [position.top_right, position.top_left, position.bottom_right, position.bottom_left], group="table")
textcolortbl = input.color(color.orange, "Table Text Color", group="table")

ph = ta.pivothigh(plen, 0)
pl = ta.pivotlow(plen, 0)

f_get_candle(_index) =>
    [open[_index], high[_index], low[_index], close[_index], bar_index[_index]]
    

f_is_candle_up(_open, _close) =>
    _open < _close
    

f_sfp() =>
    [so, sh, sl, sc, si] = f_get_candle(0)
    
    // High SFP
    hc1 = ph
    maxp = high[1]
    hc2 = false
    hx = 0
    hy = 0.0
    for i=1 to lookback
        [co, ch, cl, cc, ci] = f_get_candle(i)
        if ch >= sh
            break
        if ch < sh and ch > math.max(so, sc) and ph[bar_index - ci] and ch > maxp
            hc2 := true
            hx := bar_index[i]
            hy := ch
        if ch > maxp
            maxp := ch
    
    hcs = hc1 and hc2
    
    // Low SFP
    lc1 = pl
    minp = low[1]
    lc2 = false
    lx = 0
    ly = 0.0
    for i=2 to lookback
        [co, ch, cl, cc, ci] = f_get_candle(i)
        if cl < sl
            break
        if sl < cl and math.min(so, sc) > cl and pl[bar_index - ci] and cl < minp
            lc2 := true
            lx := bar_index[i]
            ly := cl
        if cl < minp
            minp := cl
    
    
    lcs = lc1 and lc2
    
    [hcs, hx, hy, lcs, lx, ly]
    

f_control(_tf) =>
    [_hsfp, _hx, _hy, _lsfp, _lx, _ly] = request.security(syminfo.tickerid, _tf, f_sfp())
    _hsfp or _lsfp or _hsfp[1] or _lsfp[1]
    
    
f_multitimeframe() =>
    tbl = table.new(position, 1, 1)
    txt = ""
    if f_control("5")
        txt := txt + "5m SFP Detected\n"
    if f_control("15")
        txt := txt + "15m SFP Detected\n"
    if f_control("30")
        txt := txt + "30m SFP Detected\n"
    if f_control("60")
        txt := txt + "1h SFP Detected\n"
    if f_control("120")
        txt := txt + "2h SFP Detected\n"
    if f_control("240")
        txt := txt + "4h SFP Detected\n"
    
    table.cell(tbl, 0, 0, txt, text_color=textcolortbl, text_size=size.small)


[hsfp, hx, hy, lsfp, lx, ly] = f_sfp()

hsfp := is_opposite ? hsfp and open > close : hsfp
lsfp := is_opposite ? lsfp and open < close : lsfp

if hsfp
    line.new(hx, hy, bar_index + 1, hy, color=color.red)
    alert("High SFP Detected!", alert.freq_once_per_bar)
plotshape(hsfp?high:na, "High SFP", style=shape.triangledown, location=location.abovebar, color=color.red, text="SFP", textcolor=color.red, size=size.tiny)

if lsfp
    line.new(lx, ly, bar_index + 1, ly, color=color.green)
    alert("Low SFP Detected!", alert.freq_once_per_bar)
plotshape(lsfp?low:na, "Low SFP", style=shape.triangleup, location=location.belowbar, color=color.green, text="SFP", textcolor=color.green, size=size.tiny)

f_multitimeframe()