RSI + rCalc
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TdB1

//@version=5
indicator(title="Relative Strength Index", shorttitle="RSI", format=format.price, precision=2)


//User Inputs//
len = input.int(14, minval=1, title="RSI Length", group="RSI Settings")
src = input.source(close, "Source", group="RSI Settings")
maTypeInput = input.string("SMA", title="MA Type", options=["SMA", "Bollinger Bands", "EMA", "SMMA (RMA)", "WMA", "VWMA", "ALMA", "HMA"], group="MA Settings")
maLengthInput = input.int(14, title="MA Length", group="MA Settings")
bbMultInput = input.float(2.0, minval=0.001, maxval=50, title="BB StdDev", group="MA Settings")
ob = input.float(70.0, 'Overbought Input', minval=0, step=5)
os = input.float(30.0, 'Oversold Input', minval=0, step=5)
pan = input(true, ' Show Information Panel')
off = input.int(35, '  Panel Position Offset', minval=0)
s = input(true, 'Show Entered RSI Price Level')
ersi = input(40.0, '  Entered RSI Input')
s2 = input(false, 'Show RSI Level for Input Price')
ip = input.float(10000, '  Entered Price for RSI')
dec = input.int(1, 'Decimals', minval=0, maxval=10)
bg = input(false, 'Invisible Background')
//alma//
stperiod = input.int(title='Period for ALMA', defval=21, group='MA Settings')
stoffset = input.float(title='Offset for ALMA', step=0.025, defval=0.8, group='MA Settings')
stsigma = input.float(title='Sigma for ALMA', step=0.5, defval=6, group='MA Settings')
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)
        "ALMA" =>ta.alma(source, stperiod, stoffset, stsigma)
        "HMA" => ta.hma(source, length)

up = ta.rma(math.max(ta.change(src), 0), len)
down = ta.rma(-math.min(ta.change(src), 0), len)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
rsiMA = ma(rsi, maLengthInput, maTypeInput)
isBB = maTypeInput == "Bollinger Bands"
stalma=ta.alma(rsi, stperiod, stoffset, stsigma)
up_color = input.color(#66bb6a, 'RSI Cross Down', group='Short-term ALMA')
down_color = input.color(#ef5350, 'RSI Cross Up', group='Short-term ALMA')
macolor = rsiMA>rsi ? up_color : down_color


Round(value, decimals) =>
    float v = math.pow(10, decimals)
    math.round(math.abs(value) * v) / (v * math.sign(value))
    //
    
plot(rsi, "RSI", color=#7E57C2)
plot(rsiMA, "RSI-based MA", color=macolor)
rsiUpperBand = hline(70, "RSI Upper Band", color=#787B86)
hline(50, "RSI Middle Band", color=color.new(#787B86, 50))
rsiLowerBand = hline(30, "RSI Lower Band", color=#787B86)
fill(rsiUpperBand, rsiLowerBand, color=color.rgb(126, 87, 194, 90), title="RSI Background Fill")
bbUpperBand = plot(isBB ? rsiMA + ta.stdev(rsi, maLengthInput) * bbMultInput : na, title = "Upper Bollinger Band", color=color.green)
bbLowerBand = plot(isBB ? rsiMA - ta.stdev(rsi, maLengthInput) * bbMultInput : na, title = "Lower Bollinger Band", color=color.green)
fill(bbUpperBand, bbLowerBand, color= isBB ? color.new(color.green, 90) : na, title="Bollinger Bands Background Fill")

/// reverse RSI///


//Reverse RSI Functions
reverse(Level) =>
    x1 = (len - 1) * (ta.rma(math.max(nz(src[1], src) - src, 0), len) * Level / (100 - Level) - ta.rma(math.max(src - nz(src[1], src), 0), len))
    x1 >= 0 ? src + x1 : src + x1 * (100 - Level) / Level


//Reverse RSI Price Level Calculations
revma = reverse(rsiMA)
revob = reverse(ob)
revos = reverse(os)
reversi = reverse(ersi)

//Reverse Reverse RSI
rr(input) =>
    alpha = 1 / len
    up1 = ta.rma(math.max(ta.change(src), 0), len)
    down1 = ta.rma(-math.min(ta.change(src), 0), len)
    up = alpha * math.max(input - src[1], 0) + (1 - alpha) * nz(up1[1])
    down = alpha * -math.min(input - src[1], 0) + (1 - alpha) * nz(down1[1])
    rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - 100 / (1 + up / down)
    rsi


rrrsi = rr(ip)


//Information Panel
labelstyle = label.style_label_center
labelstyle2 = label.style_label_down

labelc = bg ? color.new(#000000, 100) : color.new(#000000, 45)

    
//Offset 
xp(offset) =>
    time + math.round(ta.change(time) * offset)
lable1(offset, P, T, s, color_PnL) =>
    label PnL_Label = na
    PnL_Label := label.new(xp(offset), P, text=T, color=color_PnL, textcolor=#b2b5be, style=s, yloc=yloc.price, xloc=xloc.bar_time, size=size.normal)
    label.delete(PnL_Label[1])


ud() =>
    if rsi < rsiMA
        'UP MA'
    else
        'DOWN MA'

//Panel Plot
if pan
    lable1(off, 50, 'RSI Cross ' + ud() + ' Price : ' + str.tostring(Round(revma, dec)) + '\n\n' + str.tostring(Round(ob, dec)) + ' Overbought Level Price : ' + str.tostring(Round(revob, dec)) + '\n\n' + str.tostring(Round(os, dec)) + ' Oversold Level Price : ' + str.tostring(Round(revos, dec)), labelstyle, labelc)


if s
    lable1(off, 50, str.tostring(Round(ersi, dec)) + ' RSI Price : ' + str.tostring(Round(reversi, dec)), labelstyle2, labelc)


if s2
    lable1(1, rrrsi, 'RSI ' + str.tostring(Round(rrrsi, dec)) + ' For Input Price ' + str.tostring(Round(ip, dec)), labelstyle2, labelc)

        
