I don’t remember where I got this formula but if I am not mistaken it was translated from MT4 to Amibroker by a German programmer. I’ve tested with original JMA, and the results are the same/accurate (if I’m not mistaken) but there are drawbacks, maybe because the translation is not perfect, sometimes we got an error. For example, the error (Error 10. Array subscript out of range) sometimes appears when changing timeframe to monthly. Maybe someone can fix it?
Many thanks are for Jurik, to the original coder and anyone who can fix the error and share the fix.

//+——————————————————————+
//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”) ) ;
Leave a Reply
You must be logged in to post a comment.