Fibonacci Levels Based on Supertrend  [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("Supertrend-Fib", overlay = true, max_lines_count = 500, max_labels_count = 500)

// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// |                                   INPUT                                    |
// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// SuperTrend
supAtr = input.int(10, "ATR Length", 1,            group = "Supertrend", inline = "1")
factor = input.float(3.0, "   Factor",             group = "Supertrend", inline = "1")

pltChk = input.bool(true, "Show Supertrend Line?", group = "Supertrend", inline = "2")
upCol  = input.color(color.green, "   ",         group = "Supertrend", inline = "2")
dnCol  = input.color(color.red, "",              group = "Supertrend", inline = "2")

// Table Style 
tablePos = input.string("Top Right", "RunUp Statistics Table Location ", 
             ["Hide", "Top Right" , "Middle Right"  , "Bottom Right" , 
              "Top Center", "Middle Center" , "Bottom Center", 
              "Top Left"  , "Middle Left"   , "Bottom Left" ], inline = "1", group = "Fibonacci Run-Up Historical Statistics Table")

tBgCol = input.color(#696969, "Title",     inline = "2", group = "Fibonacci Run-Up Historical Statistics Table")
cBgCol = input.color(#A9A9A9, "     Cell", inline = "2", group = "Fibonacci Run-Up Historical Statistics Table")
txtCol = input.color(#ffffff, "     Text", inline = "2", group = "Fibonacci Run-Up Historical Statistics Table")

// Line Style
linExt = input.string("None Extend", "Lines ‏ ‏",
         ["Hide", "Right Extend", "Left Extend", "Both Extend", "None Extend"], group = "Line & Label Style", inline = "line")
linSty = input.string("________", "", 
         ["________", "-----------", "..........."],                            group = "Line & Label Style", inline = "line")
linSiz = input.int(2, "", 1, tooltip = "Line Extend | Line Style | Line Size",  group = "Line & Label Style", inline = "line")

// Label Style
lblPos = input.string("Right", "Labels", ["Hide", "Right"],                     group = "Line & Label Style", inline = "label")
lblSty = input.string("Percent", "", 
         ["Percent", "Value", "Price", "Percent & Price", "Value & Price"],     group = "Line & Label Style", inline = "label")
lblSiz = input.string("Small", "", 
         ["Auto", "Huge", "Large", "Normal", "Small", "Tiny"],                  group = "Line & Label Style", inline = "label",
             tooltip = "Label Position | Label Style | Label Size")

// Fibonacci
lastSet = input.bool(true, "Apply Fibonacci Levels to ONLY Last Supertrend Direction", 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(50, "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                                 |
// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// ++++++++++++ Supertrend Indicator
[super, dirc] = ta.supertrend(factor, supAtr)

var intlSupr = float(na),   var rangSupr = float(na)
intlSupr := dirc != dirc[1] ? super                      : intlSupr
rangSupr := dirc != dirc[1] ? math.abs(super - super[1]) : rangSupr

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


// ++++++++++++ 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 = col, style = label.style_label_left, textalign = text.align_left)

// ++++++++++++ Drawing Levels
var runUp  = array.new<float>(na) // Collect RunUp Fib

var linArr = array.new<line>(na)
var labArr = array.new<label>(na)

line trnd  = na
var trndBr = 0

if array.size(inVal) > 0
    if dirc != dirc[1]   
        if confrim ? barstate.isconfirmed : true
            if lastSet
                line.delete(trnd[trndBr])

                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.unshift(runUp, levFib(close))
            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 linExt != "Hide"
                        array.push(linArr, linFunc(bar_index, 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
                            trnd := line.new(bar_index, fibLev(1), bar_index, super, 
                             xloc.bar_index, extend.none, trndCol, line.style_dashed, 1)
                            trndBr := 1

                    // Label
                    if lblPos != "Hide"
                        array.push(labArr, labFun(array.get(inVal, i), linCol))     

    else
        if array.size(runUp) > 0
            runUpLast = array.get(runUp, 0)
            runUpSrc  =  dirc == -1 ? high : low
            array.set(runUp, 0, runUpLast > levFib(runUpSrc) ? runUpLast : levFib(runUpSrc))

        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
            line.set_x2(trnd[trndBr], bar_index)
            trndBr += 1

// Supertrend Plots and Signals
upTrend   = plot(pltChk and dirc < 0 ? super : na, "Up Trend",   upCol, 3, plot.style_linebr)
downTrend = plot(pltChk and dirc > 0 ? super : na, "Down Trend", dnCol, 3, plot.style_linebr)

plotshape(pltChk and dirc < 0 and dirc != dirc[1] ? super : na, "Long",  shape.labelup,   location.absolute, upCol, 0, "LONG",  color.white, display = display.pane, size = size.small)
plotshape(pltChk and dirc > 0 and dirc != dirc[1] ? super : na, "Short", shape.labeldown, location.absolute, dnCol, 0, "SHORT", color.white, display = display.pane, size = size.small)


// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
// |                                 STATISTICS                                 |
// |++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[1] Table
// Get Tbale Location & Size
locNsze(x) => 
    y   = str.split(str.lower(x), " ")
    out = ""
    for i = 0 to array.size(y) - 1
        out := out + array.get(y, i)
        if i != array.size(y) - 1
            out := out + "_"
    out

// Create Table
var tbl = table.new(tablePos != "Hide" ? locNsze(tablePos) : position.top_right, 2, array.size(usVal) + 8,
          frame_width = 1, frame_color = color.new(tBgCol, 100), border_width = 1, border_color = color.new(tBgCol, 100))

perFib(x) => 
    str.contains(lblSty, "Percent") ? str.tostring(x * 100, format.percent) : str.tostring(x, "#.###")

// Cell Function
cell(col, row, txt, color) => 
    table.cell(tbl, col, row, text = txt, text_color = txtCol, bgcolor = color, 
     text_size = size.small)


// Stats Cells
applyCell(row, des, val) =>
    cell(0, row   , des,  tBgCol), table.merge_cells(tbl, 0,    row, 1,    row)
    cell(0, row +1, val,  cBgCol), table.merge_cells(tbl, 0, row +1, 1, row +1)


if barstate.islast and array.size(runUp) > 0 and tablePos != "Hide"
    fibVal = array.copy(usVal)
    array.sort(fibVal, order.descending)

    mtx = matrix.new<float>(array.size(fibVal), 2, 0)
    matrix.add_col(mtx, 0, fibVal)
    totRunUp = array.size(runUp)
    for i = 0 to totRunUp - 1
        runup = array.get(runUp, i)
        for j = 0 to matrix.rows(mtx) - 1
            if not(runup < matrix.get(mtx, j, 0))
                matrix.set(mtx, j, 1, matrix.get(mtx, j, 1) + 1)
                matrix.set(mtx, j, 2, math.round(matrix.get(mtx, j, 1)/totRunUp * 100, 2))
                break

    // Table
    if array.size(fibVal) > 0
        table.clear(tbl, 0, 0, 1, array.size(usVal)+7)

        y = 0
        cell(0, y, "Historical",  tBgCol), table.merge_cells(tbl, 0, 0, 1, 0)
        y += 1

        cell(0, y, "Fibonacci",   tBgCol)
        cell(1, y, "RunUP (%)",   tBgCol)
        y += 1

        for i = 0 to matrix.rows(mtx) - 1
            fib = matrix.get(mtx, i, 0)
            if fib >= 1
                Col = array.get(usCol, array.indexof(usVal, fib))
                cell(0, y, perFib(fib) ,                 Col)
                cell(1, y, str.tostring(matrix.get(mtx, i, 2), format.percent), Col)
                y+=1
        
        // Separator
        table.cell(tbl, 0, y, height = 2), table.merge_cells(tbl, 0, y, 1, y), 
        y += 1
        
        applyCell(y, "Number of Trades", str.tostring(array.size(runUp)))
        y += 2

        applyCell(y, "Median Fib RunUp", perFib(array.median(runUp)))
        y += 2

        applyCell(y, "Mean Fib RunUp", perFib(array.avg(runUp)))
        
