RSI Multi Length With Divergence Alert [Skiploss]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Skiploss

// This is a modified indicator base code from RSI Multi Length [LUX] and we will added some of fuction by finding a classic/hidden divergence

//@version=5

indicator(title = "RSI Multi Length With Divergence Alert [Skiploss]", shorttitle = "RMLWDA v0.77")

// RSI Setting
length_max  =   input(20, 'Maximum Length', group = 'RSI Setting')
length_min  =   input(10, 'Minimum Length', group = 'RSI Setting')

level_overbought   =   input.float(70, 'Overboght Level', step = 5, group = 'RSI Setting')
level_oversold     =   input.float(30, 'Oversold Level', step = 5, group = 'RSI Setting')

rsi_source  =   input(close, 'Source', group = 'RSI Setting')

// MA Setting
ma(source, length, type) =>
    switch type
        "SMA" => ta.sma(source, length)
        "Bollinger Bands" => ta.sma(source, length)
        "EMA" => ta.ema(source, length)
        "SMMA (RMA)" => ta.rma(source, length)
        "WMA" => ta.wma(source, length)
        "VWMA" => ta.vwma(source, length)

ma_type = input.string("EMA", title = "MA Type", options = ["SMA", "Bollinger Bands", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group = "RSI Base MA Settings")
ma_length = input.int(14, title = "MA Length", group="RSI Base MA Settings")

// Divergence Setting

pivot_look_back_right    =   input(title = "Pivot Right", defval = 7, group = 'Divergence Setting')
pivot_look_back_left    =   input(title =  "Pivot Left", defval = 7, group = 'Divergence Setting')

rangeUpper = input(title = "Max Range", defval = 60, group = 'Divergence Setting')
rangeLower = input(title = "Min Range", defval =  5, group = 'Divergence Setting')

//Display Settings
plot_ma_base_rsi	=	input(title = "RSI Base MA", defval = false, group = 'Display Setting')

plotBull  =   input(title = "Classic Bullish Divergence", defval = true, group = 'Display Setting')
plotBear  =   input(title = "Classic Bearish Divergence", defval = true, group = 'Display Setting')

plotHiddenBull   =   input(title = "Hidden Bullish Divergence", defval = false, group = 'Display Setting')
plotHiddenBear   =   input(title = "Hidden Bearish Divergence", defval = false, group = 'Display Setting')

// Style Setting
color_css_gradient_overbought   =   input(#bfcdcc, 'Overbought', group = 'Style Setting')
color_css_gradient_oversold     =   input(#ff8e8e,   'Oversold', group = 'Style Setting')

color_bearish =   input(#e8ff8e, 'Bearish', group = 'Style Setting')
color_bullish =   input(#8eff8e, 'Bullish', group = 'Style Setting')
color_hidden_bullish = color.new(color_bullish, 80)
color_hidden_bearish = color.new(color_bearish, 80)
textColor = #000000
noneColor = color.new(color.white, 100)

// Define values
counting_numbers   =   length_max-length_min+1
difference         =   nz(rsi_source - rsi_source[1])

var numerator      = array.new_float(counting_numbers, 0)
var denominator    = array.new_float(counting_numbers, 0)

// Lenght Values
factor     = 0
overbought = 0
oversold   = 0
average    = 0.
for i = length_min to length_max
    alpha   =   1/i

    numerator_rma   =   alpha*difference + (1-alpha)*array.get(numerator,factor)
    denominator_rma =   alpha*math.abs(difference) + (1-alpha)*array.get(denominator,factor)
    value_rsi = 50*numerator_rma/denominator_rma + 50
    average += value_rsi

    overbought := value_rsi > level_overbought ? overbought + 1 : overbought
    oversold := value_rsi < level_oversold ? oversold + 1 : oversold

    array.set(numerator, factor, numerator_rma)
    array.set(denominator, factor, denominator_rma)
    factor += 1

// RSI Values
average_rsi = average/counting_numbers
rsi_bought_ma = 0.
rsi_sold_ma = 0.

rsi_bought_ma := nz(rsi_bought_ma[1] + overbought/counting_numbers*(average_rsi - rsi_bought_ma[1]), average_rsi)
rsi_sold_ma := nz(rsi_sold_ma[1] + oversold/counting_numbers*(average_rsi - rsi_sold_ma[1]), average_rsi)

// RSI Meter
var meter = table.new(position.top_right,2,2)
if barstate.islast
    // 1st Row
    table.cell(meter, 0, 0, 'Overbought', text_color = #787b86, bgcolor = na)
    table.cell(meter, 1, 0, 'Oversold', text_color = #787b86, bgcolor = na)
    // 2nd Row
    table.cell(meter, 0, 1, str.tostring(overbought/counting_numbers*100, '#.##')+'%', text_color = color_css_gradient_overbought, bgcolor = color.new(color_css_gradient_overbought,90))
    table.cell(meter, 1, 1, str.tostring(oversold/counting_numbers*100, '#.##')+'%', text_color = color_css_gradient_oversold, bgcolor = color.new(color_css_gradient_oversold,90))

// Plot RSI
css_gradient = color.from_gradient(average_rsi, rsi_sold_ma, rsi_bought_ma, color_css_gradient_oversold, color_css_gradient_overbought)
plot(average_rsi, color = css_gradient)

// Plot Band
hline(level_overbought, 'Upper Line', color = color.new(color.gray,50), linestyle = hline.style_solid, display = display.all)
hline(50, 'Medium Line', color = color.new(color.gray,50), linestyle = hline.style_solid, display = display.all)
hline(level_oversold, 'Lower Line', color = color.new(color.gray,50), linestyle = hline.style_solid, display = display.all)

// RSI Base MA
rsi_base_ma	= ma(average_rsi, ma_length, ma_type)

plot(rsi_base_ma, "RSI Base MA", color = #DFFF00, display = plot_ma_base_rsi == true ? display.all : display.none)

////////////////////////////// Divergence //////////////////////////////
// Set RSI Value to Multi lenge
osc = average_rsi

plFound = na(ta.pivotlow(osc, pivot_look_back_left, pivot_look_back_right)) ? false : true
phFound = na(ta.pivothigh(osc, pivot_look_back_left, pivot_look_back_right)) ? false : true
_inRange(cond) =>
	bars = ta.barssince(cond == true)
	rangeLower <= bars and bars <= rangeUpper

//------------------------------------------------------------------------------
// Regular Bullish
// Osc: Higher Low

oscHL = osc[pivot_look_back_right] > ta.valuewhen(plFound, osc[pivot_look_back_right], 1) and _inRange(plFound[1])

// Price: Lower Low

priceLL = low[pivot_look_back_right] < ta.valuewhen(plFound, low[pivot_look_back_right], 1)
bullCond = plotBull and priceLL and oscHL and plFound

plot(
     plFound ? osc[pivot_look_back_right] : na,
     offset=-pivot_look_back_right,
     title="Regular Bullish",
     linewidth=2,
     color=(bullCond ? color_bullish : noneColor)
     )

plotshape(
	 bullCond ? osc[pivot_look_back_right] : na,
	 offset=-pivot_look_back_right,
	 title="Regular Bullish Label",
	 text=" Bullish ",
	 style=shape.labelup,
	 location=location.absolute,
	 color=color_bullish,
	 textcolor=textColor
	 )
// Hidden Bullish
// Osc: Lower Low

oscLL = osc[pivot_look_back_right] < ta.valuewhen(plFound, osc[pivot_look_back_right], 1) and _inRange(plFound[1])

// Price: Higher Low

priceHL = low[pivot_look_back_right] > ta.valuewhen(plFound, low[pivot_look_back_right], 1)
hiddenBullCond = plotHiddenBull and priceHL and oscLL and plFound

plot(
	 plFound ? osc[pivot_look_back_right] : na,
	 offset=-pivot_look_back_right,
	 title="Hidden Bullish",
	 linewidth=2,
	 color=(hiddenBullCond ? color_hidden_bullish : noneColor)
	 )

plotshape(
	 hiddenBullCond ? osc[pivot_look_back_right] : na,
	 offset=-pivot_look_back_right,
	 title="Hidden Bullish Label",
	 text=" H Bullish ",
	 style=shape.labelup,
	 location=location.absolute,
	 color=color_bullish,
	 textcolor=textColor
	 )

//------------------------------------------------------------------------------
// Regular Bearish
// Osc: Lower High

oscLH = osc[pivot_look_back_right] < ta.valuewhen(phFound, osc[pivot_look_back_right], 1) and _inRange(phFound[1])

// Price: Higher High

priceHH = high[pivot_look_back_right] > ta.valuewhen(phFound, high[pivot_look_back_right], 1)

bearCond = plotBear and priceHH and oscLH and phFound

plot(
	 phFound ? osc[pivot_look_back_right] : na,
	 offset=-pivot_look_back_right,
	 title="Regular Bearish",
	 linewidth=2,
	 color=(bearCond ? color_bearish : noneColor)
	 )

plotshape(
	 bearCond ? osc[pivot_look_back_right] : na,
	 offset=-pivot_look_back_right,
	 title="Regular Bearish Label",
	 text=" Bearish ",
	 style=shape.labeldown,
	 location=location.absolute,
	 color=color_bearish,
	 textcolor=textColor
	 )

//------------------------------------------------------------------------------
// Hidden Bearish
// Osc: Higher High

oscHH = osc[pivot_look_back_right] > ta.valuewhen(phFound, osc[pivot_look_back_right], 1) and _inRange(phFound[1])

// Price: Lower High

priceLH = high[pivot_look_back_right] < ta.valuewhen(phFound, high[pivot_look_back_right], 1)

hiddenBearCond = plotHiddenBear and priceLH and oscHH and phFound

plot(
	 phFound ? osc[pivot_look_back_right] : na,
	 offset=-pivot_look_back_right,
	 title="Hidden Bearish",
	 linewidth=2,
	 color=(hiddenBearCond ? color_hidden_bearish : noneColor)
	 )

plotshape(
	 hiddenBearCond ? osc[pivot_look_back_right] : na,
	 offset=-pivot_look_back_right,
	 title="Hidden Bearish Label",
	 text=" H Bearish ",
	 style=shape.labeldown,
	 location=location.absolute,
	 color=color_bearish,
	 textcolor=textColor
	 )

// Alert Condition
alertcondition(bullCond, title = "Bullish Divergence", message = "Bullish Divergence")
alertcondition(bearCond, title = "Bearish Divergence", message = "Bearish Divergence")
alertcondition(hiddenBullCond, title = "Hidden Bullish Divergence", message = "Hidden Bullish Divergence")
alertcondition(hiddenBearCond, title = "Hidden Bearish Divergence", message = "Hidden Bearish Divergence")