// Downloaded From https://www.WiseStockTrader.com
//+------------------------------------------------------------------+
//SetBarsRequired(ceil(20+80*(r1^0.36)));
//SetBarsRequired(200,0);
function IntPortion( Paramet )
{
    return IIf( Paramet > 0, floor( Paramet ), ceil( Paramet ) );
};

//+------------------------------------------------------------------+
function JJMA( Array, Length, Phase )
{
	//----buffers
    fC0Buffer = fC8Buffer = fA8Buffer = 0;
    JMAValueBuffer = Array;
    JMAValue = 0;
    loopCriteria = cycleDelta = cycleLimit = counterA = counterB = JMATempValue = 0;
	//+------------------------------------------------------------------+
	//|JMAinitFlagizationfunction|
	//+------------------------------------------------------------------+
    ring2 = 0;
    ring1 = 0;
    buffer = 0;
	//----initialpart
    limitValue = 63;
    startValue = 64;
	//----

    for( i = 0; i <= limitValue; i++ )
        list[i] = -1000000;

    for( i = startValue; i <= 127; i++ )
        list[i] = 1000000;

	//----
    initFlag = True;

    lengthParam = IIf( Length < 1.0000000002, 0.0000000001, ( Length - 1 ) / 2.0 );

	//----
    if( Phase < -100 )
        phaseParam = 0.5;
    else
        if( Phase > 100 )
            phaseParam = 2.5;
        else
            phaseParam = Phase / 100.0 + 1.5;

	//----
    logParam = log( sqrt( lengthParam ) ) / log( 2.0 );

	//----
    logParam = IIf( ( logParam + 2.0 ) < 0, 0, logParam + 2.0 );

	//----
    sqrtParam = sqrt( lengthParam ) * logParam;

    lengthParam = lengthParam * 0.9;

    lengthDivider = lengthParam / ( lengthParam + 2.0 );

	//----
	//+------------------------------------------------------------------+
	//|JMAiterationfunction|
	//+------------------------------------------------------------------+
	//----maincycle
    loopParam = 0;

    for( shift = 0; shift <= BarCount - 1; shift++ )
    {
        series = Array[shift];

        if( loopParam < 61 )
        {
            loopParam++;
            buffer[loopParam] = series;
        }

        if( loopParam > 30 )
        {
            if( initFlag )
            {
                initFlag = False;

                diffFlag = 0;

                for( i = 1; i <= 29; i++ )
                {
                    if( buffer[i + 1] != buffer[i] )
                        diffFlag = 1;
                }

                highLimit = diffFlag * 30;

                if( highLimit == 0 )
                    paramB = series;
                else
                    paramB = buffer[1];

                paramA = paramB;

                if( highLimit > 29 )
                    highLimit = 29;
            }
            else
                highLimit = 0;

			//----bigcycle
            for( i = highLimit; i >= 0; i-- )
            {
                if( i == 0 )
                    sValue = series;
                else
                    sValue = buffer[31 - i];

                if( abs( sValue - paramA ) > abs( sValue - paramB ) )
                    absValue = abs( sValue - paramA );
                else
                    absValue = abs( sValue - paramB );

                dValue = absValue + 0.0000000001; //1.0e-10;

                if( counterA <= 1 )
                    counterA = 127;
                else
                    counterA--;

                if( counterB <= 1 )
                    counterB = 10;
                else
                    counterB--;

                if( cycleLimit < 128 )
                    cycleLimit++;

                cycleDelta = cycleDelta + ( dValue - ring2[counterB] );

                ring2[counterB] = dValue;

                if( cycleLimit > 10 )
                    highDValue = cycleDelta / 10.0;
                else
                    highDValue = cycleDelta / cycleLimit;

                if( cycleLimit > 127 )
                {
                    dValue = ring1[counterA];
                    ring1[counterA] = highDValue;
                    s68 = 64;
                    s58 = s68;

                    while( s68 > 1 )
                    {
                        if( list[s58] < dValue )
                        {
                            s68 = s68 / 2.0;
                            s58 = s58 + s68;
                        }
                        else
                            if( list[s58] <= dValue )
                            {
                                s68 = 1;
                            }
                            else
                            {
                                s68 = s68 / 2.0;
                                s58 = s58 - s68;
                            }
                    }
                }
                else
                {
                    ring1[counterA] = highDValue;

                    if( ( limitValue + startValue ) > 127 )
                    {
                        startValue--;
                        s58 = startValue;
                    }
                    else
                    {
                        limitValue++;
                        s58 = limitValue;
                    }

                    if( limitValue > 96 )
                        s38 = 96;
                    else
                        s38 = limitValue;

                    if( startValue < 32 )
                        s40 = 32;
                    else
                        s40 = startValue;
                }

				//----
                s68 = 64;

                s60 = s68;

                while( s68 > 1 )
                {
                    if( list[s60] >= highDValue )
                    {
                        if( list[s60 - 1] <= highDValue )
                        {
                            s68 = 1;
                        }
                        else
                        {
                            s68 = s68 / 2.0;
                            s60 = s60 - s68;
                        }
                    }
                    else
                    {
                        s68 = s68 / 2.0;
                        s60 = s60 + s68;
                    }

                    if( ( s60 == 127 ) && ( highDValue > list[127] ) )
                        s60 = 128;
                }

                if( cycleLimit > 127 )
                {
                    if( s58 >= s60 )
                    {
                        if( ( ( s38 + 1 ) > s60 ) && ( ( s40 - 1 ) < s60 ) )
                            lowDValue = lowDValue + highDValue;
                        else
                            if( ( s40 > s60 ) && ( ( s40 - 1 ) < s58 ) )
                                lowDValue = lowDValue + list[s40 - 1];
                    }
                    else
                        if( s40 >= s60 )
                        {
                            if( ( ( s38 + 1 ) < s60 ) && ( ( s38 + 1 ) > s58 ) )
                                lowDValue = lowDValue + list[s38 + 1];
                        }
                        else
                            if( ( s38 + 2 ) > s60 )
                                lowDValue = lowDValue + highDValue;
                            else
                                if( ( ( s38 + 1 ) < s60 ) && ( ( s38 + 1 ) > s58 ) )
                                    lowDValue = lowDValue + list[s38 + 1];

                    if( s58 > s60 )
                    {
                        if( ( ( s40 - 1 ) < s58 ) && ( ( s38 + 1 ) > s58 ) )
                            lowDValue = lowDValue - list[s58];
                        else
                            if( ( s38 < s58 ) && ( ( s38 + 1 ) > s60 ) )
                                lowDValue = lowDValue - list[s38];
                    }
                    else
                    {
                        if( ( ( s38 + 1 ) > s58 ) && ( ( s40 - 1 ) < s58 ) )
                            lowDValue = lowDValue - list[s58];
                        else
                            if( ( s40 > s58 ) && ( s40 < s60 ) )
                                lowDValue = lowDValue - list[s40];
                    }
                }

                if( s58 <= s60 )
                {
                    if( s58 >= s60 )
                        list[s60] = highDValue;
                    else
                    {
                        for( j = s58 + 1; j <= ( s60 - 1 ); j++ )
                        {
                            list[j - 1] = list[j];
                        }

                        list[s60 - 1] = highDValue;
                    }
                }
                else
                {
                    for( j = s58 - 1; j >= s60; j-- )
                    {
                        list[j + 1] = list[j];
                    }

                    list[s60] = highDValue;
                }

                if( cycleLimit <= 127 )
                {
                    lowDValue = 0;

                    for( j = s40; j <= s38; j++ )
                    {
                        lowDValue = lowDValue + list[j];
                    }
                }

				//----
                if( ( loopCriteria + 1 ) > 31 )
                    loopCriteria = 31;
                else
                    loopCriteria++;

                JMATempValue = sqrtDivider = sqrtParam / ( sqrtParam + 1.0 );

                if( loopCriteria <= 30 )
                {
                    if( sValue - paramA > 0 )
                        paramA = sValue;
                    else
                        paramA = sValue - ( sValue - paramA ) * sqrtDivider;

                    if( sValue - paramB < 0 )
                        paramB = sValue;
                    else
                        paramB = sValue - ( sValue - paramB ) * sqrtDivider;

                    JMATempValue = series;

                    if( loopCriteria == 30 )
                    {
                        fC0Buffer[shift] = series;

                        if( ceil( sqrtParam ) >= 1 )
                            intPart = ceil( sqrtParam );
                        else
                            intPart = 1;

                        leftInt = IntPortion( intPart );

                        if( floor( sqrtParam ) >= 1 )
                            intPart = floor( sqrtParam );
                        else
                            intPart = 1;

                        rightPart = IntPortion( intPart );

                        if( leftInt == rightPart )
                            dValue = 1.0;
                        else
                            dValue = ( sqrtParam - rightPart ) / ( leftInt - rightPart );

                        if( rightPart <= 29 )
                            upShift = rightPart;
                        else
                            upShift = 29;

                        if( leftInt <= 29 )
                            dnShift = leftInt;
                        else
                            dnShift = 29;

                        fA8Buffer[shift] = ( series - buffer[loopParam - upShift] ) * ( 1 - dValue ) / rightPart + ( series - buffer[loopParam - dnShift] ) * dValue / leftInt;
                    }
                }
                else
                {

                    dValue = lowDValue / ( s38 - s40 + 1 );

                    if( 0.5 <= logParam - 2.0 )
                        powerValue = logParam - 2.0;
                    else
                        powerValue = 0.5;

                    if( logParam >= ( absValue / dValue )^powerValue )
                        dValue = ( absValue / dValue )^powerValue;
                    else
                        dValue = logParam;

                    if( dValue < 1 )
                        dValue = 1;

                    powerValue = sqrtDivider ^ ( sqrt( dValue ) );

                    if( sValue - paramA > 0 )
                        paramA = sValue;
                    else
                        paramA = sValue - ( sValue - paramA ) * powerValue;

                    if( sValue - paramB < 0 )
                        paramB = sValue;
                    else
                        paramB = sValue - ( sValue - paramB ) * powerValue;
                }
            }

			//----endofbigcycle
            if( loopCriteria > 30 )
            {
                JMATempValue = JMAValueBuffer[shift - 1];
                powerValue = lengthDivider ^ dValue;
                squareValue = powerValue ^ 2;

                fC0Buffer[shift] = ( 1 - powerValue ) * series + powerValue * fC0Buffer[shift - 1];
                fC8Buffer[shift] = ( series - fC0Buffer[shift] ) * ( 1 - lengthDivider ) + lengthDivider * fC8Buffer[shift - 1];

                fA8Buffer[shift] = ( phaseParam * fC8Buffer[shift] + fC0Buffer[shift] - JMATempValue ) *
                                   ( powerValue * ( -2.0 ) + squareValue + 1 ) + squareValue * fA8Buffer[shift - 1];
                JMATempValue = JMATempValue + fA8Buffer[shift];
            }

            JMAValue = JMATempValue;
        }

        if( loopParam <= 30 )
            JMAValue = C[BarCount - 1];

        JMAValueBuffer[shift] = JMAValue;
		//----Endofmaincycle
    }

    return JMAValueBuffer;
}

P = ParamField( "Price field", -1 );
Periods = Param( "Periods", 15, 2, 300, 1, 10 );
phase = Param( "Phase", 0, -100, 100, 1, 1 );
SetBarsRequired( ceil( 20 + 80 * ( Periods ^ 0.36 ) ) );
Plot( JJMA( P, Periods, phase ), "JurikJMA", ParamColor( "Color", colorCycle ), ParamStyle( "Style" ) );