MTF ATR Reversal Levels (Open Source)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// Some code has been borowed from multiple open sources but the heart of the code is from the Blackflag FTS Indicator
// provided by https://www.tradingview.com/u/vsnfnd/

// @DeuceDavis aka JustDeuce

//@version=5
indicator('MTF ATR Reversal Levels', overlay=true)


// inputs //
//{
trailType = input.string('modified', 'Trailtype', options=['modified', 'unmodified'])
ATRPeriod = input(28, 'ATR Period')
ATRFactor = input.float(3.0, 'ATR Factor', step=0.1)
ATRAlertThreshold = input.float(1, 'ATR Alert Threshold', step=0.1)

showCurrentReversalLevel = input(true, 'Show Current Bar Reversal Levels (Horizontal Line')
offsetLabels = input(title='Offset Labels', defval=false)
showReversalLevel = input(false, 'Plot Historical Reversal Levels')

showTrendChangeAlert = input(title='Show Trend Change Buy/Sell Alert', defval=true)
conservativeAlert = input(title='Alert After Pullback', defval=false)



//Inputs
res1Start = input(title='------------Primary Resolution Settings----------', defval=false)
res1 = input.timeframe(title='Resolution 1', defval='Chart TF', options=['Chart TF', '1m', '3m', '5m', '15m', '30m', '45m', '1H', '2H', '3H', '4H', 'Daily', 'Weekly', 'Monthly'])
showRes1Fibs = input(title='Show Fibonacci Reversal Cloud', defval=false)
fibLevel1 = input(title='Fibonacci Level 1', defval=50.0)
fibLevel2 = input(title='Fibonacci Level 2', defval=61.8)
fibLevel3 = input(title='Fibonacci Level 3', defval=78.6)

extraResolutions = input(title='------------Other Resolution Settings----------', defval=false)


res2 = input.timeframe(title='Resolution 2', defval='15m', options=['Chart TF', '1m', '3m', '5m', '15m', '30m', '45m', '1H', '2H', '3H', '4H', 'Daily', 'Weekly', 'Monthly'])

res3 = input.timeframe(title='Resolution 3', defval='30m', options=['Chart TF', '1m', '3m', '5m', '15m', '30m', '45m', '1H', '2H', '3H', '4H', 'Daily', 'Weekly', 'Monthly'])

res4 = input.timeframe(title='Resolution 4', defval='1H', options=['Chart TF', '1m', '3m', '5m', '15m', '30m', '45m', '1H', '2H', '3H', '4H', 'Daily', 'Weekly', 'Monthly'])

res5 = input.timeframe(title='Resolution 5', defval='Daily', options=['Chart TF', '1m', '3m', '5m', '15m', '30m', '45m', '1H', '2H', '3H', '4H', 'Daily', 'Weekly', 'Monthly'])



//inputs for to choose timeframe resolution of calculations
resLookUp(Resolution) =>
    if Resolution == 'Chart TF'
        timeframe.period
    else
        if Resolution == '1m'
            '1'
        else
            if Resolution == '3m'
                '3'
            else
                if Resolution == '5m'
                    '5'
                else
                    if Resolution == '15m'
                        '15'
                    else
                        if Resolution == '30m'
                            '30'
                        else
                            if Resolution == '45m'
                                '45'
                            else
                                if Resolution == '1H'
                                    '60'
                                else
                                    if Resolution == '2H'
                                        '120'
                                    else
                                        if Resolution == '3H'
                                            '180'
                                        else
                                            if Resolution == '4H'
                                                '240'
                                            else
                                                if Resolution == 'Daily'
                                                    '1D'
                                                else
                                                    if Resolution == 'Weekly'
                                                        '1W'
                                                    else
                                                        if Resolution == 'Monthly'
                                                            '1M'




plotTransp = showReversalLevel ? 50 : 100
plotCurrentTransp = showCurrentReversalLevel ? 50 : 100
supportColor = color.new(color.lime, plotTransp)
resistanceColor = color.new(color.red, plotTransp)
currentSupportColor = color.new(color.lime, plotCurrentTransp)
currentResistanceColor = color.new(color.red, plotCurrentTransp)


//}

//////// FUNCTIONS //////////////
//{
// Wilders ma //
Wild_ma(_src, _malength) =>
    _wild = 0.0
    _wild := nz(_wild[1]) + (_src - nz(_wild[1])) / _malength
    _wild

// RoundToTickUp() rounds the given value up to the next tick,
// using the tick size of the chart's instrument.
RoundToTick(value) =>
    math.floor(value / syminfo.mintick) * syminfo.mintick

/////////// TRUE RANGE CALCULATIONS /////////////////

trueRanges(res) =>
    norm_o = request.security(syminfo.tickerid, res, open)
    norm_h = request.security(syminfo.tickerid, res, high)
    norm_l = request.security(syminfo.tickerid, res, low)
    norm_c = request.security(syminfo.tickerid, res, close)
    HiLo = request.security(syminfo.tickerid, res, math.min(norm_h - norm_l, 1.5 * nz(ta.sma(norm_h - norm_l, ATRPeriod))))
//    HiLo = min(norm_h - norm_l, 1.5 * nz(sma((norm_h - norm_l), ATRPeriod)))


    HRef = request.security(syminfo.tickerid, res, norm_l <= norm_h[1] ? norm_h - norm_c[1] : norm_h - norm_c[1] - 0.5 * (norm_l - norm_h[1]))

    LRef = request.security(syminfo.tickerid, res, norm_h >= norm_l[1] ? norm_c[1] - norm_l : norm_c[1] - norm_l - 0.5 * (norm_l[1] - norm_h))

    trueRange = request.security(syminfo.tickerid, res, trailType == 'modified' ? math.max(HiLo, HRef, LRef) : math.max(norm_h - norm_l, math.abs(norm_h - norm_c[1]), math.abs(norm_l - norm_c[1])))
//}


/////////// TRADE LOGIC ////////////////////////
//{
    loss = ATRFactor * request.security(syminfo.tickerid, res, Wild_ma(trueRange, ATRPeriod))

    Up = norm_c - loss
    Dn = norm_c + loss

    TrendUp = Up
    TrendDown = Dn
    Trend = 1

    var float trail = na

    TrendUp := norm_c[1] > TrendUp[1] ? math.max(Up, TrendUp[1]) : Up
    TrendDown := norm_c[1] < TrendDown[1] ? math.min(Dn, TrendDown[1]) : Dn

    Trend := norm_c > TrendDown[1] ? 1 : norm_c < TrendUp[1] ? -1 : nz(Trend[1], 1)
    trail := Trend == 1 ? TrendUp : TrendDown
    trail := RoundToTick(trail)
    //trail := Trend == na ? trail[1] :
    //     Trend == 1 ? TrendUp : TrendDown


    ex = 0.0
    ex := ta.crossover(Trend, 0) ? norm_h : ta.crossunder(Trend, 0) ? norm_l : Trend == 1 ? math.max(ex[1], norm_h) : Trend == -1 ? math.min(ex[1], norm_l) : ex[1]

    fib1Level = fibLevel1
    fib2Level = fibLevel2
    fib3Level = fibLevel3

    f1 = RoundToTick(ex + (trail - ex) * fib1Level / 100)
    f2 = RoundToTick(ex + (trail - ex) * fib2Level / 100)
    f3 = RoundToTick(ex + (trail - ex) * fib3Level / 100)

    atrValue = Wild_ma(trueRange, ATRPeriod)
    trueRangeRatio = trueRange / atrValue[1]

    [trail, Trend, ex, f1, f2, f3, trueRangeRatio]


//{
[trail1, Trend1, ex1, f1_1, f2_1, f3_1, atrRatio1] = trueRanges(resLookUp(res1))
[trail2, Trend2, ex2, f1_2, f2_2, f3_2, atrRatio2] = trueRanges(resLookUp(res2))
[trail3, Trend3, ex3, f1_3, f2_3, f3_3, atrRatio3] = trueRanges(resLookUp(res3))
[trail4, Trend4, ex4, f1_4, f2_4, f3_4, atrRatio4] = trueRanges(resLookUp(res4))
[trail5, Trend5, ex5, f1_5, f2_5, f3_5, atrRatio5] = trueRanges(resLookUp(res5))



t1 = plot(trail1, 'Reversal Res 1', style=plot.style_line, color=Trend1 == 1 ? supportColor : Trend1 == -1 ? resistanceColor : na)
t2 = plot(trail2, 'Reversal Res 2', style=plot.style_line, color=Trend2 == 1 ? supportColor : Trend2 == -1 ? resistanceColor : na)
t3 = plot(trail3, 'Reversal Res 3', style=plot.style_line, color=Trend3 == 1 ? supportColor : Trend3 == -1 ? resistanceColor : na)
t4 = plot(trail4, 'Reversal Res 4', style=plot.style_line, color=Trend4 == 1 ? supportColor : Trend4 == -1 ? resistanceColor : na)
t5 = plot(trail5, 'Reversal Res 5', style=plot.style_line, color=Trend5 == 1 ? supportColor : Trend5 == -1 ? resistanceColor : na)

t1_fib1 = plot(f1_1, title='f1_1', color=color.new(color.black, 100))
t1_fib2 = plot(f2_1, title='f2_1', color=color.new(color.black, 100))
t1_fib3 = plot(f3_1, title='f3_1', color=color.new(color.black, 100))


t2_fib1 = plot(f1_2, title='f1_2', color=color.new(color.black, 100))
t2_fib2 = plot(f2_2, title='f2_2', color=color.new(color.black, 100))
t2_fib3 = plot(f3_2, title='f3_2', color=color.new(color.black, 100))

t3_fib1 = plot(f1_3, title='f1_3', color=color.new(color.black, 100))
t3_fib2 = plot(f2_3, title='f2_3', color=color.new(color.black, 100))
t3_fib3 = plot(f3_3, title='f3_3', color=color.new(color.black, 100))

t4_fib1 = plot(f1_4, title='f1_4', color=color.new(color.black, 100))
t4_fib2 = plot(f2_4, title='f2_4', color=color.new(color.black, 100))
t4_fib3 = plot(f3_4, title='f3_4', color=color.new(color.black, 100))

t5_fib1 = plot(f1_5, title='f1_5', color=color.new(color.black, 100))
t5_fib2 = plot(f2_5, title='f2_5', color=color.new(color.black, 100))
t5_fib3 = plot(f3_5, title='f3_5', color=color.new(color.black, 100))




//Color Logic

l1Color = Trend1 == 1 ? currentSupportColor : Trend1 == -1 ? currentResistanceColor : na
l2Color = Trend2 == 1 ? currentSupportColor : Trend2 == -1 ? currentResistanceColor : na
l3Color = Trend3 == 1 ? currentSupportColor : Trend3 == -1 ? currentResistanceColor : na
l4Color = Trend4 == 1 ? currentSupportColor : Trend4 == -1 ? currentResistanceColor : na
l5Color = Trend5 == 1 ? currentSupportColor : Trend5 == -1 ? currentResistanceColor : na



//Lines and Labels
if barstate.islast

    l1 = line.new(x1=bar_index[1], y1=trail1, x2=bar_index, y2=trail1, extend=extend.right, width=3, color=l1Color)


    l2 = line.new(x1=bar_index[1], y1=trail2, x2=bar_index, y2=trail2, extend=extend.right, width=3, color=l2Color)


    l3 = line.new(x1=bar_index[1], y1=trail3, x2=bar_index, y2=trail3, extend=extend.right, width=3, color=l3Color)


    l4 = line.new(x1=bar_index[1], y1=trail4, x2=bar_index, y2=trail4, extend=extend.right, width=3, color=l4Color)

    l5 = line.new(x1=bar_index[1], y1=trail5, x2=bar_index, y2=trail5, extend=extend.right, width=3, color=l5Color)

    line.delete(l1[1])
    line.delete(l2[1])
    line.delete(l3[1])
    line.delete(l4[1])
    line.delete(l5[1])

    label1Text = str.tostring(res1) + ': ' + str.tostring(trail1, '0.00') + '|TR:ATR:' + str.tostring(atrRatio1, '0.00')
    label1 = label.new(x=bar_index, y=trail1, color=l1Color, textcolor=color.white, style=label.style_label_lower_left)
    label.set_text(id=label1, text=label1Text)
    label.set_xy(label1, offsetLabels ? bar_index + 5 : bar_index + 2, trail1)
    label.delete(label1[1])

    label2Text = str.tostring(res2) + ': ' + str.tostring(trail2, '0.00') + '|TR:ATR:' + str.tostring(atrRatio2, '0.00')
    label2 = label.new(x=bar_index, y=trail2, color=l2Color, textcolor=color.white, style=label.style_label_lower_left)
    label.set_text(id=label2, text=label2Text)
    label.set_xy(label2, offsetLabels ? bar_index + 15 : bar_index + 2, trail2)
    label.delete(label2[1])

    label3Text = str.tostring(res3) + ': ' + str.tostring(trail3, '0.00') + '|TR:ATR:' + str.tostring(atrRatio3, '0.00')
    label3 = label.new(x=bar_index, y=trail3, color=l3Color, textcolor=color.white, style=label.style_label_lower_left)
    label.set_text(id=label3, text=label3Text)
    label.set_xy(label3, offsetLabels ? bar_index + 20 : bar_index + 2, trail3)
    label.delete(label3[1])

    label4Text = str.tostring(res4) + ': ' + str.tostring(trail4, '0.00') + '|TR:ATR:' + str.tostring(atrRatio4, '0.00')
    label4 = label.new(x=bar_index, y=trail4, color=l4Color, textcolor=color.white, style=label.style_label_lower_left)
    label.set_text(id=label4, text=label4Text)
    label.set_xy(label4, offsetLabels ? bar_index + 25 : bar_index + 2, trail4)
    label.delete(label4[1])

    label5Text = str.tostring(res5) + ': ' + str.tostring(trail5, '0.00') + '|TR:ATR:' + str.tostring(atrRatio5, '0.00')
    label5 = label.new(x=bar_index, y=trail5, color=l5Color, textcolor=color.white, style=label.style_label_lower_left)
    label.set_text(id=label5, text=label5Text)
    label.set_xy(label5, offsetLabels ? bar_index + 30 : bar_index + 2, trail5)
    label.delete(label5[1])


//Paint Reversal Clouds


fib1Color = showRes1Fibs ? color.new(l1Color, 90) : na
fill(t1, t1_fib1, fib1Color)
fill(t1, t1_fib2, fib1Color)
fill(t1, t1_fib3, fib1Color)


//Trade Trigger (Crossover of Any Reversal Leval)

ATRTrendIndex = Trend1 + Trend2 + Trend3 + Trend4 + Trend5

labelText = 
     Trend1 != Trend1[1] ? res1 : 
     Trend2 != Trend2[1] ? res2 : 
     Trend3 != Trend3[1] ? res3 : 
     Trend4 != Trend4[1] ? res4 : 
     Trend5 != Trend5[1] ? res5 : na


TRRatioThresholdMet = 
     (atrRatio1 >= ATRAlertThreshold and Trend1 != Trend1[1]) 
     or 
     (atrRatio2 >= ATRAlertThreshold and Trend2 != Trend2[1])
     or 
     (atrRatio3 >= ATRAlertThreshold and Trend3 != Trend3[1])
     or 
     (atrRatio4 >= ATRAlertThreshold and Trend4 != Trend4[1])
     or 
     (atrRatio5 >= ATRAlertThreshold and Trend5 != Trend5[1])
     

tradeTrigger = ATRTrendIndex != ATRTrendIndex[1]
buySignal = tradeTrigger and ATRTrendIndex > ATRTrendIndex[1] and TRRatioThresholdMet
sellSignal = tradeTrigger and ATRTrendIndex < ATRTrendIndex[1] and TRRatioThresholdMet


if buySignal and showTrendChangeAlert
    buyLabel = label.new(x=bar_index, y=low - 5, color=color.green, textcolor=color.white, style=label.style_label_up, text=labelText + '\nBuy')
    alert('ALERT: ATR Bullish Cross:' + labelText, alert.freq_once_per_bar)

if sellSignal and showTrendChangeAlert
    sellLabel = label.new(x=bar_index, y=high + 5, color=color.red, textcolor=color.white, style=label.style_label_down, text=labelText + '\nSell')

    alert('ALERT: ATR Bearish Cross:' + labelText, alert.freq_once_per_bar)

