Ehlers’ Reflex: A New Zero-Lag Indicator

In the latest February 2020 Stocks & Commodities Magazine John Ehlers
presents two new interesting indicators the Reflex and TrendReflex.

http://technical.traders.com/content/TTlink.asp?mo=02&yr=2020

I would like to translate his Tradestation EasyLanguage code to AFL and I'm
having some difficulties with the looping. The Ehlers' Super Smoother filter
that he uses to smooth price data for the indicator has been previously
coded by Tomasz Janeczko and published in the January 2014
edition of Stocks & Commodities Magazine

http://technical.traders.com/content/TTlink.asp?mo=01&yr=2014

Here is Ehlers' Tradestation EasyLanguage code for the new
indicators and Tomasz' code for the SuperSmoother function:

{
Reflex Indicator
(C) 2019 John F. Ehlers
}
Inputs:
Length(20);
Vars:
Slope(0),
sum(0),
count(0),
a1(0), b1(0), c1(0), c2(0), c3(0), Filt(0),
MS(0),
Reflex(0);
//Gently smooth the data in a SuperSmoother
a1 = expvalue(-1.414*3.14159 / (.5*Length));
b1 = 2*a1*Cosine(1.414*180 / (.5*Length));
c2 = b1;
c3 = -a1*a1;
c1 = 1 - c2 - c3;
Filt = c1*(Close + Close[1]) / 2 + c2*Filt[1] + c3*Filt[2];
//Length is assumed cycle period
Slope = (Filt[Length] - Filt) / Length;
//Sum the differences
Sum = 0;
For count = 1 to Length Begin
Sum = Sum + (Filt + count*Slope) - Filt[count];
End;
Sum = Sum / Length;
//Normalize in terms of Standard Deviations
MS = .04*Sum*Sum + .96*MS[1];
If MS <> 0 Then Reflex = Sum / SquareRoot(MS);
Plot1(Reflex);
Plot2(0);
{
Trendflex Indicator
(C) 2019 John F. Ehlers
}
Inputs:
Length(20);
Vars:
sum(0),
count(0),
a1(0), b1(0), c1(0), c2(0), c3(0), Filt(0),
MS(0),
Trendflex(0);
//Gently smooth the data in a SuperSmoother
a1 = expvalue(-1.414*3.14159 / (.5*Length));
b1 = 2*a1*Cosine(1.414*180 / (.5*Length));
c2 = b1;
c3 = -a1*a1;
c1 = 1 - c2 - c3;
Filt = c1*(Close + Close[1]) / 2 + c2*Filt[1] + c3*Filt[2];
//Sum the differences
Sum = 0;
For count = 1 to Length Begin
Sum = Sum + Filt - Filt[count];
End;
Sum = Sum / Length;
//Normalize in terms of Standard Deviations
MS = .04*Sum*Sum + .96*MS[1];
If MS <> 0 Then Trendflex = Sum / SquareRoot(MS);
Plot1(Trendflex);
Plot2(0);
PI = 3.1415926; 
SQ2 = sqrt( 2 ); 

function SuperSmoother( array, periods ) 
{ 
    a1 = exp( -SQ2 * PI / periods ); 
    b1 = 2 * a1 * cos( SQ2 * PI / periods ); 
    c2 = b1; 
    c3 = -a1 * a1; 
    c1 = 1 - c2 - c3; 

    Filt = Nz( array ); 

    for ( i = 2; i < BarCount; i++ ) 
    { 
         Filt[ i ] = c1 * ( array[ i ] + array[ i - 1 ] ) / 2 + 
                     c2 * Filt[ i - 1 ] + 
                     c3 * Filt[ i - 2]; 
    } 

    return Filt; 
} 
1 Like

There isn't loop required for Super Smoother.
In manual Tomasz Janeczko posted loopless version using IIR array function.

/// IIR SuperSmoother code from AmiBroker help
/// @link https://www.amibroker.com/guide/afl/iir.html
/// Copyright AmiBroker.com
Periods = 10;  
c1 = 1.41421 * 3.14159 / Periods;  
c2 = 2.71828^-c1;  
a1 = 2 * c2 * cos( c1 );  
a2 = -c2^2;  
b0 = (1 - a1 - a2)/2;  b1 = b0;  
x = IIR( Close, b0, a1, b1, a2 ); 
Plot( x, "Super Smoother", colorRed );

That Slope variable of TS code does not need loop too.
Slope = (Ref(x, -periods) - x) / periods;

MA function is here
https://www.amibroker.com/guide/afl/ma.html

Or in case you need sum then function is here
https://www.amibroker.com/guide/afl/sum.html

MS variable of TS code is just AMA. So does not need loop too.
Ama and Ama2 are here
https://www.amibroker.com/guide/afl/ama.html
https://www.amibroker.com/guide/afl/ama2.html

On quick look it might be that loop might be required only for creating sum of first TS code.
Try yourself first. Then come back if you get stuck.

5 Likes

Thanks for the suggestions and leads fxshrat, your help is much appreciated.
Here's what I have so far for the Reflex Indicator but my sum loop lines are incorrect and not working yet.

Length = param("Reflex Length",20,2,200,1); 

c1 = 1.41421 * 3.14159 / Length;  
c2 = 2.71828^-c1;  
a1 = 2 * c2 * cos( c1 );  
a2 = -c2^2;  
b0 = (1 - a1 - a2)/2;  b1 = b0;  
Filt = IIR( Close, b0, a1, b1, a2 );

Slope = (Ref(Filt, -Length) - Filt) / Length;

RSum = 0;

for ( i = 1; i < Length; i++ ) 
    { 
       RSum = RSum + (Filt + i * Slope) - Filt [ i ] ;                 
    } 

RSum = RSum / Length;

MS = AMA2(RSum,.04,.96);

Reflex = RSum / sqrt(MS); // Need to add MS <> 0 condition to this line//

Plot(RSum, "Reflex", colorlightorange,stylethick );

PlotGrid( 0, colorwhite, 8, 2 );

Also I'm not sure how to translate the following EasyLanguage line to AFL:

If MS <> 0 Then Reflex = Sum / SquareRoot(MS);

Would that be an IIf condition that passes value when MS <> 0 and null if MS is 0 such as the following?

Reflex = IIf(MS < 0 OR MS > 0, RSum/sqrt(MS),Null)

First of all, I have posted SuperSmoother code from AB manual with added credit to AFL creator who's Tomasz Janeczko of AmiBroker. So I don't understand why you did remove that(?) Just because you change variable names it does not make it different algorithm. Did you come up with algorithm or has it been someone else? AFAICS you were asking for help on how to do it so far. You can remove credit if it is you who came up with something.


Your loop is incorrect. AB 1-dim arrays have size BarCount so it does not make sense to use subscript the way your did.
https://www.amibroker.com/guide/h_understandafl.html

Also SuperSmoother period is incorrect.
Take a look at EL code again. It is -> 0.5*Length.

/// Trendflex, Reflex Indicators
/// (C) 2019 John F. Ehlers
/// @link http://technical.traders.com/content/TTlink.asp?mo=02&yr=2020
///
periods = 20; 
/// IIR SuperSmoother code from AB manual ////////////////
/// @link https://www.amibroker.com/guide/afl/iir.html
/// Copyright AmiBroker.com
sm_period = 0.5*periods;
c1 = 1.41421 * 3.14159 / sm_period;  
c2 = 2.71828^-c1;  
a1 = 2 * c2 * cos( c1 );  
a2 = -c2^2;  
b0 = (1 - a1 - a2)/2;  
b1 = b0;  
sm = IIR( Close, b0, a1, b1, a2 ); 
//Plot( sm, "Super Smoother", colorRed );
/// End of Super Smoother ////////////////////////////////
///
/// Trendflex, Reflex
/// @link https://forum.amibroker.com/t/ehlers-reflex-a-new-zero-lag-indicator/16773/5
/// AFL code by fxshrat@gmail.com
slope = (Ref(sm,-periods)-sm) / periods;
cs = 0;
for ( i = 0; i < periods; i++ ) 
	cs += (i+1)*slope-Ref(sm, -i); 
ma1 = sm-MA(sm,periods);// for Trendflex
ma2 = sm+cs/periods;// for Reflex
///
smoothfactor = 0.04;
MS1 = AMA(ma1*ma1, smoothfactor);
MS2 = AMA(ma2*ma2, smoothfactor);
/// Trendflex 
Trendflex = ValueWhen(MS1 > 0, ma1/sqrt(MS1));
Plot( Trendflex, "Trendflex", colorRed );
/// Reflex
Reflex = ValueWhen(MS2 > 0, ma2/sqrt(MS2));
Plot( Reflex, "Reflex", colorOrange );
PlotGrid(0, colorYellow, 1, 1, True);

9

5 Likes

Thank you!! Please forgive my naivety, I thought original authorship was already established in the thread and certainly didn't mean to change credits or claim anything as my own. In future will always include authorship credits in each code work in progress iteration in the thread. Thanks for illustrating the proper looping and valuewhen conditions, trying to learn.

1 Like

OK, thank you.


Here is code improvement removing any loop completely.

This one:

slope = (Ref(sm,-periods)-sm) / periods;
cs = 0;
for ( i = 0; i < periods; i++ ) 
	cs += (i+1)*slope-Ref(sm, -i); 
ma1 = sm-MA(sm,periods);// for Trendflex
ma2 = sm+cs/periods;// for Reflex

can be shortened to this loopless version:

slope = (Ref(sm,-periods)-sm) / periods;
gauss_sum = periods/2*(1+periods);// Gauss sum of consec. numbers
ma1 = sm-MA(sm,periods);//for Trendflex 
ma2 = ma1+gauss_sum/periods*slope;//for Reflex

Updated full code:

/// Super Smoother, Trendflex, Reflex Indicators
/// (C) 2019 John F. Ehlers
/// @link http://technical.traders.com/content/TTlink.asp?mo=02&yr=2020
///
periods = 20; 
/// IIR SuperSmoother code from AB manual ////////////////
/// @link https://www.amibroker.com/guide/afl/iir.html
/// Copyright AmiBroker.com
sm_period = 0.5*periods;
c1 = 1.41421 * 3.14159 / sm_period;  
c2 = 2.71828^-c1;  
a1 = 2 * c2 * cos( c1 );  
a2 = -c2^2;  
b0 = (1 - a1 - a2)/2;  
b1 = b0;  
sm = IIR( Close, b0, a1, b1, a2 ); 
//Plot( sm, "Super Smoother", colorRed );
/// End of Super Smoother ////////////////////////////////
///
/// Trendflex, Reflex
/// @link https://forum.amibroker.com/t/ehlers-reflex-a-new-zero-lag-indicator/16773/7
/// AFL code by fxshrat@gmail.com
slope = (Ref(sm,-periods)-sm) / periods;
gauss_sum = periods/2*(1+periods);// C.Gauss sum of consecutive numbers
ma1 = sm-MA(sm,periods);//for Trendflex 
ma2 = ma1+gauss_sum/periods*slope;//for Reflex
///
smoothfactor = 0.04;
MS1 = AMA(ma1*ma1, smoothfactor);
MS2 = AMA(ma2*ma2, smoothfactor);
/// Trendflex 
Trendflex = ValueWhen(MS1 > 0, ma1/sqrt(MS1));
Plot( Trendflex, "Trendflex", colorRed );
/// Reflex
Reflex = ValueWhen(MS2 > 0, ma2/sqrt(MS2));
Plot( Reflex, "Reflex", colorOrange );
PlotGrid(0, colorYellow, 1, 1, True);
13 Likes

Thank you @fxshrat for posting this code.
I am a subscriber to S&C magazine and I use published code a a learning tool to improve my AFL skills.

In the article John Ehlers describes Reflex and TrendFlex indicators but, does not say much how to use them. I can see that TrendFlex(20) above zero indicates uptrend but, SuperSmoother(40) gives the same result. I am not sure how to interpret Refex plot line as it seems to oscillate above and below zero in the up trend phase.

Capture

What do you think is the best use for this indicator?

Kind Regards
Richard

2 Likes

Thanks for sharing the code. Request you to post/guideleins how to use this indicators for profitable trading & investment.