RSI with Divergences, Reverse Formulas, and Bull/Bear Zones
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © kylealberry

//@version=4
study(title="RSI with Divergences, Reverse Formulas, and Bull/Bear Zones")
// {INPUT
rsiOn = input(true, title="RSI On", group="RSI Settings")
rsi_len = input(13, "RSI Length", group="RSI Settings")
rsiSourceInput = input(close, "Source", input.source, group="RSI Settings")
rsiColor = input(color.new(#328787, 0), "RSI Line Color", type=input.color)
ob = input(70, "Overbought Line", group="RSI Settings")
os = input(30, "Overbought Line", group="RSI Settings")

maOn = input(true, title="MA On", group="MA Settings")
maTypeInput = input("SMA", title="MA Type", options=["SMA", "Bollinger Bands", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group="MA Settings")
maLengthInput = input(14, title="MA Length", group="MA Settings")
bbMultInput = input(2.0, minval=0.001, maxval=50, title="BB StdDev", group="MA Settings")

zonesOn = input(true, title="Zones On", group="Zones")
bull_thresh = input(60, "Bull Threshhold", input.float, minval=0, group="Zones")
bear_thresh = input(35, "Bear Threshhold", input.float, minval=0, group="Zones")
plotBull = input(title='Plot Bullish', defval=true, group="Toggle Divergence Plotting"),
plotBear = input(title='Plot Bearish', defval=true, group="Toggle Divergence Plotting")
plotHiddenBull = input(title='Plot Hidden Bullish', defval=false, group="Toggle Divergence Plotting")
plotHiddenBear = input(title='Plot Hidden Bearish', defval=false, group="Toggle Divergence Plotting")

labelOn = input(true, title="Label On", group="Labels")
decimals = input(2, title="Decimals", group="Labels")
// }

// {FUNCTIONS
ma(source, length, type) =>
    if (type == "SMA")
        sma(source, length)
    else if (type == "Bollinger Bands")
        sma(source, length)
    else if (type == "EMA")
        ema(source, length)
    else if (type == "SMMA (RMA)")
        rma(source, length)
    else if (type == "WMA")
        wma(source, length)
    else if (type == "VWMA")
        vwma(source, length)

reverse(Level) =>
    x1 = (rsi_len - 1) * (rma(max(nz(close[1],close) - close, 0), rsi_len) * Level / (100 - Level) - rma(max(close - nz(close[1],close), 0), rsi_len))
    iff(x1 >= 0, close + x1, close + x1 * (100 - Level) / Level)

Round(src, digits) => 
    p = pow(10,digits)
    round(abs(src)*p)/p*sign(src)

rangeUpper = 60
rangeLower = 5
_inRange(cond) =>
    bars = barssince(cond == true)
    rangeLower <= bars and bars <= rangeUpper
// }

rsi = rsi(close, rsi_len)
rsiMA = ma(rsi, maLengthInput, maTypeInput)
var sessioncolor = color.black
lbR = 5,lbL = 5
revob = reverse(bull_thresh)
revos = reverse(bear_thresh)

// {DIVERGENCE
osc = rsi
plFound = na(pivotlow(osc, lbL, lbR)) ? false : true,phFound = na(pivothigh(osc, lbL, lbR)) ? false : true
oscHL = osc[lbR] > valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1]), oscLL = osc[lbR] < valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1])
oscHH = osc[lbR] > valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1]),oscLH = osc[lbR] < valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1])
priceLL = low[lbR] < valuewhen(plFound, low[lbR], 1), priceHL = low[lbR] > valuewhen(plFound, low[lbR], 1)
priceHH = high[lbR] > valuewhen(phFound, high[lbR], 1),priceLH = high[lbR] < valuewhen(phFound, high[lbR], 1)
bullCond = plotBull and priceLL and oscHL and plFound
hiddenBullCond = plotHiddenBull and priceHL and oscLL and plFound
bearCond = plotBear and priceHH and oscLH and phFound
hiddenBearCond = plotHiddenBear and priceLH and oscHH and phFound
bearColor = color.new(color.red, 0)
bullColor = color.new(color.green, 0)
hiddenBullColor = color.new(color.green, 0)
hiddenBearColor = color.new(color.red, 0)
textColor = color.white
noneColor = color.new(color.white, 100)
// }

var bull = false
if (bull and rsi < bear_thresh)
    bull := false
else if (not bull and rsi > bull_thresh)
    bull := true
sessioncolor := bull ? #0fb406 : #FF0000

// { PLOTS
plot(rsiOn ? rsi : na, title='RSI', color=rsiColor, linewidth=2)
plot(maOn ? rsiMA : na, "RSI-based MA", color=color.yellow)
plot(plFound ? osc[lbR] : na, offset=-lbR, title='Regular Bullish', linewidth=3, color=bullCond ? bullColor : noneColor)
plot(plFound ? osc[lbR] : na, offset=-lbR, title='Hidden Bullish', linewidth=3, color=hiddenBullCond ? hiddenBullColor : noneColor)
plot(phFound ? osc[lbR] : na, offset=-lbR, title='Regular Bearish', linewidth=3, color=bearCond ? bearColor : noneColor)
plot(phFound ? osc[lbR] : na, offset=-lbR, title='Hidden Bearish', linewidth=3, color=hiddenBearCond ? hiddenBearColor : noneColor)

hline(bull_thresh, color=color.green , linestyle=hline.style_dashed)
hline(bear_thresh, color=color.red , linestyle=hline.style_dashed)
obline = hline(ob, color=color.white , linestyle=hline.style_solid)
osline = hline(os, color=color.white , linestyle=hline.style_solid)
fill(obline, osline, color=zonesOn ? color.new(sessioncolor, 85) : na)

var tab = table.new(position.middle_right, 1, 2)
if barstate.islast and labelOn == true
    table.cell(table_id = tab, column = 0, row = 0, text_color=color.white, text = tostring(Round(bull_thresh,decimals)) + " Bull Zone Price : " + tostring(Round(revob,decimals)))
    table.cell(table_id = tab, column = 0, row = 1, text_color=color.white, text = tostring(Round(bear_thresh,decimals)) + " Bear Zone Price : " + tostring(Round(revos,decimals)))
// }