RSI Supreme Multi-Method [JacobMagleby]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © JacobMagleby

//@version=5
indicator(title = "RSI Supreme Multi-Method", overlay = false)

// { <CONSTANTS>

RSI_GROUP = "RSI Settings"
VOLATILITY_GROUP = "Volatility Method Settings"
SESSION_GROUP = "Session Method Settings"
SMOOTHED_GROUP = "Smoothed Method Settings"
DIVERGENCE_GROUP = "Divergence Settings"
TRANSPARENT = color.new(color.black, 100)

// } <CONSTANTS>



// { <INPUTS>

rsiLength = input.int(
 title = "RSI Length",
  defval = 14,
   group = RSI_GROUP)

rsiSrc = input.source(
 title = "RSI Source",
  defval = close,
   group = RSI_GROUP)

rsiOB = input.float(
 title = "Overbought Value",
  defval = 70,
   group = RSI_GROUP)

rsiOS = input.float(
 title = "Oversold Value",
  defval = 30,
   group = RSI_GROUP)

rsiMethod = input.string(
 title = "RSI Type",
  defval = "Standard",
   options = ["Standard", "Volatility Manipulated", "Session Manipulated", "Smoothed"],
     group = RSI_GROUP)

volatilityLen = input.int(
 title = "Length",
  defval = 50,
   group = VOLATILITY_GROUP)

smoothedLength = input.int(
 title = "Length",
  defval = 5,
   group = SMOOTHED_GROUP)

session1E = input.bool(
 title = "",
  defval = true,
   group = SESSION_GROUP,
     inline = "session1")

session1 = input.session(
 title = "",
  defval = "0000-0759",
   group = SESSION_GROUP,
     inline = "session1")

session1Mult = input.float(
 title = "Mult %",
  defval = 100,
   group = SESSION_GROUP,
     inline = "session1")

session2E = input.bool(
 title = "",
  defval = true,
   group = SESSION_GROUP,
     inline = "session2")

session2 = input.session(
 title = "",
  defval = "0800-1559",
   group = SESSION_GROUP,
     inline = "session2")

session2Mult = input.float(
 title = "Mult %",
  defval = 100,
   group = SESSION_GROUP,
     inline = "session2")

session3E = input.bool(
 title = "",
  defval = true,
   group = SESSION_GROUP,
     inline = "session3")

session3 = input.session(
 title = "",
  defval = "1559-2359",
   group = SESSION_GROUP,
     inline = "session3")

session3Mult = input.float(
 title = "Mult %",
  defval = 100,
   group = SESSION_GROUP,
     inline = "session3")

session4E = input.bool(
 title = "",
  defval = false,
   group = SESSION_GROUP,
     inline = "session4")

session4 = input.session(
 title = "",
  defval = "0000-0900",
   group = SESSION_GROUP,
     inline = "session4")

session4Mult = input.float(
 title = "Mult %",
  defval = 100,
   group = SESSION_GROUP,
     inline = "session4")

session5E = input.bool(
 title = "",
  defval = false,
   group = SESSION_GROUP,
     inline = "session5")

session5 = input.session(
 title = "",
  defval = "0000-0900",
   group = SESSION_GROUP,
     inline = "session5")

session5Mult = input.float(
 title = "Mult %",
  defval = 100,
   group = SESSION_GROUP,
     inline = "session5")

session6E = input.bool(
 title = "",
  defval = false,
   group = SESSION_GROUP,
     inline = "session6")

session6 = input.session(
 title = "",
  defval = "0000-0900",
   group = SESSION_GROUP,
     inline = "session6")

session6Mult = input.float(
 title = "Mult %",
  defval = 100,
   group = SESSION_GROUP,
     inline = "session6")

showDivs = input.bool(
 title = "Show Divergences",
  defval = true,
   group = DIVERGENCE_GROUP)

pivotSens = input.int(
 title = "Sensitivity",
  defval = 5,
   group = DIVERGENCE_GROUP)

divWidth = input.int(
 title = "Width",
  defval = 2,
   group = DIVERGENCE_GROUP)

bullColor = input.color(
 title = "",
  defval = color.blue,
   group = DIVERGENCE_GROUP,
     inline = "div")

bearColor = input.color(
 title = "",
  defval = color.blue,
   group = DIVERGENCE_GROUP,
     inline = "div")

// } <INPUTS>



// { <CALCULATIONS>

vol = ta.stdev(close / close[1], volatilityLen, true)
vol_percentile = 100 - ta.percentrank(vol, volatilityLen)

var volumeArray = array.new_float()
if barstate.isconfirmed
    if array.size(volumeArray) > 1000
        array.shift(volumeArray)
    array.push(volumeArray, volume)
maxVolume = array.max(volumeArray)
minVolume = array.min(volumeArray)
diff = maxVolume - minVolume
offMin = volume - minVolume
ratio = offMin / diff + 0.5

time1 = not na(time(timeframe.period, session1))
time2 = not na(time(timeframe.period, session2))
time3 = not na(time(timeframe.period, session3))
time4 = not na(time(timeframe.period, session4))
time5 = not na(time(timeframe.period, session5))
time6 = not na(time(timeframe.period, session6))

srcToUse = rsiMethod == "Standard" ? rsiSrc :
 rsiMethod == "Volatility Manipulated" ? rsiSrc * (vol_percentile / 100) :
  rsiMethod == "Session Manipulated" ? 
   (time1 and session1E ? rsiSrc * (session1Mult / 100) :
     time2 and session2E ? rsiSrc * (session2Mult / 100) :
      time3 and session3E ? rsiSrc * (session3Mult / 100) :
       time4 and session4E ? rsiSrc * (session4Mult / 100) :
         time5 and session5E ? rsiSrc * (session5Mult / 100) :
          time6 and session6E ? rsiSrc * (session6Mult / 100) : na) : rsiSrc

baseRsiValue = ta.rsi(srcToUse, rsiLength)
prevRsiValue = baseRsiValue[1]
smoothedRsi = ta.ema(baseRsiValue, smoothedLength)
baseRsiValue := rsiMethod == "Smoothed" ? smoothedRsi : baseRsiValue 

startOverSold = ta.crossunder(baseRsiValue, rsiOS)
startOverBought = ta.crossover(baseRsiValue, rsiOB)
overSold = baseRsiValue < rsiOS
overBought = baseRsiValue > rsiOB
unOverBought = baseRsiValue < rsiOB and baseRsiValue[1] >= rsiOB
unOverSold = baseRsiValue > rsiOS and baseRsiValue[1] <= rsiOS

pHigh = ta.pivothigh(baseRsiValue, pivotSens, pivotSens)
pLow = ta.pivotlow(baseRsiValue, pivotSens, pivotSens)

lastPHigh = ta.valuewhen(not na(pHigh), pHigh, 1)
lastPLow = ta.valuewhen(not na(pLow), pLow, 1)
lastPHighP = ta.valuewhen(not na(pHigh), high[pivotSens], 1)
lastPLowP = ta.valuewhen(not na(pLow), low[pivotSens], 1)
lastPHighO = ta.valuewhen(not na(pHigh), baseRsiValue[pivotSens], 1)
lastPLowO = ta.valuewhen(not na(pLow), baseRsiValue[pivotSens], 1)
lastPHighI = ta.valuewhen(not na(pHigh), bar_index[pivotSens], 1)
lastPLowI = ta.valuewhen(not na(pLow), bar_index[pivotSens], 1)

nBearDiv = pHigh < lastPHigh and high[pivotSens] > lastPHighP
nBullDiv = pLow > lastPLow and low[pivotSens] < lastPLowP

// } <CALCULATIONS>



// { <VISUALS>

topTopValue = rsiOB + 12
topBotValue = rsiOB
botTopValue = rsiOS
botBotValue = rsiOS - 12

hline(50, "mid", color.gray, hline.style_dashed, 1)
base  = plot(baseRsiValue, "RSI", baseRsiValue > prevRsiValue ? color.green : color.red, 1, plot.style_line, false, 0.0, 0, false, true)
trace = plot(prevRsiValue, "Prev RSI", TRANSPARENT, 2, plot.style_line, false, 0.0, 0, false, true)

fill(base, trace,
 top_value = baseRsiValue > prevRsiValue ? baseRsiValue : prevRsiValue,
  bottom_value = baseRsiValue > prevRsiValue ? prevRsiValue : baseRsiValue,
   top_color = baseRsiValue > prevRsiValue ? color.green : TRANSPARENT,
     bottom_color = baseRsiValue > prevRsiValue ? TRANSPARENT : color.red)

t1 = plot(topBotValue, "top1", TRANSPARENT, 1, plot.style_line)
t2 = plot(topTopValue, "top2", TRANSPARENT, 1, plot.style_line)
b1 = plot(botTopValue, "bot1", TRANSPARENT, 1, plot.style_line)
b2 = plot(botBotValue, "bot2", TRANSPARENT, 1, plot.style_line)

fill(t1, t2, top_value = topTopValue, bottom_value = topBotValue, top_color = color.new(color.red, 30), bottom_color = color.new(color.red, 100))
fill(b1, b2, top_value = botTopValue, bottom_value = botBotValue, top_color = color.new(color.green, 100), bottom_color = color.new(color.green, 30))

plotshape(
 series = startOverBought ? rsiOB + 15 : na,
  title = "Start Overbought",
   style = shape.cross,
     location = location.absolute,
      color = color.red,
       size = size.tiny)

plotshape(
 series = overBought and overBought[1] ? rsiOB + 15 : na,
  title = "Overbought",
   style = shape.cross,
     location = location.absolute,
      color = color.blue,
       size = size.tiny)

plotshape(
 series = startOverSold ? rsiOS - 15 : na,
  title = "Start Oversold",
   style = shape.cross,
     location = location.absolute,
      color = color.green,
       size = size.tiny)

plotshape(
 series = overSold and overSold[1] ? rsiOS - 15 : na,
  title = "Oversold",
   style = shape.cross,
     location = location.absolute,
      color = color.blue,
       size = size.tiny)

plotshape(
 series = unOverBought ? rsiOB + 15 : na,
  title = "Un-Overbought",
   style = shape.cross,
     location = location.absolute,
      color = color.orange,
       size = size.tiny)

plotshape(
 series = unOverSold ? rsiOS - 15 : na,
  title = "Un-Oversold",
   style = shape.cross,
     location = location.absolute,
      color = color.orange,
       size = size.tiny)

if barstate.isconfirmed and showDivs
    if nBearDiv
        line.new(
         x1 = bar_index[pivotSens], y1 = baseRsiValue[pivotSens],
          x2 = lastPHighI, y2 = lastPHighO, xloc = xloc.bar_index,
           color = bearColor, width = divWidth)

    if nBullDiv
        line.new(
         x1 = bar_index[pivotSens], y1 = baseRsiValue[pivotSens],
          x2 = lastPLowI, y2 = lastPLowO, xloc = xloc.bar_index,
           color = bullColor, width = divWidth)

// } <VISUALS>



// { <ALERTS>

alertcondition(startOverBought, title = "New Overbought")
alertcondition(overBought, "Currently Overbought")
alertcondition(unOverBought, "Un-Overbought")

alertcondition(startOverSold, title = "New Oversold")
alertcondition(overSold, "Currently Oversold")
alertcondition(unOverSold, "Un-Oversold")

alertcondition(nBearDiv, "Bearish Divergence")
alertcondition(nBullDiv, "Bullish Divergence")

// } <ALERTS>