Directional Sentiment Line
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//  /$$$$$$   /$$                                                         /$$                                            
// /$$__  $$ | $$                                                        | $$                                            
//| $$  \__//$$$$$$    /$$$$$$  /$$    /$$ /$$$$$$   /$$$$$$   /$$$$$$$ /$$$$$$    /$$$$$$  /$$    /$$ /$$$$$$   /$$$$$$$
//|  $$$$$$|_  $$_/   /$$__  $$|  $$  /$$//$$__  $$ /$$__  $$ /$$_____/|_  $$_/   /$$__  $$|  $$  /$$//$$__  $$ /$$_____/
// \____  $$ | $$    | $$$$$$$$ \  $$/$$/| $$$$$$$$| $$  \__/|  $$$$$$   | $$    | $$$$$$$$ \  $$/$$/| $$$$$$$$|  $$$$$$ 
// /$$  \ $$ | $$ /$$| $$_____/  \  $$$/ | $$_____/| $$       \____  $$  | $$ /$$| $$_____/  \  $$$/ | $$_____/ \____  $$
//|  $$$$$$/ |  $$$$/|  $$$$$$$   \  $/  |  $$$$$$$| $$       /$$$$$$$/  |  $$$$/|  $$$$$$$   \  $/  |  $$$$$$$ /$$$$$$$/
// \______/   \___/   \_______/    \_/    \_______/|__/      |_______/    \___/   \_______/    \_/    \_______/|_______/ 

//       ___________________
//      /                   \
//     /  _____        _____ \
//    /  /     \      /     \  \
// __/__/       \____/       \__\_____
//|           ___________           ____|
// \_________/           \_________/
//            \  /////// /
//             \/////////
// © Steversteves
//@version=5
indicator("Directional Sentiment Line [SS]", shorttitle = "DSL [SS]", overlay=true, max_bars_back = 5000, max_labels_count = 500)

// Groups 
g1 = "Settings"
g2 = "Plots"

lengthInput =   input.int(75, "Length", minval = 2, group = g1)
atr_len =       input.int(500, "ATR Length", group = g1)
learn =         input.int(500, "Training Time for Buy/Sell", group = g1)
hi_lo_plt =     input.bool(false, "Plot Highest and Lowest Price", group = g2)
plot_atr =      input.bool(true, "Plot High and Low Target Boxes", group = g2) 
plot_cross =    input.bool(true, "Plot Crossovers/Unders", group = g2)
plot_signals =  input.bool(true, "Plot Buy and Sell Signals", group = g2)

// Determine variables 

hi = ta.sma(high, lengthInput)
lo = ta.sma(low, lengthInput)
cl = ta.sma(close, lengthInput) 
op = ta.sma(open, lengthInput) 

// Lowest vs highest

lowest = ta.lowest(lo, lengthInput)
highest = ta.highest(hi, lengthInput)

// bools for ribbon 

bool closeabove = close >= cl 
bool closebelow = close <= cl 
bool highabove = high >= hi 
bool lowabove = low >= lo 
bool openabove = open >= op 

// bools for highest/lowest 

bool paabovehigh = close > highest 
bool pabelowlow = close < lowest 
bool middle = close >= lo and close <= hi

// Colours 

color bull = color.green 
color bear = color.red 
color neutral = color.orange
color standard = color.blue
color fillcolorbull = color.new(color.lime, 75)
color fillcolorbear = color.new(color.red, 75)
color fillcolorneutral = color.new(color.gray, 75)

// Determine Colour 

color hicolor = highabove ? bull : bear 
color locolor = lowabove ? bull : bear 
color opcolor = openabove ? bull : bear 
color clcolor = closeabove ? bull : bear 
color lowestcolor = pabelowlow ? neutral : standard
color highestcolor = paabovehigh ? neutral : standard 
color fillfinal = closeabove ? fillcolorbull : closebelow ? fillcolorbear : middle ? fillcolorneutral : na 

//Ribbon Plots
hir = plot(hi, color = hicolor)
lor = plot(lo, color = locolor)
//plot(cl, color = hicolor)
//plot(op, color = hicolor)

// Fills
fill(hir, lor, color = fillfinal, editable=false)

// Band Plots 
plot(hi_lo_plt ? lowest : na, "Lowest Target", color = lowestcolor, linewidth=3)
plot(hi_lo_plt ? highest : na, "Highest Target", color = highestcolor, linewidth=3)

// Expand Range 
bool crossunder = ta.crossunder(close, lo)[3] and close[2] <= lo[2] and close[1] < lo[1] and close < lo 
bool crossover = ta.crossover(close, hi)[3] and close[2] >= hi[2] and close[1] > hi[1] and close > hi 
bool above_dsl = high > hi 
bool below_dsl = low < lo 

hi_array = array.new<float>()
hi_reference = array.new<float>()
lo_array = array.new<float>() 
lo_reference = array.new<float>()

hi_dif = high - hi 
lo_dif = lo - low 
for i = 0 to atr_len 
    if above_dsl[i]
        array.push(hi_array, hi_dif[i])
    if below_dsl[i]
        array.push(lo_array, lo_dif[i])
    if crossover[i]
        array.push(hi_reference, hi[i])
    if crossunder[i]
        array.push(lo_reference, lo[i])

hi_avg_from_array = array.avg(hi_array) 
hi_max = array.max(hi_array) 

lo_avg_from_array = array.avg(lo_array) 
lo_max = array.max(lo_array) 


var box lo_box = na 
var box hi_box = na 
if barstate.isconfirmed and plot_atr
    if crossover 
        box.delete(hi_box), box.delete(lo_box) 
        hi_box := box.new(bar_index[1], array.get(hi_reference, 0) + hi_max, bar_index, array.get(hi_reference, 0) + hi_avg_from_array, bgcolor = fillcolorbull, border_color = fillcolorbull, extend = extend.right)
    if crossunder 
        box.delete(lo_box), box.delete(hi_box) 
        lo_box := box.new(bar_index[1], array.get(lo_reference, 0) - lo_avg_from_array, bar_index, array.get(lo_reference, 0) - lo_max, bgcolor = fillcolorbear, border_color = fillcolorbear, extend = extend.right)




        
// Plot crossovers / unders 

plotshape(plot_cross and crossover ? low : na, title="Up Arrow", location=location.belowbar, style=shape.triangleup, size=size.small, color=color.green)
plotshape(plot_cross and crossunder ? high : na, title="Down Arrow", location=location.abovebar, style=shape.triangledown, size=size.small, color=color.red)

// Max Distance

hi_distance = math.sqrt(math.pow(close - hi,2)) 
lo_distance = math.sqrt(math.pow(lo - close,2))

hi_dist_array = array.new_float() 
lo_dist_array = array.new_float() 

for i = 0 to learn
    if above_dsl[i]
        array.push(hi_dist_array, hi_distance[i]) 
    if below_dsl[i]
        array.push(lo_dist_array, lo_distance[i])

    

hi_dist_max = array.max(hi_dist_array)
lo_dist_max = array.min(lo_dist_array) 

var int hi_counter = 0 
var int lo_counter = 0 
if above_dsl and hi_distance >= hi_dist_max and plot_signals
    hi_counter += 1 
    if hi_counter >= 5
        label.new(bar_index, high, color = color.red, text = "Short") 
        hi_counter := 0 
if below_dsl and lo_distance <= lo_dist_max and plot_signals 
    lo_counter += 1 
    if lo_counter >= 5 
        label.new(bar_index, low, text = "Long", color = color.lime, style = label.style_label_up) 
        lo_counter := 0 
