Fibonacci Levels on Any Indicator [By MUQWISHI]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © MUQWISHI

//@version=5
indicator("Fibonacci Levels on Any Indicator", overlay = true, max_bars_back = 500, max_labels_count = 500, max_lines_count = 500)
s = " ‏"

srtNme = input.string("Long", "Start Drawing Condition",  inline = "1", group = "Signal Conditions")
lngCol = input.color(color.green, "",                   inline = "1", group = "Signal Conditions")
lngCon = input.string("Value(1) New Phase", " ",          inline = "1", group = "Signal Conditions", 
                      options = ["Value(1) New Phase", "Value(1) Crosses Above Value(2)", "Value(1) Crosses Below Value(2)", "Value(1) Reversal Up", "Value(1) Reversal Down", "First Bar"], 
                      tooltip = "This section is to specify conditions for when to start drawing Fibonacci levels.\n\nParameters:\n● Name of the signal\n● Color of the signal\n● Condition of the signal")

lngVT1 = input.string("Source", "   Value(1)", ["Source", "Numerical"], inline = "2", group = "Signal Conditions")
lngVS1 = input.source(close, "",                                        inline = "2", group = "Signal Conditions")
lngVN1 = input.float(0, "||",                                           inline = "2", group = "Signal Conditions",
                      tooltip = "Parameters:\n● Type of the value(1)\n● Source: Valid for {Value(1)} = 'Source'\n● Numerical: Valid for {Value(1)} = 'Numerical'")

lngVT2 = input.string("Source", "   Value(2)", ["Source", "Numerical"], inline = "3", group = "Signal Conditions")
lngVS2 = input.source(close, "",                                        inline = "3", group = "Signal Conditions")
lngVN2 = input.float(0, "||",                                           inline = "3",  group = "Signal Conditions", 
                      tooltip = "Parameters:\n● Type of the value(2)\n● Source: Valid for {Value(2)} = 'Source'\n● Numerical: Valid for {Value(2)} = 'Numerical'")


endNme = input.string("Short", "End Drawing Condition" +s+s, inline = "1")
shtCol = input.color(color.red, "",                        inline = "1")
shtCon = input.string("Value(1) New Phase", " ",             inline = "1", 
                      options = ["Value(1) New Phase", "Value(1) Crosses Above Value(2)", "Value(1) Crosses Below Value(2)", "Value(1) Reversal Up", "Value(1) Reversal Down", "Last Bar"],
                      tooltip = "This section is to specify conditions for when to end drawing Fibonacci levels.\n\nParameters:\n● Name of the signal\n● Color of the signal\n● Condition of the signal")

shtVT1 = input.string("Source", "   Value(1)", ["Source", "Numerical"], inline = "2")
shtVS1 = input.source(close, "",                                        inline = "2")
shtVN1 = input.float(0, "||",                                           inline = "2",
                      tooltip = "Parameters:\n● Type of the value(1)\n● Source: Valid for {Value(1)} = 'Source'\n● Numerical: Valid for {Value(1)} = 'Numerical'")

shtVT2 = input.string("Source", "   Value(2)", ["Source", "Numerical"], inline = "3")
shtVS2 = input.source(close, "",                                        inline = "3")
shtVN2 = input.float(0, "||",                                           inline = "3",
                      tooltip = "Parameters:\n● Type of the value(2)\n● Source: Valid for {Value(2)} = 'Source'\n● Numerical: Valid for {Value(2)} = 'Numerical'")

// Fibonacci Pivots
upFibT = input.string("ATR Upper Band", "Upper Pivot ", ["Source", "ATR Upper Band", "Numerical"], inline = "10", group = "Fibonacci Pivots")
upFibS = input.source(close, "",                                                                   inline = "10", group = "Fibonacci Pivots")
upFibN = input.float(0, "||",                                                                      inline = "10", group = "Fibonacci Pivots",
                     tooltip = "Upper Pivot is Fibonacci 100% Level for Long Side. It considers being Fibonacci 0% level for Short Side.\n\nParameters:\n● Type of Upper Fibonacci Pivot\n● Source: Valid for {Upper Pivot} = 'Source'\n● Numerical: Valid for {Upper Pivot} = 'Numerical'\n\nNote:\nATR Upper choice is an arbitrary default value, and it's changeable by choosing source or number.")

lwFibT = input.string("ATR Lower Band", "Lower Pivot ", ["Source", "ATR Lower Band", "Numerical"], inline = "11", group = "Fibonacci Pivots")
lwFibS = input.source(close, "",                                                                   inline = "11", group = "Fibonacci Pivots")
lwFibN = input.float(0, "||",                                                                      inline = "11", group = "Fibonacci Pivots",
                     tooltip = "Upper Pivot is Fibonacci 0% Level for Long Side. It considers being Fibonacci 100% level for Short Side.\n\nParameters:\n● Type of Lower Fibonacci Pivot\n● Source: Valid for {Lower Pivot} = 'Source'\n● Numerical: Valid for {Lower Pivot} = 'Numerical'\n\n\nNote:\nATR Lower choice is an arbitrary default value, and it's changeable by choosing source or number.")

entFrc = input.bool(false, "Force to Set Fibonacci 100% Level at Close of Bar", group = "Fibonacci Pivots")

// ATR
atrLen = input.int(24,  "ATR", 0,                    inline = "10")
atrMlt = input.float(1, "‏ ‏ Mult", 0, inline = "10")
upACol = input.color(color.new(#5255ff, 50), "",   inline = "10")
dnACol = input.color(color.new(#5255ff, 50), "",   inline = "10")
pltAtr = input.bool(false, "Plot",                   inline = "10",
         tooltip = "ATR Bands Valid When\n   {Upper Pivot} = 'ATR Upper Band'\n   {Lower Pivot} = 'ATR Lower Band'\n\nParameters:\n● ATR Length\n● ATR Multiplier\n● Upper Band Color\n● Lower Band Color\n● Show/Hide Plot")


// Line Style
linChk = input.bool(true, "Lines"+s+s,                                                                                    group = "Line & Label Style", inline = "line")
linExt = input.string("None Extend", ""+s+s+s, ["Hide", "Right Extend", "Left Extend", "Both Extend", "None Extend"],     group = "Line & Label Style", inline = "line")
linSty = input.string("________", ""+s+s+s,    ["________", "-----------", "..........."],                                group = "Line & Label Style", inline = "line")
linSiz = input.int(2, "" +s+s+s, 1, tooltip = "Parameters:\n● Show/Hide Lines\n● Line Extend\n● Line Style\n● Line Size", group = "Line & Label Style", inline = "line")

// Label Style
lblChk = input.bool(true, "Labels",                                                                                   group = "Line & Label Style", inline = "label")
lblPos = input.string("Right", ""+s+s+s, ["Right"],                                                                   group = "Line & Label Style", inline = "label")
lblSty = input.string("Percent & Price", ""+s+s+s, ["Percent", "Value", "Price", "Percent & Price", "Value & Price"], group = "Line & Label Style", inline = "label")
lblSiz = input.string("Small", ""+s+s+s, ["Auto", "Huge", "Large", "Normal", "Small", "Tiny"],                        group = "Line & Label Style", inline = "label",
             tooltip = "Parameters:\n● Show/Hide Labels\n● Label Position\n● Label Style\n● Label Size")


// Fibonacci
showSig = input.bool(true, "Show Signals Labels",                           group = "Fibonacci Levels")
lastSet = input.bool(true, "Show Only Last Direction of Fibonacci Levels",  group = "Fibonacci Levels")
reverse = input.bool(false, "Reverse Fibonacci Levels",                     group = "Fibonacci Levels")
confrim = input.bool(true, "Apply Fibonacci Levels After Confirmed Signal", group = "Fibonacci Levels")


bgTrans = input.int(85, "Background Transparency",     0, 100, group = "Fibonacci Levels")
lnTrans = input.int(25, "Line Transparency          ", 0, 100, group = "Fibonacci Levels")

trndChk = input.bool(true, "Show Trend Line",          group = "Fibonacci Levels", inline = "0")
trndCol = input.color(color.new(#64b5f6, 50), "   ", group = "Fibonacci Levels", inline = "0")



shw01 = input.bool(true, "",         group = "Fibonacci Levels", inline = "Level00")
val01 = input.float(0.0, " ",        group = "Fibonacci Levels", inline = "Level00")
col01 = input.color(#787b86, " ",  group = "Fibonacci Levels", inline = "Level00")

shw02 = input.bool(true, "",         group = "Fibonacci Levels", inline = "Level00")
val02 = input.float(0.236, " ",      group = "Fibonacci Levels", inline = "Level00")
col02 = input.color(#f44336," ",   group = "Fibonacci Levels", inline = "Level00")

shw03 = input.bool(true, "",         group = "Fibonacci Levels", inline = "Level01")
val03 = input.float(0.382, " ",      group = "Fibonacci Levels", inline = "Level01")
col03 = input.color(#81c784, " ",  group = "Fibonacci Levels", inline = "Level01")

shw04 = input.bool(true, "",         group = "Fibonacci Levels", inline = "Level01")
val04 = input.float(0.5, " ",        group = "Fibonacci Levels", inline = "Level01")
col04 = input.color(#4caf50, " ",  group = "Fibonacci Levels", inline = "Level01")

shw05 = input.bool(true, "",         group = "Fibonacci Levels", inline = "Level02")
val05 = input.float(0.618, " ",      group = "Fibonacci Levels", inline = "Level02")
col05 = input.color(#009688, " ",  group = "Fibonacci Levels", inline = "Level02")

shw06 = input.bool(true, "",         group = "Fibonacci Levels", inline = "Level02")
val06 = input.float(0.786, " ",      group = "Fibonacci Levels", inline = "Level02")
col06 = input.color(#009688, " ",  group = "Fibonacci Levels", inline = "Level02")

shw07 = input.bool(true, "",         group = "Fibonacci Levels", inline = "Level03")
val07 = input.float(1.0, " ",        group = "Fibonacci Levels", inline = "Level03")
col07 = input.color(#64b5f6, " ",  group = "Fibonacci Levels", inline = "Level03")

shw08 = input.bool(true, "",         group = "Fibonacci Levels", inline = "Level03")
val08 = input.float(1.618, " ",      group = "Fibonacci Levels", inline = "Level03")
col08 = input.color(#da7d31, " ",  group = "Fibonacci Levels", inline = "Level03")

shw09 = input.bool(true, "",         group = "Fibonacci Levels", inline = "Level04")
val09 = input.float(2.1618, " ",     group = "Fibonacci Levels", inline = "Level04")
col09 = input.color(#81c784, " ",  group = "Fibonacci Levels", inline = "Level04")

shw10 = input.bool(true, "",         group = "Fibonacci Levels", inline = "Level04")
val10 = input.float(3.618, " ",      group = "Fibonacci Levels", inline = "Level04")
col10 = input.color(#f44336, " ",  group = "Fibonacci Levels", inline = "Level04")

shw11 = input.bool(true, "",         group = "Fibonacci Levels", inline = "Level05")
val11 = input.float(4.236, " ",      group = "Fibonacci Levels", inline = "Level05")
col11 = input.color(#809ef0, " ",  group = "Fibonacci Levels", inline = "Level05")

shw12 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level05")
val12 = input.float(1.272, " ",      group = "Fibonacci Levels", inline = "Level05")
col12 = input.color(#2962ff, " ",  group = "Fibonacci Levels", inline = "Level05")

shw13 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level06")
val13 = input.float(1.414, " ",      group = "Fibonacci Levels", inline = "Level06")
col13 = input.color(#e97527, " ",  group = "Fibonacci Levels", inline = "Level06")

shw14 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level06")
val14 = input.float(2.272, " ",      group = "Fibonacci Levels", inline = "Level06")
col14 = input.color(#f44336, " ",  group = "Fibonacci Levels", inline = "Level06")

shw15 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level07")
val15 = input.float(2.414, " ",      group = "Fibonacci Levels", inline = "Level07")
col15 = input.color(#9c27b0, " ",  group = "Fibonacci Levels", inline = "Level07")

shw16 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level07")
val16 = input.float(2.0, " ",        group = "Fibonacci Levels", inline = "Level07")
col16 = input.color(#b54df1, " ",  group = "Fibonacci Levels", inline = "Level07")

shw17 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level08")
val17 = input.float(3.0, " ",        group = "Fibonacci Levels", inline = "Level08")
col17 = input.color(#e91e63, " ",  group = "Fibonacci Levels", inline = "Level08")

shw18 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level08")
val18 = input.float(3.272, " ",      group = "Fibonacci Levels", inline = "Level08")
col18 = input.color(#81c784, " ",  group = "Fibonacci Levels", inline = "Level08")

shw19 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level09")
val19 = input.float(3.414, " ",      group = "Fibonacci Levels", inline = "Level09")
col19 = input.color(#f44336, " ",  group = "Fibonacci Levels", inline = "Level09")

shw20 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level09")
val20 = input.float(4.0, " ",        group = "Fibonacci Levels", inline = "Level09")
col20 = input.color(#81c784, " ",  group = "Fibonacci Levels", inline = "Level09")

shw21 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level10")
val21 = input.float(4.272, " ",      group = "Fibonacci Levels", inline = "Level10")
col21 = input.color(#009688, " ",  group = "Fibonacci Levels", inline = "Level10")

shw22 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level10")
val22 = input.float(4.414, " ",      group = "Fibonacci Levels", inline = "Level10")
col22 = input.color(#436d87, " ",  group = "Fibonacci Levels", inline = "Level10")

shw23 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level11")
val23 = input.float(4.618, " ",      group = "Fibonacci Levels", inline = "Level11")
col23 = input.color(#002396, " ",  group = "Fibonacci Levels", inline = "Level11")

shw24 = input.bool(false, "",        group = "Fibonacci Levels", inline = "Level11")
val24 = input.float(4.764, " ",      group = "Fibonacci Levels", inline = "Level11")
col24 = input.color(#006696, " ",  group = "Fibonacci Levels", inline = "Level11")


// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// |                                CALCULATION                                 |
// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// ++++++++++++ ATR Bands
upAtr = ta.ema(high, atrLen) + ta.atr(atrLen) * atrMlt
lwAtr = ta.ema(low,  atrLen) - ta.atr(atrLen) * atrMlt

plot(pltAtr ? upAtr : na, "Atr Upper Band", upACol, 2)
plot(pltAtr ? lwAtr : na, "Atr Lower Band", dnACol, 2)


// ++++++++++++ Set Direction
var shfBr = lngVT1 != "Source" and lngCon == "First Bar" and lngVN1 > 0 ? lngVN1 : 0

terminal(val1, val2, typ) =>
    switch typ
        "Value(1) New Phase"              => na(val1[1]) and val1
        "Value(1) Crosses Above Value(2)" => val1 > val2 and val1[1] <= (na(val2[1]) ? val2 : val2[1])
        "Value(1) Crosses Below Value(2)" => val1 < val2 and val1[1] >= (na(val2[1]) ? val2 : val2[1])
        "Value(1) Reversal Up"            => val1 > val1[1]
        "Value(1) Reversal Down"          => val1 < val1[1]
        "First Bar"                       => lngVT1 != "Source" and val1 > 0 ? barstate.islastconfirmedhistory ? true : false : barstate.isfirst ? true : false
        => false

// Long Direction
lVal1 = lngVT1 == "Source" ? lngVS1 : lngVN1
lVal2 = lngVT2 == "Source" ? lngVS2 : lngVN2
lDirc = terminal(lVal1, lVal2, lngCon) ? 1 : 0

// Short Direction
sVal1 = shtVT1 == "Source" ? shtVS1 : shtVN1
sVal2 = shtVT2 == "Source" ? shtVS2 : shtVN2
sDirc = terminal(sVal1, sVal2, shtCon) ? 1 : 0


// Direction 
var dirc = int(na)
dirc := lDirc == 1 ? (reverse ? 1: -1) : sDirc == 1 ? (reverse ? -1: 1) : dirc

// Set Values For Fib(0%) and Fib(100%)
var baseFib = float(na),   var rangFib = float(na)

if dirc != nz(dirc[1])
    upFibVal = upFibT != "Numerical" and entFrc and dirc < 0 ? close[shfBr] : upFibT == "Source" ? (na(upFibS[shfBr]) ? upFibS[shfBr+1] : upFibS[shfBr]) : upFibT == "ATR Upper Band" ? upAtr[shfBr] : upFibN
    dnFibVal = lwFibT != "Numerical" and entFrc and dirc > 0 ? close[shfBr] : lwFibT == "Source" ? (na(lwFibS[shfBr]) ? lwFibS[shfBr+1] : lwFibS[shfBr]) : lwFibT == "ATR Lower Band" ? lwAtr[shfBr] : lwFibN

    dirc := upFibVal < dnFibVal ? dirc * -1 : dirc

    baseFib := dirc < 0 ? math.min(upFibVal, dnFibVal) : math.max(upFibVal, dnFibVal)
    rangFib := math.abs(upFibVal - dnFibVal)


// Calculate Fib Levels Function
fibLev(x) => baseFib + (dirc == -1 ? rangFib : - rangFib) * x
levFib(x) => (x - baseFib)/ (dirc == -1 ? rangFib : - rangFib)


// ++++++++++++ Entered Fibonacci Levels
var usVal = array.new<float>(na)
var usCol = array.new<color>(na)
usValFun(val, col, flg) =>
    if flg 
        array.push(usVal, val)
        array.push(usCol, col)

if barstate.isfirst
    usValFun(val01, col01, shw01), usValFun(val02, col02, shw02), usValFun(val03, col03, shw03), 
    usValFun(val04, col04, shw04), usValFun(val05, col05, shw05), usValFun(val06, col06, shw06), 
    usValFun(val07, col07, shw07), usValFun(val08, col08, shw08), usValFun(val09, col09, shw09), 
    usValFun(val10, col10, shw10), usValFun(val11, col11, shw11), usValFun(val12, col12, shw12), 
    usValFun(val13, col13, shw13), usValFun(val14, col14, shw14), usValFun(val15, col15, shw15), 
    usValFun(val16, col16, shw16), usValFun(val17, col17, shw17), usValFun(val18, col18, shw18), 
    usValFun(val19, col19, shw19), usValFun(val20, col20, shw20), usValFun(val21, col21, shw21), 
    usValFun(val22, col22, shw22), usValFun(val23, col23, shw23), usValFun(val24, col24, shw24), 

inVal = array.new<float>(na)
for i = 0 to array.size(usVal) - 1
    array.push(inVal, fibLev(array.get(usVal, i)))
array.sort(inVal, dirc < 1 ? order.ascending : order.descending)

// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// |                                  DRAWING                                   |
// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// ++++++++++++ Get Line Style
styLine(s) =>
    switch s
        "..........."  => line.style_dotted   
        "-----------"  => line.style_dashed   
        "________"     => line.style_solid

// ++++++++++++ Get Line Extention
extLine(l) => 
    switch l
        "Right Extend" => extend.right
        "Left Extend"  => extend.left 
        "Both Extend"  => extend.both  
        => extend.none

// ++++++++++++ Get Text Label
txtLab(x) =>
    prt1 = str.contains(lblSty, "Percent") ? str.tostring(levFib(x) * 100, format.percent) + " ": 
           str.contains(lblSty, "Value"  ) ? str.tostring(levFib(x)      , "#.###") + " "       : ""
    prt2 = str.contains(lblSty, "Price")   ? "(" + str.tostring(x, format.mintick) + ")"        : ""
    (dirc > 0 ? "‏ \n" : "") + prt1 + prt2 + (dirc < 0 ? " \n‏" : "")

// ++++++++++++ Line Function
linFunc(x1, y, x2, col) =>
    line.new(x1, y, x2, y, xloc.bar_index, extLine(linExt), color.new(col, lnTrans), styLine(linSty), linSiz)

// ++++++++++++ Label Function 
labFun(y, col) =>
    label.new(bar_index, y, txtLab(y), color = color.new(col, 100), size = str.lower(lblSiz), 
     textcolor = color.new(col, lnTrans), style = label.style_label_left, textalign = text.align_left)

// ++++++++++++ Drawing Fibonacci
var linArr = array.new<line>(na)
var labArr = array.new<label>(na)
var linTrd = array.new<line>(na)

var trndBr = 0
if array.size(inVal) > 0 
    if rangFib > 0 and dirc != (lngCon == "First Bar" ? nz(dirc[1]) : dirc[1])
        if confrim ? barstate.isconfirmed : true
            if lastSet
                while array.size(linTrd) > 0
                    line.delete(array.shift(linTrd))
                
                while array.size(linArr) > 0
                    line.delete(array.shift(linArr))
                
                while array.size(labArr) > 0
                    label.delete(array.shift(labArr))
            else
                if array.size(linArr) > 0
                    for i = 0 to array.size(linArr) - 1
                        line.set_extend(array.get(linArr, i), extend.none)
                    
                if array.size(labArr) > 0
                    for i = 0 to array.size(labArr) - 1
                        label.set_style(array.get(labArr, i), label.style_label_right)
                    
                array.clear(linArr)
                array.clear(labArr)
                array.clear(linTrd)

            trndBr := 0
            for i = 0 to array.size(inVal) - 1
                if not na(array.get(inVal, i))
                    linCol = array.get(usCol, array.indexof(usVal, levFib(array.get(inVal, i))))

                    // Line
                    if linChk
                        array.push(linArr, linFunc(bar_index[shfBr], array.get(inVal, i), bar_index, linCol))

                        if array.size(linArr) >  1
                            linefill.new(array.get(linArr, array.size(linArr)-2), 
                                         array.get(linArr, array.size(linArr)-1), 
                                         color.new(linCol, bgTrans))

                        if trndChk and trndBr == 0
                            array.push(linTrd, line.new(bar_index[shfBr], fibLev(1), bar_index, fibLev(0), 
                             xloc.bar_index, extend.none, trndCol, line.style_dashed, 1))
                            trndBr := 1

                    // Label
                    if lblChk
                        array.push(labArr, labFun(array.get(inVal, i), linCol))     

    else
        if array.size(linArr) > 0
            for i = 0 to array.size(linArr) - 1
                line.set_x2(array.get(linArr, i), bar_index)
        
        if array.size(labArr) > 0
            for i = 0 to array.size(labArr) - 1
                label.set_x(array.get(labArr, i), bar_index)
        
        if trndChk
            if array.size(linTrd) > 0
                line.set_x2(array.get(linTrd, 0), bar_index)


if showSig and array.size(inVal) > 0 
    if dirc != (lngCon == "First Bar" ? nz(dirc[1]) : dirc[1])
        label.new(bar_index[shfBr], baseFib,  (reverse and dirc > 0) or (not reverse and dirc < 0) ? srtNme : endNme, xloc.bar_index, yloc.price, 
                  (reverse and dirc > 0) or (not reverse and dirc < 0) ? lngCol : shtCol, dirc < 0 ? label.style_label_up : label.style_label_down, color.white)
