Re: Ehlers Indicators for MT4

595
loxx wrote: Fri Sep 02, 2022 10:20 pm Alright, guys, here's a big one that needs to be created for MT4. This has never been released and is from Ehlers himself. We can't get this to work in PineScript, but I'm sure you can get it to work for MT$. This is the code Ehlers used for years on his trend spotter website. This is a big deal. Never been released to retail traders, so have at it. If we can get this turned out in MT4, then perhaps we can convert it to PineScript, but so far, it's just not working doing a Pine Conversion. The High Pass and Super Smoother functions here are the just the same functions that you all know from Ehlers. The rest should be pretty simple, but it's not that simple, even though this does work Trade Station. Here's the easy Language Code. If MrTools or Mladen is around, maybe they can take a look at this. It's well worth the time to parse this code and convert it to MT4 and I don't know of anyone else I would trust to do this. Also notice in this code, the "Cycle" array. I'm not sure what the point is here since it's never filled. That's the problem with this in Pine right now, but maybe you guys will understand this. I don't code for Trade Station, that's purely an Ehlers thing and he doesn't code in Pine. So there's a disconnect here with making this work, but maybe you guys will have more luck in MT4.

This is the MESA dominant cycle.

Code: Select all

>>>>>>>>>>  ! MESA  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
{
	MESA	
	(C) 1978-2021 John F. Ehlers
}

Inputs:
	LowerBound(12),
	UpperBound(54),
	Length(54),
	NumCoef(10),	//Recommend NumCoef setting as 50% of Length.  Do not exceed Length - 1	`	
	ShowDominantCycle(true);
	
Vars:
	MktOpen(630), TimeBars(15),
	Degap(0),
	HP(0),
	Filt(0), 
	count(0),
	tt(0),
	mm(0),
	Pwr(0),
	Num(0),
	Denom(0),
	Period(0),
	DenReal(0),
	DenImag(0),
	temp(0),
	MaxWave(0),
	NumDCCoef(10),
	MaxCycle(0),
	DominantCycle(0),
	cc(0),
	Color1(0),
	Color2(0),
	Color3(0);
	
Arrays:
	P[500](0),
	bb1[500](0),
	bb2[500](0),
	coef[500](0),
	coefA[500](0),
	Hcoef[500](0),
	coef2[500,12](0),
	Wave[500](0),
	NWave[500](0),
	Cycle[500](0);

Degap =ap(Close, MktOpen, TimeBars); $Deg

HP = $HighPass(Degap, UpperBound);

Filt = $SuperSmoother(HP, LowerBound);

//Initialize Power	
Pwr = 0;
For tt = 0 to Length - 1 Begin
	Pwr = Pwr + Filt[tt]*Filt[tt];
End;
Pwr = Pwr / Length;

//Initialize data arrays
bb1[1] = Filt;
bb2[Length - 1] = Filt[Length - 1];
For tt = 2 to Length - 1 Begin
	bb1[tt] = Filt[tt - 1];
	bb2[tt - 1] = Filt[tt - 1];
End;

//Initialized coefficient
Num = 0;
Denom = 0;
For tt = 1 to Length - 1 Begin
	Num = Num + bb1[tt] * bb2[tt];
	Denom = Denom + bb1[tt]*bb1[tt] + bb2[tt]*bb2[tt];
End;
If Denom <> 0 Then coef[1] = 2 * Num / Denom;
P[1] = Pwr * (1 - coef[1] * coef[1]);

//Compute coefficients
For mm = 2 to NumCoef Begin
	For tt = 1 to mm - 1 Begin
		coefA[tt] = coef[tt];
	End;
	For tt = 1 to Length - mm Begin
		bb1[tt] = bb1[tt] - coefA[mm - 1] * bb2[tt];
		bb2[tt] = bb2[tt + 1] - coefA[mm - 1] * bb1[tt +1];
	End;
		
	Num = 0;
	Denom = 0;
	For tt = 1 to Length - mm Begin
		Num = Num + bb1[tt]*bb2[tt];
		Denom = Denom + bb1[tt]*bb1[tt] + bb2[tt]*bb2[tt];
	End;
	If Denom <> 0 Then coef[mm] = 2*Num / Denom;
	P[mm] = P[mm-1]*(1 - coef[mm]*coef[mm]);
	For tt = 1 to mm - 1 Begin
		coef[tt] = coefA[tt] - coef[mm]*coefA[mm -tt];
	End;
End;

//Smooth MESA coefficients by Hann Windowing
For tt = 1 to NumCoef Begin
	coef2[tt, 1] = coef[tt];
	For count = 12 DownTo 2 Begin
		coef2[tt, count] = coef2[tt, count - 1];
	End;
End;
For tt = 1 to NumCoef Begin
	Hcoef[tt] = 0;
	cc = 0;
	For count = 1 to 12 Begin
		Hcoef[tt] = Hcoef[tt] + (1 - Cosine(360*count / (12 + 1))) * coef2[tt, count];
		cc = cc + (1 - Cosine(360*count / (12 + 1)));
	End;
	If cc <> 0 Then Hcoef[tt] = HCoef[tt] / cc;	
End;

//Compute measured Spectrum
For Period = LowerBound to UpperBound Begin
	DenReal = 0;
	DenImag = 0;
	for mm = 1 to NumCoef Begin
		DenReal = DenReal + Hcoef[mm]*Cosine(360*mm / Period);
		DenImag = DenImag - Hcoef[mm]*Sine(360*mm / Period);
	End;
	Wave[Period] = (1 - DenReal)*(1 - DenReal) + DenImag*DenImag;
	If Wave[Period] <> 0 Then Wave[Period] = P[NumCoef] / Wave[Period];
End;

//Normalize Spectrum to Max Value
MaxWave = Wave[LowerBound];
For Period = LowerBound to UpperBound Begin
	If Wave[Period] > MaxWave Then MaxWave = Wave[Period];
End;

//Normalize Amplitudes
For Period = LowerBound to UpperBound Begin
	If MaxWave <> 0 Then NWave[Period] = Wave[Period] / MaxWave;
End;

//Find Dominant Cycle
If ShowDominantCycle = true Then Begin
	MaxCycle = Cycle[LowerBound];
	For Period = LowerBound to UpperBound Begin
		If NWave[Period] > MaxCycle Then Begin
			MaxCycle = NWave[Period];
			DominantCycle = Period;
		End;
	End;
	Plot2(DominantCycle, "DC", Blue, 0, 2);	
end;

//Plot as a Heatmap
Color3 = 0;
For Period = LowerBound to UpperBound Begin
	If NWave[Period] > .5 Then Begin
		Color1 = 255;
		Color2 = 255*(2*NWave[Period] - 1);
	End
	Else Begin
		Color1 = 2*255*NWave[Period];
		Color2 = 0;
	End;
	If Period = 3 Then Plot3[0](3, "S5", RGB(Color1, Color2, Color3),0,4);
	If Period = 4 Then Plot4[0](4, "S4", RGB(Color1, Color2, Color3),0,4);
	If Period = 5 Then Plot5[0](5, "S5", RGB(Color1, Color2, Color3),0,4);
	If Period = 6 Then Plot6[0](6, "S6", RGB(Color1, Color2, Color3),0,4);
	If Period = 7 Then Plot7[0](7, "S7", RGB(Color1, Color2, Color3),0,4);
	If Period = 8 Then Plot8[0](8, "S8", RGB(Color1, Color2, Color3),0,4);
	If Period = 9 Then Plot9[0](9, "S9", RGB(Color1, Color2, Color3),0,4);
	If Period = 10 Then Plot10[0](10, "S10", RGB(Color1, Color2, Color3),0,4);
	If Period = 11 Then Plot11[0](11, "S11", RGB(Color1, Color2, Color3),0,4);
	If Period = 12 Then Plot12[0](12, "S12", RGB(Color1, Color2, Color3),0,4);
	If Period = 13 Then Plot13[0](13, "S13", RGB(Color1, Color2, Color3),0,4);
	If Period = 14 Then Plot14[0](14, "S14", RGB(Color1, Color2, Color3),0,4);
	If Period = 15 Then Plot15[0](15, "S15", RGB(Color1, Color2, Color3),0,4);
	If Period = 16 Then Plot16[0](16, "S16", RGB(Color1, Color2, Color3),0,4);
	If Period = 17 Then Plot17[0](17, "S17", RGB(Color1, Color2, Color3),0,4);
	If Period = 18 Then Plot18[0](18, "S18", RGB(Color1, Color2, Color3),0,4);
	If Period = 19 Then Plot19[0](19, "S19", RGB(Color1, Color2, Color3),0,4);
	If Period = 20 Then Plot20[0](20, "S20", RGB(Color1, Color2, Color3),0,4);
	If Period = 21 Then Plot21[0](21, "S21", RGB(Color1, Color2, Color3),0,4);
	If Period = 22 Then Plot22[0](22, "S22", RGB(Color1, Color2, Color3),0,4);
	If Period = 23 Then Plot23[0](23, "S23", RGB(Color1, Color2, Color3),0,4);
	If Period = 24 Then Plot24[0](24, "S24", RGB(Color1, Color2, Color3),0,4);
	If Period = 25 Then Plot25[0](25, "S25", RGB(Color1, Color2, Color3),0,4);
	If Period = 26 Then Plot26[0](26, "S26", RGB(Color1, Color2, Color3),0,4);
	If Period = 27 Then Plot27[0](27, "S27", RGB(Color1, Color2, Color3),0,4);
	If Period = 28 Then Plot28[0](28, "S28", RGB(Color1, Color2, Color3),0,4);
	If Period = 29 Then Plot29[0](29, "S29", RGB(Color1, Color2, Color3),0,4);
	If Period = 30 Then Plot30[0](30, "S30", RGB(Color1, Color2, Color3),0,4);
	If Period = 31 Then Plot31[0](31, "S31", RGB(Color1, Color2, Color3),0,4);
	If Period = 32 Then Plot32[0](32, "S32", RGB(Color1, Color2, Color3),0,4);
	If Period = 33 Then Plot33[0](33, "S33", RGB(Color1, Color2, Color3),0,4);
	If Period = 34 Then Plot34[0](34, "S34", RGB(Color1, Color2, Color3),0,4);
	If Period = 35 Then Plot35[0](35, "S35", RGB(Color1, Color2, Color3),0,4);
	If Period = 36 Then Plot36[0](36, "S36", RGB(Color1, Color2, Color3),0,4);
	If Period = 37 Then Plot37[0](37, "S37", RGB(Color1, Color2, Color3),0,4);
	If Period = 38 Then Plot38[0](38, "S38", RGB(Color1, Color2, Color3),0,4);
	If Period = 39 Then Plot39[0](39, "S39", RGB(Color1, Color2, Color3),0,4);
	If Period = 40 Then Plot40[0](40, "S40", RGB(Color1, Color2, Color3),0,4);
	If Period = 41 Then Plot41[0](41, "S41", RGB(Color1, Color2, Color3),0,4);
	If Period = 42 Then Plot42[0](42, "S42", RGB(Color1, Color2, Color3),0,4);
	If Period = 43 Then Plot43[0](43, "S43", RGB(Color1, Color2, Color3),0,4);
	If Period = 44 Then Plot44[0](44, "S44", RGB(Color1, Color2, Color3),0,4);
	If Period = 45 Then Plot45[0](45, "S45", RGB(Color1, Color2, Color3),0,4);
	If Period = 46 Then Plot46[0](46, "S46", RGB(Color1, Color2, Color3),0,4);
	If Period = 47 Then Plot47[0](47, "S47", RGB(Color1, Color2, Color3),0,4);
	If Period = 48 Then Plot48[0](48, "S48", RGB(Color1, Color2, Color3),0,4);
	If Period = 49 Then Plot49(49, "S49", RGB(Color1, Color2, 0),0,4);
	If Period = 50 Then Plot50(50, "S50", RGB(Color1, Color2, 0),0,4);
	If Period = 51 Then Plot51(51, "S51", RGB(Color1, Color2, 0),0,4);
	If Period = 52 Then Plot52(52, "S52", RGB(Color1, Color2, 0),0,4);
	If Period = 53 Then Plot53(53, "S53", RGB(Color1, Color2, 0),0,4);
	If Period = 54 Then Plot54(54, "S54", RGB(Color1, Color2, 0),0,4);
	If Period = 55 Then Plot55(55, "S55", RGB(Color1, Color2, 0),0,4);
	If Period = 56 Then Plot56(56, "S56", RGB(Color1, Color2, 0),0,4);
	If Period = 57 Then Plot57(57, "S57", RGB(Color1, Color2, 0),0,4);
	If Period = 58 Then Plot58(58, "S58", RGB(Color1, Color2, 0),0,4);
	If Period = 59 Then Plot59(59, "S59", RGB(Color1, Color2, 0),0,4);
	If Period = 60 Then Plot60(60, "S60", RGB(Color1, Color2, 0),0,4);
	If Period = 61 Then Plot61(61, "S61", RGB(Color1, Color2, 0),0,4);
	If Period = 62 Then Plot62(62, "S62", RGB(Color1, Color2, 0),0,4);
	If Period = 63 Then Plot63(63, "S63", RGB(Color1, Color2, 0),0,4);
	If Period = 64 Then Plot64(64, "S64", RGB(Color1, Color2, 0),0,4);
	If Period = 65 Then Plot65(65, "S65", RGB(Color1, Color2, 0),0,4);
	If Period = 66 Then Plot66(66, "S66", RGB(Color1, Color2, 0),0,4);
	If Period = 67 Then Plot67(67, "S67", RGB(Color1, Color2, 0),0,4);
	If Period = 68 Then Plot68(68, "S68", RGB(Color1, Color2, 0),0,4);
	If Period = 69 Then Plot69(69, "S69", RGB(Color1, Color2, 0),0,4);
	If Period = 70 Then Plot70(70, "S70", RGB(Color1, Color2, 0),0,4);
	If Period = 71 Then Plot71(71, "S71", RGB(Color1, Color2, 0),0,4);
	If Period = 72 Then Plot72(72, "S72", RGB(Color1, Color2, 0),0,4);
	If Period = 73 Then Plot73(73, "S73", RGB(Color1, Color2, 0),0,4);
	If Period = 74 Then Plot74(74, "S74", RGB(Color1, Color2, 0),0,4);
	If Period = 75 Then Plot75(75, "S75", RGB(Color1, Color2, 0),0,4);
	If Period = 76 Then Plot76(76, "S76", RGB(Color1, Color2, 0),0,4);
	If Period = 77 Then Plot77(77, "S77", RGB(Color1, Color2, 0),0,4);
	If Period = 78 Then Plot78(78, "S78", RGB(Color1, Color2, 0),0,4);
	If Period = 79 Then Plot79(79, "S79", RGB(Color1, Color2, 0),0,4);
	If Period = 80 Then Plot80(80, "S80", RGB(Color1, Color2, 0),0,4);
	If Period = 81 Then Plot81(81, "S81", RGB(Color1, Color2, 0),0,4);
	If Period = 82 Then Plot82(82, "S82", RGB(Color1, Color2, 0),0,4);
	If Period = 83 Then Plot83(83, "S83", RGB(Color1, Color2, 0),0,4);
	If Period = 84 Then Plot84(84, "S84", RGB(Color1, Color2, 0),0,4);
	If Period = 85 Then Plot85(85, "S85", RGB(Color1, Color2, 0),0,4);
	If Period = 86 Then Plot86(86, "S86", RGB(Color1, Color2, 0),0,4);
	If Period = 87 Then Plot87(87, "S87", RGB(Color1, Color2, 0),0,4);
	If Period = 88 Then Plot88(88, "S88", RGB(Color1, Color2, 0),0,4);
	If Period = 89 Then Plot89(89, "S89", RGB(Color1, Color2, 0),0,4);
	If Period = 90 Then Plot90(90, "S90", RGB(Color1, Color2, 0),0,4);
	If Period = 91 Then Plot91(91, "S91", RGB(Color1, Color2, 0),0,4);
	If Period = 92 Then Plot92(92, "S92", RGB(Color1, Color2, 0),0,4);
	If Period = 93 Then Plot93(93, "S93", RGB(Color1, Color2, 0),0,4);
	If Period = 94 Then Plot94(94, "S94", RGB(Color1, Color2, 0),0,4);
	If Period = 95 Then Plot95(95, "S95", RGB(Color1, Color2, 0),0,4);
	If Period = 96 Then Plot96(96, "S96", RGB(Color1, Color2, 0),0,4);
	If Period = 97 Then Plot97(97, "S97", RGB(Color1, Color2, 0),0,4);
	If Period = 98 Then Plot98(98, "S98", RGB(Color1, Color2, 0),0,4);
	If Period = 99 Then Plot99(99, "S99", RGB(Color1, Color2, 0),0,4);	
	
End;
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Once this is converted to MT4, we have a whole new world open to us in terms of indicators.
The high pass and super smoother are here:

Code: Select all

>>>>>>>>>>  $HighPass  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
{
     Highpass Function
     (C) 2013-2021   John F. Ehlers
}

Inputs:
	Price(numericseries),
	Period(numericsimple);
	
Vars:
	a1(0),
	b1(0),
	c1(0),
	c2(0),
	c3(0);

a1 = expvalue(-1.414*3.14159 / Period);
b1 = 2*a1*Cosine(1.414*180 / Period);
c2 = b1;
c3 = -a1*a1;
c1 = (1 + c2 - c3) / 4;

$HighPass = c1*(Price - 2*Price[1] + Price[2]) + c2*$HighPass[1] + c3*$HighPass[2];
If Currentbar < 4 Then $HighPass = 0;
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
and

Code: Select all

>>>>>>>>>>  $SuperSmoother  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
{
     SuperSmoother Function
     (C) 2015-2021  John F. Ehlers
}

Inputs:
	Price(numericseries),
	Period(numericsimple);
	
Vars:
	a1(0),
	b1(0),
	c1(0),
	c2(0),
	c3(0);

a1 = expvalue(-1.414*3.14159 / Period);
b1 = 2*a1*Cosine(1.414*180 / Period);
c2 = b1;
c3 = -a1*a1;
c1 = 1 - c2 - c3;
$SuperSmoother = c1*(Price + Price[1]) / 2 + c2*$SuperSmoother[1] + c3*$SuperSmoother[2];
If Currentbar < 3 Then $SuperSmoother = Price;
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
EDIT, added Degap function

Code: Select all

>>>>>>>>>>  $Degap  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
{
     Degap Function
     (C) 2015-2021  John F. Ehlers
}

Inputs:
	Price(numericseries),
	SessionOpen(numericsimple),
	TimeBars(numericsimple);
	
Vars:
	Gap(0);

If Time = SessionOpen + TimeBars Then Gap = Price - $Degap[1];
$Degap = Price - Gap;
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Emjoy
I converted the indi to MT4 but I can't seem to make it work properly

is there some code missing ?

Jeff
These users thanked the author ionone for the post (total 5):
Jackson Doh, Chickenspicy, krzysiaczek99, RodrigoRT7, loxx


Re: Ehlers Indicators for MT4

596
ionone wrote: Thu Feb 09, 2023 11:53 pm I converted the indi to MT4 but I can't seem to make it work properly

is there some code missing ?

Jeff
Thanks for that. I will check if it is any good. I also got mail from John - see below. It gives some light..
Krzysztof

Krzysztol:
After years of research I conclude it is basically hopeless to use measured frequency. That is because frequency it the rate change of angle (derivative), and therefore is much more noisy. It is therefore better to create indicators base on the measured angle.
A more direct approach is to simply use a combination of a highpass and lowpass filter to create the bandlimited waveforms from which you extract the trading signals.
I think this is a profound overview of DSP applied to trading: Market data are fractal and has a pink noise spectrum. That means that the amplitude of the cyclic component swings are in direct proportion to their wavelength. A reasonable approximation is that the cyclic swing amplitudes increase at the rate of 6 dB per octave. Since the spectrum components do not have equal amplitude, cyclic analysis is possible only if the spectrum is equalized. The spectrum can be equalized by taking a simple difference of successive data samples, which is approximately the same as taking a derivative in calculus. The derivative has a frequency response of -6 dB per octave, which provides the equalization. The result of taking the difference is a band limited signal (i.e. an oscillator). The information in the band limited signal can be recovered by using the opposite mathematical function; taking the integral of the band limited signal. Integration is the equivalent of summation and summation is the basically the same as Low Pass filtering. The result of using the two opposite calculus operations is an approximation to a statistically matched filter in the frequency domain. This matched filter can be tuned using combinations of HighPass and LowPass filters.
I hope this helps.
John

On 2/5/2023 7:51 AM, Krzysztof Fajst wrote:
Hello John,

Hope you are well.

My name is Krzysztof and I ‘am a fan of your work related to
using DSP for trading. Recently I made some testing of your code related
to Dominant Cycle calculation using different methods suggest by you
and I found some strange behaviours. I enclose two screenshots one for
test signals (chirp and teeth saw) and real time data. Dominant cycle calculators are
as followed:

1 - From the book 'Cybernetic Analysis for Stocks and Futures' by John Ehlers
2 - From book 'Cycle Analysis for Traders' by John Ehlers autocorrelation periodogram
3 - From book 'Cycle Analysis for Traders' by John Ehlers combined BandPass output
4 - TASC0308 (BandPass filter bank)
5 - From book 'Cycle Analysis for Traders' by John Ehlers DFT

from screenshots we can see that all detectors are OK with chirp signal

as per trends (297 bars long) is clear that some of them settle on completely wrong period
so nr 3 on 23 bars and nr 5 on 13 bars. Nr 5 has some strange notches down from expected
period of 50 bars. Do you maybe know how to correct this ??

As per real data and comparison of DC measured all of them show different DC. Nr 4 for example
shows the same DC value even market switches from trend mode to cycle node (01/22 - 05/22). Nr 3
shows similar behaviour. Any idea which of those detectors is most accurate ??

Krzysztof
These users thanked the author krzysiaczek99 for the post (total 3):
Chickenspicy, Jackson Doh, ionone


Who is online

Users browsing this forum: Abdi, eka2, Google Images [Bot], kvak, Proximic [Bot] and 109 guests