[MAD] Fibonacci retracement
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © djmad
//@version=5

indicator('[MAD] Fib retracement', overlay=true)

int Starttime               =   input.time(timestamp("2020-02-19"),title= "B O T T O M  -   L E F T", inline="B O T T O M  -   L E F T", confirm = true,group='Line 1')
var Bottom                  =   input.price(defval=100, title= "B O T T O M   L E F T", inline="B O T T O M  -   L E F T", confirm = true,group='Line 1')
var Top                     =   input.price(defval=100, title='T O P',confirm = true)
var tracking                =   input.bool(false,"Active Tracking",group="Global", inline="11a")
var fibreverse              =   input.bool(false,'Reverse Fib',group="Global", inline="11a")
var decimals_price          =   input.int(2,"Price decimals",group="decimals trimming",inline="1")
var decimals_percent        =   input.int(2,"Percent decimals",group="decimals trimming",inline="1")

textcolor1                  =   input.color(color.white,"Text color",group="Global",inline="1a")
size1                       =   input.string(size.small,"size", options = [size.tiny,size.small,size.normal,size.large],group="Global",inline="1a")
Linecolor_Global            =   input.color(color.white,"Linecolor",inline="1a")
var transp                  =   input.int(60,"Transparency fillings",group="Fillings")

fib_01 = input.float(1.0     ,"Level 0",group="Fiblevels 01",step=0.001)
fib_02 = input.float(0.786    ,"Level 1",group="Fiblevels 01",step=0.001,inline="1a")      
fib_03 = input.float(0.65    ,"Level 2",group="Fiblevels 23",step=0.001 ) 
fib_04 = input.float(0.618   ,"Level 3",group="Fiblevels 23",step=0.001,inline="1b")       
fib_05 = input.float(0.5    ,"Level 4",group="Fiblevels 4",step=0.001)      
fib_06 = input.float(0.382    ,"Level 5",group="Fiblevels 56",step=0.001 )    
fib_07 = input.float(0.35    ,"Level 6",group="Fiblevels 56",step=0.001,inline="1c")       
fib_08 = input.float(0.236  ,"Level 7",group="Fiblevels 78",step=0.001 )
fib_09 = input.float(0.0    ,"Level 8",group="Fiblevels 78",step=0.001,inline="1d")      

channels = array.new<float>(0,na)
if fibreverse
    channels := array.from(
     fib_01,fib_02,fib_03,fib_04,fib_05,fib_06,fib_07,fib_08,fib_09 
     )
else
    channels := array.from(
     1-fib_09,1-fib_08,1-fib_07,1-fib_06,1-fib_05,1-fib_04,1-fib_03,1-fib_02,1-fib_01 
     )

color1=color.new(input.color(color.rgb(175, 76, 76, 0),"Fill-Color 0-1",group="Fiblevels 01",inline="1a"),transp)
color2=color.new(input.color(color.rgb(175, 172, 76, 0),"Fill-Color 2-3",group="Fiblevels 23",inline="1b"),transp)
color3=color.new(input.color(color.rgb(175, 172, 76, 0),"Fill-Color 5-6",group="Fiblevels 56",inline="1c"),transp)
color4=color.new(input.color(color.rgb(76, 175, 79, 0),"Fill-Color 7-8",group="Fiblevels 78",inline="1d"),transp)

bool        ChartisLog              =   input.bool(false,'Logarithmic',group='Global',inline='11a')

if tracking and time > Starttime
    Top := Top < high ? high:Top
    Bottom := Bottom > low ? low:Bottom

linearray = array.new_line(0,na)

shifting(_value) =>
    var string output = ""
    output := ""
    for i = 0 to _value by 3
        output := output + "   "

float       LOGICAL_OFFSET          =   4
float       COORD_OFFSET            =   0.0001

f_round(_val, decimals) =>
    // Rounds _val to _decimals places.
    _p = math.pow(10, decimals)
    math.round(math.abs(_val) * _p) / _p * math.sign(_val)

fromLog(series float value) =>
    float exponent = math.abs(value)
    float product  = math.pow(10, exponent - LOGICAL_OFFSET) - COORD_OFFSET
    float result   = exponent < 1e-8 ? 0 : value < 0 ? - product : product

toLog(series float value) =>
    float exponent = math.abs(value)
    float product  = math.log10(exponent + COORD_OFFSET) + LOGICAL_OFFSET
    float result   = exponent < 1e-8 ? 0 : value < 0 ? - product : product

f_fibcalc(Top, Bottom, channels, ChartisLog) =>
    output = array.new<float>()

    Diff = Top-Bottom

    for i = 0 to array.size(channels) -1
        if ChartisLog
            array.push(output, fromLog( toLog(Bottom) + (toLog(Top)-toLog(Bottom)) * array.get(channels,i) ))
        else
            array.push(output, (Bottom) + (Diff) * (array.get(channels,i)))
    output

output = f_fibcalc(Top,Bottom, channels,ChartisLog)

cleareverything() =>
    a_allLines = line.all
    if array.size(a_allLines) > 0
        for i = 0 to array.size(a_allLines) - 1
            line.delete(array.get(a_allLines, i))
    a_allLabel = label.all
    if array.size(a_allLabel) > 0
        for i = 0 to array.size(a_allLabel) - 1
            label.delete(array.get(a_allLabel, i))
    a_allFills = linefill.all
    if array.size(a_allFills) > 0
        for i = 0 to array.size(a_allFills) - 1
            linefill.delete(array.get(a_allFills, i))
    

drawout() =>
    for i = 0 to array.size(channels)-1
        line line1 = na
        linefill fill1 = na
        label label1 = na
        label label2 = na

        line1 := line.new(x1= Starttime, y1= array.get(output,i),x2 = time, y2 = array.get(output,i), xloc=xloc.bar_time, style=line.style_solid, extend=extend.right,color=Linecolor_Global)
        array.insert(linearray,i,line1)

        if i == 1
            fill1 := linefill.new(array.get(linearray,0),array.get(linearray,1),color1)
        if i == 3
            fill1 := linefill.new(array.get(linearray,2),array.get(linearray,3),color2)
        if i == 6
            fill1 := linefill.new(array.get(linearray,5),array.get(linearray,6),color3)
        if i == 8
            fill1 := linefill.new(array.get(linearray,7),array.get(linearray,8),color4)

        label1 := label.new(x=time <= chart.right_visible_bar_time?time:chart.right_visible_bar_time, y= array.get(output,i), 
         text = time <= chart.right_visible_bar_time?
          "                                                                                        " + str.tostring(fibreverse?(1-array.get(channels,i)):array.get(channels,i)) + ' (' + str.tostring(f_round(array.get(output,i),decimals_price)) + ')  ' + str.tostring(f_round(array.get(output,i)/close*100-100,decimals_percent)) + '% = ' + str.tostring(f_round(array.get(output,i)-close,decimals_price)) :
          "" + str.tostring(fibreverse?(1-array.get(channels,i)):array.get(channels,i)) + ' (' + str.tostring(f_round(array.get(output,i),decimals_price)) + ')                          ', 
         xloc=xloc.bar_time, 
         yloc=yloc.price, 
         color=color.white, 
         style=label.style_none, 
         textcolor=textcolor1, 
         size=size1, 
         textalign=text.align_left)

        if i == 8
            label2 := label.new(x=time <= chart.right_visible_bar_time?time:chart.right_visible_bar_time, y= array.get(output,i), 
             text = time <= chart.right_visible_bar_time?
              "                                                                                        Range-Up     =   " + str.tostring(f_round(array.get(output,0)/array.get(output,8)*100-100,decimals_percent)) + '% / ' + str.tostring(f_round(array.get(output,0)-array.get(output,8),decimals_price)) + '\n                                                                                        Range-Down = ' + str.tostring(f_round(array.get(output,8)/array.get(output,0)*100-100,decimals_percent)) + '%\n':
              "", 
             xloc=xloc.bar_time, 
             yloc=yloc.price, 
             color=color.white, 
             style=label.style_none, 
             textcolor=textcolor1, 
             size=size1, 
             textalign=text.align_left)            


cleareverything()
drawout()