RVSI
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © MightyZinger

//@version=5

// @description This Library contains functions that calculate all types of "Relative Volume Strength Index (MZ RVSI)" depending upon unique volume oscillator. Achieved RVSI value can be used for divergence in volume or to adapt dynamic length in Moving Averages.

library("RVSI", overlay=false)


// @function Relative Volume Strength Index based on TFS Volume Oscillator
// @param vol_src        Volume Source
// @param vol_Len        Volume Legth for TFS Volume Oscillato
// @param rvsiLen        Period of Relative Volume Strength Index
// @param _open          Ticker Open Value
// @param _close         Ticker Close Value
// @returns              Relative Volume Strength Index value based on TFS Volume Oscillator
export rvsi_tfs(float vol_src, simple int vol_Len, simple int rvsiLen, float _open, float _close) =>
    float result = 0
    nVolAccum = math.sum((_close > _open ? vol_src : _close < _open ? -vol_src : 0) ,vol_Len)
    result := nVolAccum / vol_Len
	var float rvsi = 0.0
    // MA of Volume Oscillator Source
    volMA = ta.sma(result , rvsiLen)
    // RSI of Volume Oscillator Data
    rsivol = ta.rsi(volMA, rvsiLen)
    rvsi := ta.hma(rsivol, rvsiLen)
    rvsi

// @function Relative Volume Strength Index based on On Balance Volume
// @param vol_src        Volume Source to Calculate On Balance Volume
// @param rvsiLen        Period of Relative Volume Strength Index
// @param _close         Ticker Close Value
// @returns              Relative Volume Strength Index value based on On Balance Volume    
export rvsi_obv(float vol_src, float _close, simple int rvsiLen) =>
    float result = 0
    result :=  ta.cum(math.sign(ta.change(_close)) * vol_src)
	var float rvsi = 0.0
    // MA of Volume Oscillator Source
    volMA = ta.sma(result , rvsiLen)
    // RSI of Volume Oscillator Data
    rsivol = ta.rsi(volMA, rvsiLen)
    rvsi := ta.hma(rsivol, rvsiLen)
    rvsi    

// @function Relative Volume Strength Index based on Klinger Volume Oscillator
// @param vol_src        Volume Source
// @param FastX          Volume Fast Length
// @param SlowX          Volume Slow Length
// @param rvsiLen        Period of Relative Volume Strength Index
// @param _close         Ticker Close Value
// @returns              Relative Volume Strength Index value based on Klinger Volume Oscillator
export rvsi_kvo(float vol_src, float _close, simple int FastX, simple int SlowX, simple int rvsiLen) =>    
    float result = 0
    xTrend = _close > _close[1] ? vol_src * 100 : -vol_src * 100
    xFast = ta.ema(xTrend, FastX)
    xSlow = ta.ema(xTrend, SlowX)
    result :=  xFast - xSlow
	var float rvsi = 0.0
    // MA of Volume Oscillator Source
    volMA = ta.sma(result , rvsiLen)
    // RSI of Volume Oscillator Data
    rsivol = ta.rsi(volMA, rvsiLen)
    rvsi := ta.hma(rsivol, rvsiLen)
    rvsi

// @function Relative Volume Strength Index based on Volume Zone Oscillator
// @param vol_src        Volume Source
// @param zLen           Volume Legth for Volume Zone Oscillator
// @param rvsiLen        Period of Relative Volume Strength Index
// @param _close         Ticker Close Value
// @returns              Relative Volume Strength Index value based on Volume Zone Oscillator
export rvsi_vzo(float vol_src, float _close, simple int zLen, simple int rvsiLen) =>
    float result = 0
    var float _z = 0.0
    vp = _close > _close[1] ? vol_src : _close < _close[1] ? -vol_src : _close == _close[1] ? 0 : 0
    result := 100 * (ta.ema(vp, zLen) / ta.ema(vol_src, zLen))
	var float rvsi = 0.0
    // MA of Volume Oscillator Source
    volMA = ta.sma(result , rvsiLen)
    // RSI of Volume Oscillator Data
    rsivol = ta.rsi(volMA, rvsiLen)
    rvsi := ta.hma(rsivol, rvsiLen)
    rvsi

// @function Relative Volume Strength Index based on Cumulative Volume Oscillator with On Balance Volume as Calculations Source
// @param vol_src        Volume Source
// @param ema1len        EMA Fast Length
// @param ema2len        EMA Slow Length
// @param rvsiLen        Period of Relative Volume Strength Index
// @returns              Relative Volume Strength Index value based on Cumulative Volume Oscillator with On Balance Volume as Calculations Source 
export rvsi_cvo_obv(simple int ema1len, simple int ema2len, simple int rvsiLen) =>
    float result = 0
    cv = ta.obv
    ema1 = ta.ema(cv,ema1len)
    ema2 = ta.ema(cv,ema2len)
    result := ema1 - ema2 
	var float rvsi = 0.0
    // MA of Volume Oscillator Source
    volMA = ta.sma(result , rvsiLen)
    // RSI of Volume Oscillator Data
    rsivol = ta.rsi(volMA, rvsiLen)
    rvsi := ta.hma(rsivol, rvsiLen)
    rvsi

// @function Relative Volume Strength Index based on Cumulative Volume Oscillator with Price Volume Trend as Calculations Source
// @param vol_src        Volume Source
// @param FastX          EMA Fast Length
// @param SlowX          EMA Slow Length
// @param rvsiLen        Period of Relative Volume Strength Index
// @returns              Relative Volume Strength Index value based on Cumulative Volume Oscillator with Price Volume Trend as Calculations Source     
export rvsi_cvo_pvt(simple int ema1len, simple int ema2len, simple int rvsiLen) =>
    float result = 0
    cv = ta.pvt
    ema1 = ta.ema(cv,ema1len)
    ema2 = ta.ema(cv,ema2len)
    result := ema1 - ema2 
	var float rvsi = 0.0
    // MA of Volume Oscillator Source
    volMA = ta.sma(result , rvsiLen)
    // RSI of Volume Oscillator Data
    rsivol = ta.rsi(volMA, rvsiLen)
    rvsi := ta.hma(rsivol, rvsiLen)
    rvsi

// @function Relative Volume Strength Index based on Cumulative Volume Oscillator with Cumulative Volume Delta as Calculations Source
// @param vol_src        Volume Source
// @param FastX          EMA Fast Length
// @param SlowX          EMA Slow Length
// @param rvsiLen        Period of Relative Volume Strength Index
// @param _open          Ticker Open Value
// @param _close         Ticker Close Value
// @param _high          Ticker High Value
// @param _low           Ticker Low Value
// @returns              Relative Volume Strength Index value based on Cumulative Volume Oscillator with Cumulative Volume Delta as Calculations Source  
export rvsi_cvo_cvd(float vol_src, simple int ema1len, simple int ema2len, simple int rvsiLen, float _open, float _high, float _low, float _close) =>    
    float result = 0  
    float ctl = na
    tw = _high - math.max(_open, _close) 
    bw = math.min(_open, _close) - _low 
    body = math.abs(_close - _open)
    rate_up = 0.5 * (tw + bw + (_open <= _close ? 2 * body : 0)) / (tw + bw + body) 
    rate_up := nz(rate_up) == 0 ? 0.5 : rate_up
    deltaup =  vol_src * rate_up
    rate_dn = 0.5 * (tw + bw + (_open > _close ? 2 * body : 0)) / (tw + bw + body) 
    rate_dn := nz(rate_dn) == 0 ? 0.5 : rate_dn
    deltadown = vol_src * rate_dn
    delta = _close >= _open ? deltaup : -deltadown
    cumdelta = ta.cum(delta)
    ctl := cumdelta
    cv = ctl
    ema1 = ta.ema(cv,ema1len)
    ema2 = ta.ema(cv,ema2len)
    result := ema1 - ema2 
	var float rvsi = 0.0
    // MA of Volume Oscillator Source
    volMA = ta.sma(result , rvsiLen)
    // RSI of Volume Oscillator Data
    rsivol = ta.rsi(volMA, rvsiLen)
    rvsi := ta.hma(rsivol, rvsiLen)
    rvsi    


// RVSI IndicatorPlot

mz_rvsi_tfs = rvsi_tfs(volume, 30, 14, open, close)
mz_rvsi_obv = rvsi_obv(volume, close, 14)
mz_rvsi_kvo = rvsi_kvo(volume, close, 50, 200, 14)
mz_rvsi_vzo = rvsi_vzo(volume, close, 21, 14)
mz_rvsi_cvo_obv = rvsi_cvo_obv(8, 21, 14)
mz_rvsi_cvo_pvt = rvsi_cvo_pvt(8, 21, 14)
mz_rvsi_cvo_cvd = rvsi_cvo_cvd(volume, 8, 21, 14, open, high, low, close)

plot(mz_rvsi_tfs, "MZ RVSI TFS", color.green, 2)
plot(mz_rvsi_obv, "MZ RVSI OBV", color.yellow, 2)
plot(mz_rvsi_kvo, "MZ RVSI KVO", color.red, 2)
plot(mz_rvsi_vzo, "MZ RVSI VZO", color.maroon, 2)
plot(mz_rvsi_cvo_obv, "MZ RVSI CVO:OBV", color.aqua, 2)
plot(mz_rvsi_cvo_pvt, "MZ RVSI CVO:PVT", color.purple, 2)
plot(mz_rvsi_cvo_cvd, "MZ RVSI CVO:CVD", color.lime, 2)

TopBand   = 80
LowBand   = 20
MidBand   = 50

hline(TopBand, color=color.red,linestyle=hline.style_dotted, linewidth=2)
hline(LowBand, color=color.green, linestyle=hline.style_dotted, linewidth=2)
hline(MidBand, color=color.lime, linestyle=hline.style_dotted, linewidth=1)


