Up Down Volatility
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Koalems
// @version=5

import Koalems/Library_Smoothers/3 as Smoothers

RMA(float src, int len) =>
	alpha = 1 / len
	sum = 0.0
	sum := na(sum[1]) ? ta.sma(src, len) : alpha * src + (1 - alpha) * nz(sum[1])

ATR(float High, float Low, float Close, int len) =>
    tr  = na(High[1]) ? High - Low : math.max(math.max(High - Low, math.abs(High - Close[1])), math.abs(Low - Close[1]))
    atr = RMA(tr, len)
    atr

// v = σ√T
// where:
//   v = volatility over some interval of time
//   σ = standard deviation of returns
//   T = number of periods in the time horizon
Volatility(rVolSrc, len) => ta.stdev(rVolSrc, len) * math.sqrt(len)

indicator(
  title         = "Up Down Volatility", 
  shorttitle    = "UD Volatility",
  overlay       = false
  )

Group0000 = 'Show'
rVolShowVolatility                     = input.bool(false,                           'Volatility',                                               group=Group0000)
rVolShowUpDown                         = input.bool(true,                            'Up/down',                                                  group=Group0000, inline='rVolMa.2')
rVolShowDiff                           = input.bool(true,                            'Relative strength',                                        group=Group0000, inline='rVolMa.2')
rVolShowUpDownRel                      = input.bool(false,                           'Relative up/down',                                         group=Group0000, inline='rVolMa.3')
rVolShowDiffRel                        = input.bool(false,                           'Relative strength',                                        group=Group0000, inline='rVolMa.3')

Group0010 = 'Settings'
rVolUseAtrAsSrc                        = input.bool(false,                           "Use ATR's of high/low/close as the source",                group=Group0010, tooltip='Otherwise uses high/low/close')
useMA                                  = input.bool(false,                           "Use moving average",                                       group=Group0010)
atrLen                                 = input.int(10,                               'ATR length',                                               group=Group0010, minval=1)

Group0020 = 'MA: Settings'

correctedToolTip="Corrected Average indicator by A.Uhl (also known as the “Optimal Moving Average“).\n\nThe strengths of the corrected Average (CA) is that the current value of the time series must exceed a the current volatility-dependent threshold, so that the filter increases or falls, avoiding false signals in a weak trend phase.\n– by Prof. A.Uhl –"

rVolMaCorrected                        = input.bool(false,                           'Corrected',                                                group=Group0020, tooltip=correctedToolTip)
rVolMaType                             = input.string('SMMA',                        'MA type',                                                  group=Group0020, inline='rVolMa.4', options=['None', 'AST_RMA', 'EMA', 'EHMA', 'FRAMA', 'Jurik', 'HMA', 'LINREG', 'RMA', 'SMA', 'SMMA', 'SrVolUper Smoother', 'SWMA', 'VAWMA', 'VIDYA', 'VWMA', 'WMA'])
rVolMaLength                           = input.int(10,                               'Length',                                                   group=Group0020, inline='rVolMa.4', minval=1, step=10)

Group0030 = 'MA: Settings: Extra'
rVolMaFramaFast                        = input.int(2,                                'FRAMA: Fast',                                              group=Group0030, inline='rVolMa.5', minval=1, step=1)
rVolMaFramaSlow                        = input.int(200,                              'Slow',                                                     group=Group0030, inline='rVolMa.5', minval=1, step=10)
rVolMaJurikPhase                       = input.int(50,                               'Jurik: Phase',                                             group=Group0030, inline='rVolMa.6', minval=-100, maxval=100, step=5)
rVolMaJurikPower                       = input.float(2,                              'Power',                                                    group=Group0030, inline='rVolMa.6', minval=0, step=0.25)
rVolMaLinRegOffset                     = input.int(0,                                'Lin. Reg.: Offset',                                        group=Group0030, inline='rVolMa.6', minval=0, step=1)
rVolMaVwwmaStartingWeight              = input.int(1,                                'VAWMA: Starting weight',                                   group=Group0030, inline='rVolMa.7', minval=0, step=1)
rVolMaVwwmaVolumeDefault               = input.int(0,                                'Vol. default',                                             group=Group0030, inline='rVolMa.7', minval=0, step=1)

rVolUpDown      = math.sign(close - close[1])

var rVolDnClose = 0., var rVolDnHigh = 0., var rVolDnLow  = 0.
var rVolUpClose = 0., var rVolUpHigh = 0., var rVolUpLow  = 0.

if rVolUpDown == 1
    rVolUpClose := close, rVolUpHigh := high, rVolUpLow := low

if rVolUpDown == -1
    rVolDnClose := close, rVolDnHigh := high, rVolDnLow := low

rVolAtr         = ta.atr(atrLen)
rVolDnAtr       = ATR(rVolDnHigh, rVolDnLow, rVolDnClose, atrLen)
rVolUpAtr       = ATR(rVolUpHigh, rVolUpLow, rVolUpClose, atrLen)

rVolSrc         = rVolUseAtrAsSrc ? rVolAtr   : close
rVolDnSrc       = rVolUseAtrAsSrc ? rVolDnAtr : low
rVolUpSrc       = rVolUseAtrAsSrc ? rVolUpAtr : high

srcMA           = Smoothers.SmootherType(rVolMaType, rVolSrc,   rVolMaLength, rVolMaFramaFast, rVolMaFramaSlow, rVolMaLinRegOffset, rVolMaJurikPhase, rVolMaJurikPower, rVolMaVwwmaStartingWeight, rVolMaVwwmaVolumeDefault, rVolMaCorrected)
rVolDnSrcMA     = Smoothers.SmootherType(rVolMaType, rVolDnSrc, rVolMaLength, rVolMaFramaFast, rVolMaFramaSlow, rVolMaLinRegOffset, rVolMaJurikPhase, rVolMaJurikPower, rVolMaVwwmaStartingWeight, rVolMaVwwmaVolumeDefault, rVolMaCorrected)
rVolUpSrcMA     = Smoothers.SmootherType(rVolMaType, rVolUpSrc, rVolMaLength, rVolMaFramaFast, rVolMaFramaSlow, rVolMaLinRegOffset, rVolMaJurikPhase, rVolMaJurikPower, rVolMaVwwmaStartingWeight, rVolMaVwwmaVolumeDefault, rVolMaCorrected)

rVolSrc        := useMA ? srcMA   : rVolSrc
rVolDnSrc      := useMA ? rVolDnSrcMA : rVolDnSrc
rVolUpSrc      := useMA ? rVolUpSrcMA : rVolUpSrc

rVolVol         = Volatility(rVolSrc,   atrLen)
rVolDnVol       = Volatility(rVolDnSrc, atrLen)
rVolUpVol       = Volatility(rVolUpSrc, atrLen)
rVolDnUpVol     = rVolUpVol - rVolDnVol

rVolDnVolRel    = rVolDnVol / rVolSrc
rVolUpVolRel    = rVolUpVol / rVolSrc
rVolDnUpVolRel  = rVolUpVolRel - rVolDnVolRel

plot(rVolShowDiff or rVolShowDiffRel ?    0 : na, color=color.new(color.gray,    50), title="Zero")

plot(rVolShowVolatility   ? rVolVol         : na, color=color.new(#00ff95,        0), title="Volatility")

plot(rVolShowUpDown       ? rVolDnVol       : na, color=color.new(color.orange,   0), title="Down")
plot(rVolShowUpDown       ? rVolUpVol       : na, color=color.new(color.blue,     0), title="Up")
plot(rVolShowDiff         ? rVolDnUpVol     : na, color=color.new(#af4c93,        0), title="Down/up")

plot(rVolShowUpDownRel    ? rVolDnVolRel    : na, color=color.new(color.orange,   0), title="Relative down")
plot(rVolShowUpDownRel    ? rVolUpVolRel    : na, color=color.new(color.blue,     0), title="Relative up")
plot(rVolShowDiffRel      ? rVolDnUpVolRel  : na, color=color.new(#e14da3,        0), title="Relative down/up")
