Auto Fibonacci TP Levels [WJ]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © War-Jackel

//@version=5
indicator("Auto Fibonacci TP Levels [WJ]", shorttitle = "Auto Fibs [WJ]", overlay=true, max_boxes_count = 500, max_labels_count = 500)

tradeSource       = input.source(close, "Trade Source 1" , group = "Trade Settings", tooltip = "Source entry value:\nLong = 1\nShort = 2")
tradeSource2      = input.source(close, "Trade Source 2" , group = "Trade Settings", tooltip = "Source entry value:\nLong = 1\nShort = 2")
fibStart1         = input.source(low, "Fib Start : Longs", group = "Trade Settings", tooltip = "Where to start the fib from")
fibStart2         = input.source(open,  "Fib Start : Shorts", group = "Trade Settings", tooltip = "Where to start the fib from")
length_to_check   = input(50, "HH/LL Bars Back", group = "Trade Settings", tooltip = "Historical bars for HH/LL")

fibLabel          = input.bool(true, "Fib 0.618 Distance from entry", group = "Labels & Lines", tooltip = "How far from the entry to the 0.618 Fib")
showCrossLabels   = input(true, title="Fib Crossing", group = "Labels & Lines", tooltip = "When a fib line was crossed")
onlyGP            = input.bool(false, "Only Golden Pocket Levels", group = "Labels & Lines", tooltip = "Show only the golden pocket (0.618,0.65) fib lines")

chk1 = onlyGP ? false : input.bool(false, "", group = "Fibonacci", inline = "colors1")
chk2 = onlyGP ? true  : input.bool(true , "", group = "Fibonacci", inline = "colors2")
chk3 = onlyGP ? true  : input.bool(true , "", group = "Fibonacci", inline = "colors3")
chk4 = onlyGP ? false : input.bool(true , "", group = "Fibonacci", inline = "colors4")
chk5 = onlyGP ? false : input.bool(true , "", group = "Fibonacci", inline = "colors5")
chk6 = onlyGP ? false : input.bool(true , "", group = "Fibonacci", inline = "colors6")
chk7 = onlyGP ? false : input.bool(false, "", group = "Fibonacci", inline = "colors7")
chk8 = onlyGP ? false : input.bool(true , "", group = "Fibonacci", inline = "colors8")
chk9 = onlyGP ? false : input.bool(true , "", group = "Fibonacci", inline = "colors9")

fib_level_1 = input.float(1.,     title="Fib Level 1" , group = "Fibonacci", inline = "colors1")
fib_level_2 = input.float(0.618,  title="Fib Level 2" , group = "Fibonacci", inline = "colors2")
fib_level_3 = input.float(0.65,   title="Fib Level 3" , group = "Fibonacci", inline = "colors3")
fib_level_4 = input.float(0.236,  title="Fib Level 4" , group = "Fibonacci", inline = "colors4")
fib_level_5 = input.float(0.382,  title="Fib Level 5" , group = "Fibonacci", inline = "colors5")
fib_level_6 = input.float(0.786,  title="Fib Level 6" , group = "Fibonacci", inline = "colors6")
fib_level_7 = input.float(0.,     title="Fib Level 7" , group = "Fibonacci", inline = "colors7")
fib_level_8 = input.float(1.286,  title="Stop Loss Level: Short", group = "Fibonacci", inline = "colors8") // Stop loss for Bear
fib_level_9 = input.float(-0.386, title="Stop Loss Level: Long ‏" , group = "Fibonacci", inline = "colors9") // Stop loss for Bull

color_level_1 = input(color.gray  , group = "Fibonacci", inline = "colors1", title = "")
color_level_2 = input(color.orange, group = "Fibonacci", inline = "colors2", title = "")
color_level_3 = input(color.orange, group = "Fibonacci", inline = "colors3", title = "")
color_level_4 = input(color.lime  , group = "Fibonacci", inline = "colors4", title = "")
color_level_5 = input(color.lime  , group = "Fibonacci", inline = "colors5", title = "")
color_level_6 = input(color.lime  , group = "Fibonacci", inline = "colors6", title = "")
color_level_7 = input(color.gray  , group = "Fibonacci", inline = "colors7", title = "")
color_level_8 = input(color.red   , group = "Fibonacci", inline = "colors8", title = "") // Stop loss color for Bear
color_level_9 = input(color.red   , group = "Fibonacci", inline = "colors9", title = "") // Stop loss color for Bull

fib_levels_float = array.new_float(0)
array.push(fib_levels_float, fib_level_1)
array.push(fib_levels_float, fib_level_2)
array.push(fib_levels_float, fib_level_3)
array.push(fib_levels_float, fib_level_4)
array.push(fib_levels_float, fib_level_5)
array.push(fib_levels_float, fib_level_6)
array.push(fib_levels_float, fib_level_7)
array.push(fib_levels_float, fib_level_8) 
array.push(fib_levels_float, fib_level_9) 

fib_colors = array.new_color(0)
array.push(fib_colors, chk1 ? color_level_1 : na)
array.push(fib_colors, chk2 ? color_level_2 : na)
array.push(fib_colors, chk3 ? color_level_3 : na)
array.push(fib_colors, chk4 ? color_level_4 : na)
array.push(fib_colors, chk5 ? color_level_5 : na)
array.push(fib_colors, chk6 ? color_level_6 : na)
array.push(fib_colors, chk7 ? color_level_7 : na)
array.push(fib_colors, chk8 ? color_level_8 : na) 
array.push(fib_colors, chk9 ? color_level_9 : na) 

bull_cross = tradeSource == 1 or tradeSource2 == 1
bear_cross = tradeSource == 2 or tradeSource2 == 2

var float p1 = na
var float p2 = na
var int cross_bar = na
var box[] fib_box = array.new_box(0)
var label[] fib_label = array.new_label(0)
var float high_level = na
var float low_level = na
var bool[] touchArray = array.new_bool(0)
var int[] touchCounter = array.new_int(0, 0)
var string crossedFibLevel = na
var int hh_bar = na
var int ll_bar = na
var float hh = na
var float ll = na
var bool fibCross = false

for i = 0 to array.size(fib_levels_float) - 1
    level = array.get(fib_levels_float, i)
    if (bull_cross and level == fib_level_7) or (bear_cross and level == fib_level_4)
        b = box.new(left=cross_bar, top=p1+(p2-p1)*level, right=bar_index, bottom=p1+(p2-p1)*level, extend = extend.none, border_color = array.get(fib_colors, i), border_width=1)
        array.push(fib_box, b)
        array.push(touchArray, false)
        if level == 0.618
            priceAtLevel = math.round(p1+(p2-p1)*level)

if length_to_check > 0
    hh := ta.highest(high, length_to_check)
    ll := ta.lowest(low, length_to_check)
    high_level := hh
    low_level := ll
    hh_bar := bar_index - ta.highestbars(high, length_to_check) // get the bar index of highest high
    ll_bar := bar_index - ta.lowestbars(low, length_to_check) // get the bar index of lowest low

if bull_cross
    cross_bar := bar_index
    p1 := fibStart1 
    p2 := high_level

else if bear_cross
    cross_bar := bar_index
    p1 := fibStart2
    p2 := low_level

if not na(p1) and not na(p2) and cross_bar[1] != cross_bar
    array.clear(fib_box)
    array.clear(touchArray)
    array.clear(touchCounter)
    array.clear(fib_label)

    for i = 0 to array.size(fib_levels_float) - 1
        level = array.get(fib_levels_float, i)
        if bull_cross    
            if level != fib_level_8 
                b = box.new(left=cross_bar, top=(p1-p2)*(1-level)+p2, right=bar_index, bottom=(p1-p2)*(1-level)+p2, extend = extend.none, border_color = array.get(fib_colors, i), border_width=1)
                array.push(fib_box, b)
                array.push(touchArray, false)
                array.push(touchCounter, 0)
                if level == 0.618
                    priceAtLevel = (p1-p2)*(1-level)+p2
                    priceAt0FibLevel = p1
                    percentageDifference = math.abs((priceAtLevel / priceAt0FibLevel) - 1)
                    if fibLabel
                        l = label.new(x=cross_bar, y=box.get_bottom(b), text=str.tostring((percentageDifference)*100,"0.000") + "% \n(" + str.tostring(priceAtLevel) + ")", xloc=xloc.bar_index, yloc=yloc.price, color=color.new(color.lime, 90), textcolor=color.white, style=label.style_label_down, size=size.small)
                        array.push(fib_label, l)
        else if bear_cross
            if level != fib_level_9
                b = box.new(left=cross_bar, top=p1+(p2-p1)*(1-level), right=bar_index, bottom=p1+(p2-p1)*(1-level), extend = extend.none, border_color = array.get(fib_colors, i), border_width=1)
                array.push(fib_box, b)
                array.push(touchArray, false)
                array.push(touchCounter, 0)
                if level == 0.618
                    priceAtLevel = p1+(p2-p1)*(1-level)
                    priceAt0FibLevel = p1 
                    percentageDifference = math.abs((priceAtLevel - priceAt0FibLevel) / priceAt0FibLevel)
                    if fibLabel
                        l = label.new(x=cross_bar, y=box.get_bottom(b), text=str.tostring((percentageDifference)*100,"0.000") + "% \n(" + str.tostring(priceAtLevel) + ")", xloc=xloc.bar_index, yloc=yloc.price, color=color.new(color.red, 90), textcolor=color.white, style=label.style_label_up, size=size.small)
                        array.push(fib_label, l)

if array.size(fib_box) > 0
    for i = 0 to array.size(fib_box) - 1 
        b = array.get(fib_box, i)
        if not array.get(touchArray, i)
            if high >= box.get_top(b) and low <= box.get_bottom(b)
                array.set(touchCounter, i, array.get(touchCounter, i) + 1)
                levelValue = array.get(fib_levels_float, i)
                if (not na(levelValue))
                    crossedFibLevel := str.tostring(levelValue)
                else
                    crossedFibLevel := "na"
                
                shouldShowLabel = false
                // Adjust which levels to show
                if crossedFibLevel == str.tostring(fib_level_1 )
                    shouldShowLabel := chk1
                else if crossedFibLevel == str.tostring(fib_level_2)  
                    shouldShowLabel := chk2
                else if crossedFibLevel == str.tostring(fib_level_3)  
                    shouldShowLabel := chk3
                else if crossedFibLevel == str.tostring(fib_level_4)
                    shouldShowLabel := chk4
                else if crossedFibLevel == str.tostring(fib_level_5)
                    shouldShowLabel := chk5
                else if crossedFibLevel == str.tostring(fib_level_6)
                    shouldShowLabel := chk6
                else if crossedFibLevel == str.tostring(fib_level_7)
                    shouldShowLabel := chk7
                else if crossedFibLevel == str.tostring(fib_level_8)
                    shouldShowLabel := chk8
                else if crossedFibLevel == str.tostring(fib_level_9)
                    shouldShowLabel := chk9

                // create label every time the fib level is crossed but not for 0 and 1
                if shouldShowLabel and showCrossLabels and crossedFibLevel != "0" and crossedFibLevel != "1"  
                    label.new(bar_index, close, text=" " + str.tostring(crossedFibLevel) + " Crossed", color=color.new(color.white, 70), style = label.style_label_down, textcolor=color.white, size = size.tiny) // Note that we are now converting the float to a string for the label text.
                    fibCross := true
                if array.get(touchCounter, i) >= 1    
                    array.set(touchArray, i, true)
                    if i < array.size(fib_label)
                        l = array.get(fib_label, i)
                        label.set_x(l, bar_index)
            else
                box.set_right(b, bar_index)

//// Entries
plotshape(series=bull_cross,title="Long", location=location.belowbar, color=color.green, style=shape.labelup,  text="" , textcolor =color.white)
plotshape(series=bear_cross,title="Short", location=location.abovebar, color=color.red, style=shape.labeldown, text="", textcolor = color.white)

//// Plots
plot(chk1 ? p1+(p2-p1)*fib_level_1 : na, title="Fib 1",   color=na, editable= false)
plot(chk2 ? p1+(p2-p1)*fib_level_2 : na, title="Fib 2",   color=na, editable= false)
plot(chk3 ? p1+(p2-p1)*fib_level_3 : na, title="Fib 3",   color=na, editable= false)
plot(chk4 ? p1+(p2-p1)*fib_level_4 : na, title="Fib 4",   color=na, editable= false)
plot(chk5 ? p1+(p2-p1)*fib_level_5 : na, title="Fib 5",   color=na, editable= false)
plot(chk6 ? p1+(p2-p1)*fib_level_6 : na, title="Fib 6",   color=na, editable= false)
plot(chk7 ? p1+(p2-p1)*fib_level_7 : na, title="Fib 7",   color=na, editable= false)
plot(chk8 ? p1+(p2-p1)*fib_level_8 : na, title="Fib SSL", color=na, editable= false)
plot(chk9 ? p1+(p2-p1)*fib_level_9 : na, title="Fib LSL", color=na, editable= false)

///// Alerts

//Any alert()
bAlert = '"Long Alert"'
sAlert = '"Short Alert"'
fibCrossAlert= '"Price crossed Fibonacci level" "'+ crossedFibLevel +'" '
alerts(sym) =>
    if  (bull_cross or bear_cross or fibCross)
        alert_text = bull_cross ? bAlert : bear_cross ? sAlert : fibCross ? fibCrossAlert : "na"
        alert(alert_text,  alert.freq_once_per_bar_close)
alerts(syminfo.tickerid)

alertcondition(bull_cross, title="Bull Cross", message="Bull Cross has occurred")
alertcondition(bear_cross, title="Bear Cross", message="Bear Cross has occurred")
alertcondition(fibCross, title="Fib Cross", message="Fib Crossed")

///// Connector
bool Out_Long   =  bull_cross
bool Out_Short  =  bear_cross
bool Out_LongX  =  bull_cross and fibCross
bool Out_ShortX =  bear_cross and fibCross
plot(Out_Long ? 1 : Out_Short ? 2 : Out_LongX ? 3 : Out_ShortX ? 4 : 0, title = "⭐ Fib TP Outbound signal", display = display.none, editable = false)
