Volume Adaptive Chikou Scalping Study
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © MightyZinger
//@version=4

study(shorttitle="MZ Adaptive Scalping",title="Volume Adaptive Chikou Scalping Study", overlay=true)

timeFrameticker  = input("",type=input.resolution, title="Timeframe")
uha   =input(true, title="Use Heikin Ashi Candles for Volume")
uha2   =input(false, title="Use Heikin Ashi Candles for Chikou Calculations")

// Use only Heikinashi Candles for all calculations
haclose = uha ? security(heikinashi(syminfo.tickerid), timeFrameticker, close) : security(syminfo.tickerid, timeFrameticker, close)
haopen = uha ? security(heikinashi(syminfo.tickerid), timeFrameticker, open) : security(syminfo.tickerid, timeFrameticker, open)
hahigh = security(syminfo.tickerid, timeFrameticker, high)
halow = security(syminfo.tickerid, timeFrameticker, low)

src = security(heikinashi(syminfo.tickerid), timeFrameticker, close)
vol = security(syminfo.tickerid, timeFrameticker, volume)


//  INPUT RESOLUTION
highMAresolution = input("",type=input.resolution, title="High MA Resolution")
lowMAresolution = input("",type=input.resolution, title="Low MA Resolution")
haMAhigh = security(syminfo.tickerid, highMAresolution, high)
haMAhigh_close = uha2 ? security(heikinashi(syminfo.tickerid), highMAresolution, close) : security(syminfo.tickerid, highMAresolution, close)
haMAlow = security(syminfo.tickerid, lowMAresolution, low)
haMAlow_close = uha2 ?security(heikinashi(syminfo.tickerid), lowMAresolution, close) : security(syminfo.tickerid, lowMAresolution, close)


//  INPUT LENGTHS
highminLength = input(20, minval=1, title="High MA Min Length", inline="h_len")
highmaxLength = input(50, minval=1, title="High MA Max Length", inline="h_len")
lowminLength = input(20, minval=1, title="Low MA Min Length", inline="l_len")
lowmaxLength = input(50, minval=1, title="Low MA Max Length", inline="l_len")


// Adaptive Length Checks

grp1 = "Adapt Dynamic Length Based on (Max Length if both left unchecked)"
grp2 = "Signals Confirmations Based on"

ch1 = "Volume"
ch2 = "Volatility"

adaptPerc    = input(3.141, minval = 0, maxval = 100, title="Adapting Percentage:", group = grp1) / 100.0
volume_chk = input(true, title= ch1, group= grp1, inline="len_chks")
volat_chk = input(true, title= ch2, group= grp1, inline="len_chks")

t_volume_chk = input(true, title= ch1, group= grp2, inline="trd_chks")
t_volat_chk = input(false, title= ch2, group= grp2, inline="trd_chks")


/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

// Volume and other Inputs
// Volume Oscillator Types Input
osc1 = "TFS Volume Oscillator"
osc2 = "On Balance Volume"
osc3 = "Klinger Volume Oscillator"
osc4 = "Cumulative Volume Oscillator"
osc5 = "Volume Zone Oscillator"
osctype = input(title="Volume Oscillator Type", type=input.string, group="MZ RVSI Indicator Parameters", defval = osc1, options=[osc1, osc2, osc3, osc4, osc5])

volLen = input(30, minval=1,title="Volume Length", group="MZ RVSI Indicator Parameters")
rvsiLen = input(14, minval=1,title="RVSI Period",  group="MZ RVSI Indicator Parameters")
vBrk = input(50, minval=1,title="RVSI Break point",  group="MZ RVSI Indicator Parameters")

atrFlength         = input(14, title="ATR Fast Length", group="Volatility Dynamic Optimization Parameters")
atrSlength         = input(46, title="ATR Slow Length", group="Volatility Dynamic Optimization Parameters")



/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////                Dynamic Length Function                   //////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////


dyn_Len(volume_chk, volat_chk, volume_Break, high_Volatility, adapt_Pct, minLength, maxLength) =>
    var float result = avg(minLength,maxLength)
    para = (volume_chk == true and volat_chk == false) ? volume_Break : (volume_chk == false and volat_chk == true) ? high_Volatility : (volume_chk == true and volat_chk == true) ? volume_Break and high_Volatility : na
    result := iff(para, max(minLength, result * (1 - adapt_Pct)), min(maxLength, result * (1 + adapt_Pct)))
    result


// Up/Down parameter function to mark market dynamics 

_uppara(volume_chk, volat_chk, vol_Brk_up, high_Volatility) =>
    bool up_para = 0.0

    if volume_chk == true and volat_chk == false
        up_para := vol_Brk_up

    if volume_chk == false and volat_chk == true
        up_para := high_Volatility

    if volume_chk == true and volat_chk == true
        up_para := high_Volatility and vol_Brk_up

    if volume_chk == false and volat_chk == false
        up_para := na
    up_para

_dnpara(volume_chk, volat_chk, vol_Brk_dn, high_Volatility) =>
    bool dn_para = 0.0
   
    if volume_chk == true and volat_chk == false
        dn_para := vol_Brk_dn
    
    if volume_chk == false and volat_chk == true
        dn_para := high_Volatility
    
    if volume_chk == true and volat_chk == true
        dn_para := high_Volatility and vol_Brk_dn
    
    if volume_chk == false and volat_chk == false
        dn_para := na
    dn_para
    
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////             Volume Oscillator Functions                  //////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

// Volume Zone Oscillator

zone(_src, _type, _len) =>
    vp = _src > _src[1] ? _type : _src < _src[1] ? -_type : _src == _src[1] ? 0 : 0
    z = 100 * (ema(vp, _len) / ema(_type, _len))

vzo(vol_src, _close) =>
    float result = 0
    zLen = input(21, "VZO Length", minval=1, group="Volume Zone Oscillator Parameters")
    result := zone(_close, vol_src, zLen)
    result

//  Cumulative Volume Oscillator

_rate(cond, tw, bw, body) =>
    ret = 0.5 * (tw + bw + (cond ? 2 * body : 0)) / (tw + bw + body) 
    ret := nz(ret) == 0 ? 0.5 : ret
    ret

cvo(vol_src, _open, _high, _low, _close) =>
    float result = 0
    ema1len = input(defval = 8, title = "EMA 1 Length", minval = 1, group="Cumulative Volume Oscillator Parameters")
    ema2len = input(defval = 21, title = "EMA 1 Length", minval = 1, group="Cumulative Volume Oscillator Parameters")
    obvl = "On Balance Volume"
    cvdo = "Cumulative Volume Delta"
    pvlt = "Price Volume Trend"
    cvtype = input(defval = pvlt, options = [obvl, cvdo, pvlt], group="Cumulative Volume Oscillator Parameters")

    tw = _high - max(_open, _close) 
    bw = min(_open, _close) - _low 
    body = abs(_close - _open) 

    deltaup =  vol_src * _rate(_open <= _close , tw, bw, body) 
    deltadown = vol_src * _rate(_open > _close , tw, bw, body) 
    delta = _close >= _open ? deltaup : -deltadown
    cumdelta = cum(delta)
    float ctl = na
    ctl := cumdelta
    cv = cvtype == obvl ? obv : cvtype == cvdo ? ctl : pvt
    ema1 = ema(cv,ema1len)
    ema2 = ema(cv,ema2len)
    result := ema1 - ema2 
    result

//  Volume Oscillator function

vol_osc(type, vol_src, vol_Len, _open, _high, _low, _close) =>
    float result = 0
    if type=="TFS Volume Oscillator"
        nVolAccum = sum(iff(_close > _open, vol_src, iff(_close < _open, -vol_src, 0))  ,vol_Len)
        result := nVolAccum / vol_Len
    if type=="On Balance Volume"
        result :=  cum(sign(change(_close)) * vol_src)
    if type=="Klinger Volume Oscillator"
        FastX = input(34, minval=1,title="Volume Fast Length", group="KVO Parameters")
        SlowX = input(55, minval=1,title="Volume Slow Length", group="KVO Parameters")
        xTrend = iff(_close > _close[1], vol * 100, -vol * 100)
        xFast = ema(xTrend, FastX)
        xSlow = ema(xTrend, SlowX)
        result :=  xFast - xSlow
    if type=="Cumulative Volume Oscillator"
        result := cvo(vol_src, _open, _high, _low, _close)
    if type=="Volume Zone Oscillator"
        result := vzo(vol_src, _close)
    result
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////


// MA of Volume Oscillator Source
volMA = sma(vol_osc(osctype,vol,volLen,haopen,hahigh,halow,haclose) , rvsiLen) // HMA can also be used just like used in RVSI's original Indicator

// RSI of Volume Oscillator Data
rsivol = rsi(volMA, rvsiLen)
rvsi = hma(rsivol, rvsiLen)

// Volume Breakout Condition
volBrkUp = rvsi > vBrk // and rvsiSlp >=  flat 
volBrkDn = rvsi < vBrk //or rvsiSlp <= -flat //

//Volatility Meter
highVolatility = atr(atrFlength) > atr(atrSlength)                  

/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

high_dyna = dyn_Len(volume_chk, volat_chk, volBrkUp, highVolatility, adaptPerc, highminLength, highmaxLength)
low_dyna = dyn_Len(volume_chk, volat_chk, volBrkUp, highVolatility, adaptPerc, lowminLength, lowmaxLength)
plotchar(high_dyna, "Slow MA Dynamic Length", "", location.top, color.green) 
plotchar(low_dyna, "Fast MA Dynamic Length", "", location.top, color.yellow) 


//  Linear Regression

highma = linreg(haMAhigh , int(high_dyna), 0)
lowma = linreg(haMAlow , int(low_dyna), 0)

swing = iff(haMAhigh_close > highma[int(high_dyna)], 1, iff(haMAlow_close < lowma[int(low_dyna)], -1, 0))
_high = highest(haMAhigh, int(high_dyna))
_low = lowest(haMAlow, int(low_dyna))
var float stop = 0.0
stop := iff(swing==1, _low, iff(swing==-1, _high, stop[1]))

/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

// Signals

up_para = _uppara(t_volume_chk, t_volat_chk, volBrkUp, highVolatility)
dn_para = _dnpara(t_volume_chk, t_volat_chk, volBrkDn, highVolatility)

_up = src > stop and up_para
_dn = src < stop and dn_para

buy  = _up and not _up[1] 
sell = _dn and not _dn[1] 


var sig = 0
if buy and sig <= 0
    sig := 1
if sell and sig >= 0 
    sig := -1

longsignal  = sig ==  1 and (sig !=  1)[1]
shortsignal = sig == -1 and (sig != -1)[1]


linecolor = iff(stop < haMAlow, color.green, color.red)
stop_plot = plot(stop, linewidth=4, color=linecolor, transp = 80)

//plot(highma, title='High MA', color=color.olive, linewidth=2)
//plot(lowma, title='Low MA', color=color.teal, linewidth=2)


plotshape(longsignal, style = shape.triangleup, color = color.green, location = location.belowbar, text = "Long", size = size.small)
plotshape(shortsignal, style = shape.triangledown, color = color.red, location = location.abovebar, text = "Short", size = size.small)


//  Envelop Parameters
showEnv    = input(true, title="Show Envelope", group="ENVELOPE DISTANCE ZONE")
atr_mult        = input(10, title="Distance (Envelope) Multiplier", step=.1, group="ENVELOPE DISTANCE ZONE")
env_atr    = input(40, title="Envelope ATR Length", group="ENVELOPE DISTANCE ZONE")


env_MA = stop
dev = atr_mult * atr(env_atr)

// Bands
m1 = input(0.236, minval=0, step=0.01, title="Fib 1", group= "Fibonacci Parameters", inline = "fibs1")
m2 = input(0.382, minval=0, step=0.01, title="Fib 2", group= "Fibonacci Parameters", inline = "fibs1")
m3 = input(0.5, minval=0, step=0.01, title="Fib 3", group= "Fibonacci Parameters", inline = "fibs1")
m4 = input(0.618, minval=0, step=0.01, title="Fib 4", group= "Fibonacci Parameters", inline = "fibs1")
m5 = input(0.764, minval=0, step=0.01, title="Fib 5", group= "Fibonacci Parameters", inline = "fibs1")
m6 = input(1, minval=0, step=0.01, title="Fib 6", group= "Fibonacci Parameters", inline = "fibs1")
m7 = input(1.618, minval=0, step=0.01, title="Fib 7", group= "Fibonacci Parameters", inline = "fibs1")
m8 = input(2.618, minval=0, step=0.01, title="Fib 8", group= "Fibonacci Parameters", inline = "fibs1")

upper_1= iff(src > stop, env_MA + (m1*dev), env_MA - (m1*dev))
upper_2= iff(src > stop, env_MA + (m2*dev), env_MA - (m2*dev))
upper_3= iff(src > stop, env_MA + (m3*dev), env_MA - (m3*dev))
upper_4= iff(src > stop, env_MA + (m4*dev), env_MA - (m4*dev))
upper_5= iff(src > stop, env_MA + (m5*dev), env_MA - (m5*dev))
upper_6= iff(src > stop, env_MA + (m6*dev), env_MA - (m6*dev))

// Plotting Envelope Distance Zone

p1 = plot(showEnv ? upper_1 : na, color=color.new(color.red, 50), linewidth=1, title="0.236")
p2 = plot(showEnv ? upper_2 : na, color=color.new(color.red, 50), linewidth=1, title="0.382")
p3 = plot(showEnv ? upper_3 : na, color=color.new(color.aqua, 50), linewidth=3, title="0.5")
p4 = plot(showEnv ? upper_4 : na, color=color.new(color.blue, 50), linewidth=1, title="0.618")
p5 = plot(showEnv ? upper_5 : na, color=color.new(color.blue, 50), linewidth=1, title="0.764")
p6 = plot(showEnv ? upper_6 : na, color=color.new(color.blue, 50), linewidth=2, title="1")


fill(p1, stop_plot, color=color.red, transp=95)
fill(p5, p6, color=color.green, transp=95)



// For Strategy Entries
//if (longsignal)
//    strategy.entry("BUY", strategy.long, when = window())

//if (shortsignal)
//    strategy.entry("SELL", strategy.short, when = window())
