Adaptive_Length
// 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 to calculate Adaptive dynamic length which can be used in Moving Averages and other indicators.

library("Adaptive_Length")

// @function             Adaptive dynamic length based on boolean parameter
// @param para           Boolean parameter; if true then length would decrease and would increase if its false
// @param adapt_Pct      Percentage adaption based on parameter
// @param minLength      Minimum allowable length
// @param maxLength      Maximum allowable length
// @returns              Adaptive Dynamic Length based on Boolean Parameter
export dynamic(bool para, float adapt_Pct, simple int minLength, simple int maxLength) =>
    var dyna_len = int(na)
    var float i_len = math.avg(minLength, maxLength)
    i_len := para ? math.max(minLength, i_len * adapt_Pct) : math.min(maxLength, i_len * (2-adapt_Pct))
    dyna_len := int(i_len)
    dyna_len

// @function             Adaptive dynamic length based on two boolean parameters for increasing and decreasing dynamic length seperatally with more precision
// @param up_para        Boolean parameter; if true then length would decrease
// @param dn_para        Boolean parameter; if true then length would increase
// @param adapt_Pct      Percentage adaption based on parameter
// @param minLength      Minimum allowable length
// @param maxLength      Maximum allowable length
// @returns              Adaptive Dynamic Length based on Two Boolean Parameters for increasing and decreasing dynamic length seperatally with more precision
export dynamic_2(bool up_para, bool dn_para, float adapt_Pct, simple int minLength, simple int maxLength) =>
    var _dyna_len = int(na)
    var float i_len = math.avg(minLength, maxLength)
    i_len := up_para and not dn_para ? math.max(minLength, i_len * adapt_Pct) :
         dn_para and not up_para ? math.min(maxLength, i_len * (2-adapt_Pct)) : nz(i_len[1])
    _dyna_len := int(i_len)
    _dyna_len

med(x,y,z) => (x+y+z) - math.min(x,math.min(y,z)) - math.max(x,math.max(y,z))

// @function             Adaptive length based automatic alpha calculations from source input
// @param src            Price source for alpha calculations 
// @param a              Input Alpha value
// @returns              Adaptive Length calculated from input price Source and Alpha
export auto_alpha(float src, float a)=>  
    float ip = 0.0
    s = (src + 2*src[1] + 2*src[2] + src[3])/6.0
    float c = 0.0
    var n = bar_index
    c := n<7?(src - 2*src[1] + src[2])/4.0:((1 - 0.5*a)*(1 - 0.5*a)*(s - 2*s[1] + s[2]) + 2*(1-a)*c[1] - (1 - a)*(1-a)*c[2])
    q1 = (.0962*c + 0.5769*c[2] - 0.5769*c[4] - .0962*c[6])*(0.5+.08*nz(ip[1]))
    I1 = c[3]
    dp_ = q1 != 0 and q1[1] != 0 ? (I1/q1 - I1[1]/q1[1]) / (1 + I1*I1[1]/(q1*q1[1])) : 0
    dp = dp_ < 0.1 ? 0.1 : dp_ > 1.1 ? 1.1 : dp_
    md = med(dp,dp[1], med(dp[2], dp[3], dp[4]))
    dc = md == 0 ? 15 : 6.28318 / md + 0.5
    ip := .33*dc + .67*nz(ip[1])
    int p = 0
    p := int(.15*ip + .85*nz(p[1]))
    p


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

/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////                           Plots                          //////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
src = input.source(hlc3, 'Source')
string grp1 = 'MA Parameters'
AadaptPerc = input.float(96.85, minval=0, maxval=100, title='MA Dynamic Adapting Percentage:', group=grp1) / 100.0
MA1_min_Length = input.int(20, title='MA 1 Minimum Length:', group=grp1, inline = 'ma1')
MA1_max_Length = input.int(50, title='MA 1 Maximum Length:', group=grp1, inline = 'ma1')
MA2_Length = input.int(50, title='MA 2 Length:', group=grp1)
alpha_val = input(.07, title="Alpha", group=grp1)
MA3_min_Length = input.int(50, title='MA 3 Minimum Length:', group=grp1, inline = 'ma3')
MA3_max_Length = input.int(200, title='MA 3 Maximum Length:', group=grp1, inline = 'ma3')

import MightyZinger/Chikou/2 as filter
[c_col, _trend] = filter.chikou(src, 50, 50, high, low, color.green, color.red, color.yellow)  
up_para = _trend == 1
dn_para = _trend == -1

dynamic_Length = dynamic(up_para , AadaptPerc , MA1_min_Length , MA1_max_Length)
auto_Length = auto_alpha(src, alpha_val)
dynamic_2_length = dynamic_2(up_para , dn_para, AadaptPerc , MA3_min_Length , MA3_max_Length)

_ema(src, length)=>     // EMA with Series Int Support
    var result = float(na)
    result := (src - nz(result[1])) * (2.0 / (length + 1)) + nz(result[1])
    result
    
ma1 = _ema(src, dynamic_Length)
ma2 = _ema(src, auto_Length)
ma3 = _ema(src, dynamic_2_length)

// MAs Plot

ma1_plot = plot(ma1, color= c_col , title="MA 1",  linewidth=4)
ma2_plot = plot(ma2, color= c_col , title="MA 2",  linewidth=2)
ma3_plot = plot(ma3, color= c_col , title="MA 3",  linewidth=2)

plotchar(dynamic_Length, 'Dynamic Length', '', location.top, color.new(color.green, 0))
plotchar(auto_Length, 'Auto Alpha Length', '', location.top, color.new(color.lime, 0))
plotchar(dynamic_2_length, 'Dynamic_2 Length', '', location.top, color.new(color.yellow, 0))

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