# Correlation Trend Indicator (TASC May 2020)

``````/*
Correlation Trend Indicator
(c) 2013-2019 John F. Ehlers

translated to Amibroker by J. Talikka
*/

Length = Param( "Length", 20, 1, 100 );

Plot( Correlation( C, BarIndex(), Length ), "Correlation Trend Indicator", colorRed, styleLine );
Plot( 0, "", colorBlue, styleLine );
``````

hmm... this indicator ended up being a one liner really.

1 Like

@jani I don't think that is exactly correct. In the text of the article author Ehlers briefly mentions that the indicator is "the Spearman correlation of closing prices against a straight line with a positive slope". I am not enough of a statistician to dissect the difference between the Pearson Product Moment correlation vs Spearman but it's out there on the internet for those inclined to do so.

AmiBroker's built in function looks like the Pearson version to me.

``````function Correl( x, y, number )
{
nom= MA( x * y, number ) - MA( x, number ) * MA( y, number );
denom = sqrt( MA( x ^ 2, number ) - MA( x, number ) ^ 2 ) *
sqrt( MA( y ^ 2, number ) - MA( y, number ) ^ 2 );
return nom/denom;
}

``````

The Spearman Rank Correlation was better discussed in the TASC February 2011 issue by Dan Valcu who also coded his version in AmiBroker's own afl language (within the article itself). I tried plotting your simple correlation indicator against the Spearman and although the values are very similar (and not significantly different on a quick look) I am uncertain if they are exactly what Ehler's intended.

Overall it's a pretty disappointing article considering how unoriginal the idea is and that makes several months in a row with uninspired articles for the "Traders Tips" section.

FWIW another AmiBroker user (Steve Walsh) has posted a different version of the Spearman Rank Correlation in the user library.

http://www.amibroker.com/members/library/detail.php?id=1500

Nice job Steve!

3 Likes Well, that might be, but the code attached to the article and in the Traders Tips section produces an identical result to the code I posted before. Here's a line by line calculation mirroring John Ehlers' easylanguage code from the article:

``````/*
Correlation Trend Indicator
(c) 2013-2019 John F. Ehlers

translated to Amibroker by J. Talikka
*/

Length = Param( "Length", 20, 1, 100 );

Plot( Correlation( C, BarIndex(), Length ), "Correlation Trend Indicator", colorBlack, styleDashed );
Plot( 0, "", colorBlue, styleLine );

/*
Sx = 0;
Sy = 0;
Sxx = 0;
Sxy = 0;
Syy = 0;
For count = 0 to Length - 1 Begin
X = Close[count];
Y = -count;
Sx = Sx + X;
Sy = Sy + Y;
Sxx = Sxx + X*X;
Sxy = Sxy + X*Y;
Syy = Syy + Y*Y;
End;
If (Length*Sxx - Sx*Sx > 0) and (Length*Syy - Sy*Sy > 0)
Then Corr = (Length*Sxy - Sx*Sy) / SquareRoot((Length*Sxx -
Sx*Sx)*(Length*Syy - Sy*Sy));
*/

Sx = Sy = Sxx = Sxy = Syy = 0;

for( count = 0; count < Length; count++ )
{
X = Ref( Close, -count );
Y = -count;
Sx = Sx + X;
Sy = Sy + Y;
Sxx = Sxx + X * X;
Sxy = Sxy + X * Y;
Syy = Syy + Y * Y;
}

Num = Length * Sxy - Sx * Sy;

Denom = sqrt( ( Length * Sxx - Sx * Sx ) * ( Length * Syy - Sy * Sy ) );

Corr = IIf( Denom != 0, Num / Denom, Null );

Plot( Corr, "maths from article Correlation Trend Indicator", colorRed, styleThick );

``````
4 Likes

Well done @jani and I doubt for the purpose of quantifying stock trends that it will make a difference. But there are data sets that will result in different results for the Pearson vs Spearman correlation. I am not a statistician so I can't tell you which measure is more appropriate for which data.

You can find some significant differences as discussed in this paper comparing the two.

Even in stock data I can find differences if I alter the "periods" to a shorter interval. Thanks for sharing your work with the forum.

For what it is worth, AmiBroker internal Correl function can not be accurately implemented the way shown in post #2. Mathematically the formula is correct but suffers from numerical problems when arguments have large magnitude but differences are very small.
To address that AmiBroker internal implementation uses double precision and some techniques to make sure that results are precise.

1 Like

Thank you @jani
Amibroker version of any S&C code is always the shortest and simplest application from all the published solutions. I was looking at EasyLanguage code and I was thinking - AFL code needs be shorter and simpler than that. You have proven that this is the case. Thanks again.

Regards
Richard

Hello,

John Ehlers just published (in S&C June 2020 issue) another article where he is using last month Trend Correlation Indicator to define new Cycle Mode and Trend Mode indicator.
Has anyone had a chance to look at this?

Tomasz no longer publishes AFL code to support S&C feature articles.
I made an attempt to convert EasyLanguage article code but, Angle = Cycle Mode indicator plot does not look the same as published in the article example.

``````//AFL code (converted from Easy language by @jani - Same/similar to Spearman indicator published in S&C 02 2011)

Sx = Sy = Sxx = Sxy = Syy = 0;
Length2 = Param( "Length2", 40, 1, 100 );

for( count = 0; count < Length2; count++ )
{
X = Ref( Close, -count );
Y = -count;
Sx = Sx + X;
Sy = Sy + Y;
Sxx = Sxx + X * X;
Sxy = Sxy + X * Y;
Syy = Syy + Y * Y;
}

Num = Length2 * Sxy - Sx * Sy;
Denom = sqrt( ( Length2 * Sxx - Sx * Sx ) * ( Length2 * Syy - Sy * Sy ) );
Corr2 = IIf( Denom != 0, Num / Denom, Null );
//Plot( Corr2, "Correlation maths from article Correlation Trend Indicator", colorRed, styleThick );

//Cycle mode - compute the angle as an arctangent function and resolve ambiguity
//EasyLanguage code = If ( Corr != 0 )  Angle = 90 + Atan( C / Corr); If ( Corr > 0 ) Then Angle = Angle - 180;
Angle = 0;
Angle = IIf( Corr2 != 0, 90 + Atan( Num / Corr2), IIf( Corr2 > 0, Angle - 180, 0) );
//Do not allow the rate change of angle to go negative
//EasyLanguage Code = If ( Ref(Angle, -1) - Angle < 270 and Angle < Ref(Angle, -1) )  Angle = Ref(Angle, -1);
Angle = IIf( (Ref(Angle, -1) - Angle) < 270 AND Angle < Ref(Angle, -1), Angle = Ref(Angle, -1), Angle);
Plot(Angle, "Cycle mode (Angle)", colorBlue, styleThick);
PlotGrid(0, colorBlue, 1, 2);
``````

Regards
Richard

@richpach
First of all a replacement of the original loop: please don't use loops ``````function CTI(array, length)
{
Sx = Sum(array, length);
Sxx = Sum(array^2, length);
a = length^2*(length+1);

Num = a * (WMA(array, length) - Sx/length);   //FIR
Denom = sqrt ( (Sxx*length - Sx^2) * a*(length-1) / 3 ) + 1e-9;

return Num/Denom;
}
``````

``````//Cycle mode - compute the angle as an arctangent function and resolve ambiguity
//EasyLanguage code = If ( Corr != 0 )  Angle = 90 + Atan( C / Corr); If ( Corr > 0 ) Then Angle = Angle - 180;
Angle = Nz((Imag != 0) * Atan( Real / (Imag +1e-9)) -90*sign(Imag));
//Do not allow the rate change of angle to go negative
//EasyLanguage Code = If ( Ref(Angle, -1) - Angle < 270 and Angle < Ref(Angle, -1) )  Angle = Ref(Angle, -1);
b = Ref(Angle, -1) - Angle;
Angle += b * (b < 270 AND b > 0);
``````

Note that I've changed your Num and Corr2.
I think this line was wrong too:

``````Angle = IIf( (Ref(Angle, -1) - Angle) < 270 AND Angle < Ref(Angle, -1), Angle = Ref(Angle, -1), Angle);
``````

You need to adjust my upper code (the Y in the EL-Code and additionally the last lines) and compute the "CTI" twice for Real and Imag.
Then you hopefully should get your desired result.

1 Like

getting error "variable Imag used without having been initialized

Sure. That was my goal.
As mentioned, you need to adjust the Y (see EL-code from the link) and calculate the "CTI" twice.
I've just posted a better CTI and some hints (one should now see, how to code this without loops).
I want to see more effort... he just copied the (loop-)CTI from @jani (it seems that he didn't recognized that he needs to adjust it slightly).

Here is a better CTI-Version (e.g. without original hints) :

``````function CTI(array, length)
{
Num = FIR(array, Cum(2) - length - 1, length);
Denom = length * Stdev(array, length) * sqrt( (length^2 - 1) / 3) + 1e-9;
return Num/Denom;
}
``````
1 Like

Hello @euroundusd

I am sorry for the late reply. I am a little slow "digesting" AFL code but, I appreciate your feedback and hints.
I need a bit more time to dissect this information. I am sure, the old brain can work it out now.
I started from wrong assumption. I thought, I could use previous month CTI code and define tangent (Angle) to create Ehlers "Cycle Mode" indicator.

Thanks again for your input. I had no idea that you can use FIR (Finite Impulse Response filter) to define Ehlers CTI.

Kind Regards
Richard

Hello Mr richpach,
Ich fond the varables Imag and Real not initialized and where is given a content for this variables?. In Ehlers code "Real = (Length * Sxy -----" and " Image = ....."

Hello @Selbsiebzig

Real = ( Length * Sxy - Sx * Sy ) / SquareRoot( ( Length * Sxx - Sx * Sx ) * ( Length * Syy - Sy * Sy ) ) ;

Imag = ( Length * Sxy - Sx * Sy ) / SquareRoot( ( Length * Sxx - Sx * Sx ) * ( Length * Syy - Sy * Sy ) ) ;

They look the same in definition but, the "Y" value is different.
Y = Cosine( 360 * ( Count - 1 ) / Period ) ; - for Real
and
Y = -Sine( 360 * ( count - 1 ) / Period ) ; - for Imag

I still have not had time to look into this - next week looks little bit less busy than this one.
I hope this helps. I am not an expert in AFL but, I am learning and improving slowly.
I was going to try CTI function which @euroundusd posted to compute these values.

Regards
Richard

1 Like

I program reasonable well in Powerlanguage from Multicharts and Tradebasic a derivative of the BASIC language.
I also understand the trading methods - momentum, breakouts, mean reversion and have been successfully trading for 20 years.
Amibroker has fascinated me because of its capabilities although I never could program it properly.
I am using the correlation indicator given by Ehlers in S&C June 2020 issue, after modifying it into a strategy. I find it has positive expectations with only one variable.
I am not a maths guy. I tried to program the correlation indicator in Amibroker, after going through the code shared here and in trading view. This is my effort:

``````Sx = Sy = Sxx = Sxy = Syy = 0;
PIx2 = 6.28318530718;

for( count = 0; count < Length; count++ )
{
X = Ref( Close, count-1 );
// the next two line are supposed to be a replacement for
// Y = Cosine( 360 * ( Count - 1 ) / Period ) ;
temp = PIx2 * (count - 1) / period;
y = cos(temp);
Sx = Sx + X;
Sy = Sy + Y;
Sxx = Sxx + X * X;
Sxy = Sxy + X * Y;
Syy = Syy + Y * Y;
}

Num = Length * Sxy - Sx * Sy;

Denom = sqrt( ( Length * Sxx - Sx * Sx ) * ( Length * Syy - Sy * Sy ) );

Real = IIf( Denom != 0, Num / Denom, Null );

Plot( Real, "SCJune20", colorRed, styleThick );
``````

While there is a plot, the values are different from powereditor and tradebasic.
Just sharing my efforts with you.
Cheers.

While copy - paste, missed the first line:
Period = 54;
length = Period;

You are looking into the "future" because your `Ref()` period is positive (mostly):

You have to add minus sign to look backwards as shown in `Ref()` documentation.

a negative period references "n" periods ago.

http://www.amibroker.com/guide/afl/ref.html

@fxshrat, so many thanks to you. I now have the S&C June 2020 Ehlers correlation code, perfectly matching with the code in the trading tips section (and with Multicharts). Here is the code:

``````// june 2020 ehlers corelation
// matches with the code in the magazine

Period = 54;
Length = Period;

Sx = Sy = Sxx = Sxy = Syy = 0;
PIx2 = 6.28318530718;

for( count = 1; count <= Length; count++ )
{
X = Ref( Close, -(count-1));
// the next two line are supposed to be a replacement for
// Y = Cosine( 360 * ( Count - 1 ) / Period ) ;
temp = PIx2 * (count - 1) / period;
y = cos(temp);
Sx = Sx + X;
Sy = Sy + Y;
Sxx = Sxx + X * X;
Sxy = Sxy + X * Y;
Syy = Syy + Y * Y;
}

Num = Length * Sxy - Sx * Sy;

Denom = sqrt( ( Length * Sxx - Sx * Sx ) * ( Length * Syy - Sy * Sy ) );

Real = IIf( Denom != 0, Num / Denom, Null );

Plot( Real, "SCJune20", colorRed, styleThick );

``````
2 Likes