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

//@version=5

// @description This library function returns a moving average.
library("TypeMovingAverages",overlay=false)

// @function TODO: add function description here
// @returns TODO: MAType

//****************************************************************************//
//offset=input(title="Alma Offset (only for ALMA)",defval=0.85, step=0.05)
offset = 0.85
//volatility_lookback =input(title="Volatility lookback (only for VAMA)",defval=12)
volatility_lookback = 13
//i_fastAlpha = input(1.25,"KAMA's alpha (only for KAMA)", minval=1,step=0.25)
i_fastAlpha = 1.30
fastAlpha = 2.0 / (i_fastAlpha + 1)
slowAlpha = 2.0 / 31



export MA_selector(float src, simple int length, string ma_select, simple int xsmooth) =>
    ma = 0.0
    if ma_select == 'SMA'
        ma := ta.sma(ta.sma(src, length), xsmooth)
        ma

    if ma_select == 'EMA'
        ma := ta.ema(ta.ema(src, length), xsmooth)
        ma

    if ma_select == 'WMA'
        ma := ta.wma(ta.wma(src, length), xsmooth)
        ma
    if ma_select == 'HMA'
        ma := ta.hma(ta.hma(src, length), xsmooth)
        ma
    if ma_select == 'JMA'
        beta = 0.45 * (length - 1) / (0.45 * (length - 1) + 2)
        alpha = beta
        tmp0 = 0.0
        tmp1 = 0.0
        tmp2 = 0.0
        tmp3 = 0.0
        tmp4 = 0.0
        tmp0 := (1 - alpha) * src + alpha * nz(tmp0[1])
        tmp1 := (src - tmp0[0]) * (1 - beta) + beta * nz(tmp1[1])
        tmp2 := tmp0[0] + tmp1[0]
        tmp3 := (tmp2[0] - nz(tmp4[1])) * (1 - alpha) * (1 - alpha) + alpha * alpha * nz(tmp3[1])
        tmp4 := nz(tmp4[1]) + tmp3[0]
        ma := tmp4
        ma
    if ma_select == 'KAMA'
        momentum = math.abs(ta.change(src, length))
        volatility = math.sum(math.abs(ta.change(src)), length)
        efficiencyRatio = volatility != 0 ? momentum / volatility : 0
        smoothingConstant = math.pow(efficiencyRatio * (fastAlpha - slowAlpha) + slowAlpha, 2)
        var kama = 0.0
        kama := nz(kama[1], src) + smoothingConstant * (src - nz(kama[1], src))
        ma := kama
        ma
    if ma_select == 'TMA'
        ma := ta.sma(ta.sma(ta.sma(src, math.ceil(length / 2)), math.floor(length / 2) + 1), xsmooth)
        ma

    if ma_select == 'VMA'
        valpha = 2 / (length + 1)
        vud1 = src > src[1] ? src - src[1] : 0
        vdd1 = src < src[1] ? src[1] - src : 0
        vUD = math.sum(vud1, 9)
        vDD = math.sum(vdd1, 9)
        vCMO = nz((vUD - vDD) / (vUD + vDD))
        VAR = 0.0
        VAR := nz(valpha * math.abs(vCMO) * src) + (1 - valpha * math.abs(vCMO)) * nz(VAR[1])
        ma := VAR
        ma

    if ma_select == 'WWMA'
        wwalpha = 1 / length
        WWMA = 0.0
        WWMA := wwalpha * src + (1 - wwalpha) * nz(WWMA[1])
        ma := WWMA
        ma

    if ma_select == 'EMA_NO_LAG'
        EMA1 = ta.ema(ta.ema(src, length), xsmooth)
        EMA2 = ta.ema(ta.ema(EMA1, length), xsmooth)
        Difference = EMA1 - EMA2
        ma := EMA1 + Difference
        ma

    if ma_select == 'TSF'
        lrc = ta.linreg(src, length, 0)
        lrc1 = ta.linreg(src, length, 1)
        lrs = lrc - lrc1
        TSF = ta.linreg(src, length, 0) + lrs
        ma := TSF
        ma

    if ma_select == 'VAMA'  // Volatility Adjusted from @fractured
        mid = ta.ema(ta.ema(src, length), xsmooth)
        dev = src - mid
        vol_up = ta.highest(dev, volatility_lookback)
        vol_down = ta.lowest(dev, volatility_lookback)
        ma := mid + math.avg(vol_up, vol_down)
        ma
    if ma_select == 'SMMA'
        smma = float(0.0)
        smaval = ta.sma(ta.sma(src, length), xsmooth)
        smma := na(smma[1]) ? smaval : (smma[1] * (length - 1) + src) / length
        ma := smma
        ma

    if ma_select == 'DEMA'
        e1 = ta.ema(ta.ema(src, length), xsmooth)
        e2 = ta.ema(ta.ema(e1, length), xsmooth)
        ma := 2 * e1 - e2
        ma
    if ma_select == 'ALMA'
        ma := ta.alma(src, length, offset, 6)
        ma
    ma


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

// //@version=5
// indicator("Test MATYPE", overlay=true)
// import hapharmonic/TypeMovingAverages/3 as MAType

// xprd1 = input(title='   💉Fast EMA period', defval=12)
// ma_select1 = input.string(title='   ⚖️Fast moving average Type', defval='EMA', options=['SMA', 'EMA', 'WMA', 'HMA', 'JMA', 'KAMA', 'TMA', 'VAMA', 'SMMA', 'DEMA', 'VMA', 'WWMA', 'EMA_NO_LAG', 'TSF', 'ALMA'])

// xprd2 = input(title='   💉Fast EMA period', defval=26)
// ma_select2 = input.string(title='   ⚖️Fast moving average Type', defval='EMA', options=['SMA', 'EMA', 'WMA', 'HMA', 'JMA', 'KAMA', 'TMA', 'VAMA', 'SMMA', 'DEMA', 'VMA', 'WWMA', 'EMA_NO_LAG', 'TSF', 'ALMA'])
// xsmooth = input.int(title='🏄‍♂️Smoothing period (1 = no smoothing)', minval=1, defval=1)

// ma_fast = MAType.MA_selector(close, xprd1, ma_select1,xsmooth)
// ma_slow = MAType.MA_selector(close, xprd2, ma_select2,xsmooth)

// plot(ma_fast, "INDICATOR",color.green) 
// plot(ma_slow, "INDICATOR",color.red) 
// ///////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////
