Registered User Joined: 10/7/2004 Posts: 816
|
Bruce,
I’ve been trying to convert John Ehler’s Sinewave indicator for a couple of weeks now – and I’ve gotten myself so confused I that I need your help. I’ve been using a version from Metastock for years and the Sinewave indicator is the only thing that hasn’t been converted to Stockfinder yet. Since jumping in and out of Metastock just for that is not very efficient and is actually a pain – I’d like to just use Stockfinder exclusively.
It’s an indicator that effectively identifies trending versus cyclical markets effectively and when used with the LeadSine (Plot 2 below) can identify cycle turning points by the LeadSine crossing the Sine line. According to John “The Sinewave Indicator gives entry and exit signals 1/16th of a cycle period in advance of the cycle turning point. The Sinewave indicator seldom give false whipsaw signals when the market is in a Trend Mode”
Additionally, a good portion of the code is re-usable in making some standard indicators ( RSI, Stochastics and CCI are the ones John identifies specifically ) more adaptable to current market conditions.
Ehler’s Sinewave Indicator from my copy of Rocket Science for Traders by John Ehlers (in EasyLanguage [so they say]):
Variables:
Smooth
Detrender
I1
Q1
jI
jQ
I2
Q2
Re
Im
Period
SmoothPeriod
SmoothPrice
DCPeriod
RealPart
ImagPart
Count
DCPhase
Input: Price((Hi + Low)/2)
If CurrentBar > 5 then
Smooth = ( 4*Price + 3*Price(1) + 2*Price(2) + Price(3))/10
Detrender = (.0962*Smooth + .5769*Smooth(2) - .5769*Smooth(4) - .0962*Smooth(6) ) * (.075*Period(1) + .54)
‘Compute InPhase and Quadrature components
Q1 = (.0962*DeTrender + .5769* DeTrender (2) - .5769* DeTrender (4) - .0962* DeTrender (6) ) * (.075*Period(1) + .54)
I1 = Detrender(3)
‘Advance the phase of I1 and Q1 by 90 degrees
J1 = (.0962*I1 + .5769* I1 (2) - .5769* I1 (4) - .0962* I1 (6) ) * (.075*Period(1) + .54)
jQ = (.0962*Q1 + .5769* Q1 (2) - .5769* Q1 (4) - .0962* Q1 (6) ) * (.075*Period(1) + .54)
‘ Phasor addition for 3 bar averaging
I2 = I1 + jQ
Q2 = Q1 + Ji
‘ Smooth the I and Q components before applying the discriminator
I2 = .2*I2 + .8*I2(1)
Q2 = .2*Q2 + .8*Q2(1)
‘ Homodyne Discriminator
Re = I2*I2(1) + Q2*Q2(1)
Im = I2*Q2(1) – Q2*I2(1)
Re = .2* Re + .8*Re(1)
Im = .2*Im + .8*Im(1)
If Im <> 0 and Re <> 0 then Period = 360/ArcTangent(Im/Re)
If Period > 1.5*Period(1) then Period = 1.5*Period(1)
If Period < .67Period(1) then Period = .67*Period(1)
If Period < 6 then Period = 6
If Period > 50 then Period = 50
Period = .2*Period + .8*Period(1)
SmoothPeriod = .33*Period + .67* SmoothPeriod(1)
‘ Compute Dominant Cycle Phase
SmoothPrice = (4*Price + 3*Price(1) + 2*Price(2) + Price(3)) /10
DCPeriod = IntPortion(SmoothPeriod + .5)
RealPart = 0
ImagPart = 0
For count = 0 to DCPeriod -1 begin
RealPart = RealPart + Cosine(360 * count / DCPeriod) * (SmoothPrice(count))
ImagPart = ImagPart + Sine(360*count / DCPeriod) * (SmoothPrice(count))
End
If AbsValue(RealPart ) > 0.001 then DCPhase = ArcTangent(ImagPart / RealPart)
If AbsValue(RealPart ) <= 0.001 then DCPhase = 90* Sign (ImagPart)
DCPhase = DCPhase + 90
‘ Compensate for one bar lag of weighted moving average
DCPhase + DCPhase + 360*SmoothPeriod
If ImagPart < 0 then DCPhase = DCPhase + 180
If DCPhase > 315 then DCPhase = DCPhase – 360
Plot1 = Sine(DCPhase)
End
===================================================
Note: Plot2 would be the signal line with the same code except Plot 1 =Sine(DCPhase) would be replaced by Plot 2 = Sine(DCPhase + 45)
I’d greatly appreciate your realcode help
Thanks
BobMc
|
|
Registered User Joined: 10/7/2004 Posts: 816
|
Ah! the devil is in the details
it appears the devil doesn't like sixes
in the "detrender" line -.0962 * Smooth[6]
in the "Q1" line -.0962 * Detrender[6]
in the "J1" line -.0962 * I1[6]
in the "jQ" line -.0962 * Q1 [6]
Regards
BobMc
|
|
Worden Trainer
Joined: 10/7/2004 Posts: 65,138
|
I really don't speak EasyLanguage, so the following is probably completely wrong (with no knowledge of how it is supposed to be interpreted, it certainly looks seriously wrong to me), but here is my first attempt at an absolutely literal interpretation (quite a few optimizations could probably be applied once an accurate literal interpretation is achieved):
'|******************************************************************
'|*** StockFinder RealCode Indicator - Version 5.0 www.worden.com
'|*** Copy and paste this header and code into StockFinder *********
'|*** Indicator:Ehler's Sinewave Indicator
'|******************************************************************
'# Cumulative
Static Input As New List(Of Single)
Static Smooth As New List(Of Single)
Static Detrender As New List(Of Single)
Static Q1 As New List(Of Single)
Static I1 As New List(Of Single)
Static J1 As New List(Of Single)
Static jQ As New List(Of Single)
Static I2 As New List(Of Single)
Static J2 As New List(Of Single)
Static Q2 As New List(Of Single)
Static Re As New List(Of Single)
Static Im As New List(Of Single)
Static Period As New List(Of Single)
Static SmoothPeriod As New List(Of Single)
Static Deg As Single
If isFirstBar Then
Input.Clear
Smooth.Clear
Detrender.Clear
Q1.Clear
I1.Clear
J1.Clear
jQ.Clear
I2.Clear
J2.Clear
Q2.Clear
Re.Clear
Im.Clear
Period.Clear
Period.Add(6 )
Period.Add(6 )
SmoothPeriod.Clear
Deg = 180 / System.Math.Pi
End If
Input.Add((Price.High + Price.Low) / 2)
If Input.Count = 4 Then
Smooth.Add((4 * Input(3) + 3 * Input(2) + 2 * Input(1) + Input(0)) / 10)
Input.RemoveAt(0)
End If
If Smooth.Count >= 7 Then
Detrender.Add((.0962 * Smooth(Smooth.Count - 1) + _
.5769 * Smooth(Smooth.Count - 3) - _
.5769 * Smooth(Smooth.Count - 5) - _
.0962 * Smooth(Smooth.Count - 7)) * (.075 * Period(0) + .54))
If Smooth.Count > 50 Then
Smooth.RemoveAt(0)
End If
End If
'Compute InPhase and Quadrature components
If Detrender.Count >= 4 Then
I1.Add(Detrender(Detrender.Count - 4))
End If
If Detrender.Count = 7 Then
Q1.Add((.0962 * Detrender(6 ) + .5769 * Detrender(4) - _
.5769 * Detrender(2) - .0962 * Detrender(0)) * (.075 * Period(0) + .54))
Detrender.RemoveAt(0)
End If
'Advance the phase of I1 and Q1 by 90 degrees
If I1.Count = 7 Then
J1.Add((.0962 * I1(6 ) + .5769 * I1(4) - _
.5769 * I1(2) - .0962 * I1(0)) * (.075 * Period(0) + .54))
I1.RemoveAt(0)
If J1.Count > 1 Then
J1.RemoveAt(0)
End If
End If
If Q1.Count = 7 Then
jQ.Add((.0962 * Q1(6 ) + .5769 * Q1(4) - _
.5769 * Q1(2) - .0962 * Q1(0)) * (.075 * Period(0) + .54))
Q1.RemoveAt(0)
If jQ.Count > 1 Then
jQ.RemoveAt(0)
End If
End If
'Phasor addition for 3 bar averaging
If I1.Count >= 1 AndAlso jQ.Count = 1 Then
I2.Add(I1(I1.Count - 1) + jQ(0))
End If
If Q1.Count >= 1 AndAlso J1.Count = 1 Then
Q2.Add(Q1(Q1.Count - 1) + J1(0))
End If
'Smooth the I and Q components before applying the discriminator
If I2.Count >= 2 Then
I2(1) = .2 * I2(1) + .8 * I2(0)
End If
If Q2.Count >= 2 Then
Q2(1) = .2 * Q2(1) + .8 * Q2(0)
End If
'Homodyne Discriminator
If I2.Count = 2 AndAlso Q2.Count = 2 Then
Re.Add(I2(1) * I2(0) + Q2(1) * Q2(0))
Im.Add(I2(1) * Q2(0) - Q2(1) * I2(0))
End If
If Re.Count = 2 Then
Re(1) = .2 * Re(1) + .8 * Re(0)
Re.RemoveAt(0)
End If
If Im.Count = 2 Then
Im(1) = .2 * Im(1) + .8 * Im(0)
Im.RemoveAt(0)
End If
If I2.Count = 2 Then
I2.RemoveAt(0)
End If
If Q2.Count = 2 Then
Q2.RemoveAt(0)
End If
If Re.Count = 1 AndAlso Re(0) <> 0 AndAlso _
Im.Count = 1 AndAlso Im(0) <> 0 Then
Period.Add(360 / (Deg * System.Math.Atan(Im(0) / Re(0))))
End If
If Period.Count = 2 Then
If Period(1) > 1.5 * Period(0) Then Period(1) = 1.5 * Period(0)
If Period(1) < .67 * Period(0) Then Period(1) = .67 * Period(0)
If Period(1) < 6 Then Period(1) = 6
If Period(1) > 50 Then Period(1) = 50
Period(1) = .2 * Period(1) + .8 * Period(0)
Period.RemoveAt(0)
End If
SmoothPeriod.Add(Period(0))
If SmoothPeriod.Count = 2 Then
SmoothPeriod(1) = .33 * SmoothPeriod(1) + .67 * SmoothPeriod(0)
SmoothPeriod.RemoveAt(0)
End If
'Compute Dominant Cycle Phase
Dim DCPeriod As Integer = System.Math.Floor(SmoothPeriod(0) + .5)
DCPeriod = System.Math.Min(DCPeriod, Smooth.Count)
If DCPeriod >= 6 Then
Dim RealPart As Single = 0
Dim ImagPart As Single = 0
For count As Integer = 0 To DCPeriod - 1
RealPart += System.Math.Cos((360 * count / DCPeriod) / Deg) _
* (Smooth(Smooth.Count - 1 - count))
ImagPart += System.Math.Sin((360 * count / DCPeriod) / Deg) _
* (Smooth(Smooth.Count - 1 - count))
Next
Dim DCPhase As Single
If System.Math.Abs(RealPart) > 0.001 Then
DCPhase = Deg * System.Math.Atan(ImagPart / RealPart)
Else
DCPhase = 90 * System.Math.Sign(ImagPart)
End If
DCPhase += 90
'Compensate for one bar lag of weighted moving average
DCPhase += 360 / SmoothPeriod(0)
If ImagPart < 0 Then
DCPhase += 180
End If
If DCPhase > 315 Then
DCPhase -= 360
End If
OpenValue = System.Math.Sin((DCPhase + 45) / Deg)
HighValue = System.Math.Sin(DCPhase / Deg)
LowValue = System.Math.Sin(DCPhase / Deg)
Plot = System.Math.Sin(DCPhase / Deg)
Else
OpenValue = Single.NaN
HighValue = Single.NaN
LowValue = Single.NaN
Plot = Single.NaN
End If
-Bruce Personal Criteria Formulas TC2000 Support Articles
|
|
Registered User Joined: 10/7/2004 Posts: 816
|
Thanks Bruce
I'll install this and compare it with the Metastock version and we'll go from there if necessary.
After looking at your code it's no wonder that my attempt was pretty feeble.
Appreciate your work
Thanks and Regards
BobMc
|
|
Registered User Joined: 10/7/2004 Posts: 816
|
Bruce,
You're absolute right about the indicator looking seriously wrong. Doesn't come close to the metastock indicator. I know it's not right but unfortunately I can't get to the metastock code to see if it's similar or even matches the book's code. So I'll keep looking.
Couple of quick questions
- I assume this is the way to declare an array - Static Q1 As New List(Of Single) and you don't have to indicate a number of elements in the array?
- Period.Add(6 ) there are 2 of these - don't know if that matters or not?
- In this logic - If Smooth.Count >= 7 Then
Detrender.Add((.0962 * Smooth(Smooth.Count - 1) + _
.5769 * Smooth(Smooth.Count - 3) - _
.5769 * Smooth(Smooth.Count - 5) - _
.0962 * Smooth(Smooth.Count - 7)) * (.075 * Period(0) + .54))
If Smooth.Count > 50 Then
Smooth.RemoveAt(0)
End If
End If
--is the bolded part the way to remove the first entry of the array and shift all the others?
I'm going to spent some more time trying to understand the code
Regards
BobMc
|
|
Worden Trainer
Joined: 10/7/2004 Posts: 65,138
|
I could be wring (I'm not a programmer), but I think that at least in VB parlance, it is technically a list and not an array (there is even a method to convert a list to an array), but for our purposes, considering the result to be an adjustable size array works just fine.
The two Period.Add(6 ) lines fill the Period list with two past Periods defaulted to 6 to get things started. Each line adds one element with a value of 6.
The .RemoveAt(0) method removes the first element of the list and shifts everything else.
I used this technique to try and replicate the supplied code as closely as possible by supplying past values for the variables. For some variables, this just adds complication.
One note is that the trigonometric functions in the original code appear to be in degrees while VB uses radians. I tried to convert it correctly, but even one conversion being missed, in the wrong direction or even in the wrong place parentheses wise could create very, very different results from the original.
Another note is that the lists are zero based with the oldest item being zero, while references in the original code were the number of Bars Ago being referenced.
Yet another note is that this line form the original seemed absolutely meaningless to me:
DCPhase + DCPhase + 360*SmoothPeriod
I ended up with the following line only after searching for the Indicator on the internet and looking at the code I was able to find:
DCPhase += 360 / SmoothPeriod(0)
The fact that Period can have only a single value instead of two in the original version seems problematic, so I have created a new version (probably still wrong).
'|******************************************************************
'|*** StockFinder RealCode Indicator - Version 5.0 www.worden.com
'|*** Copy and paste this header and code into StockFinder *********
'|*** Indicator:Ehler's Sinewave Indicator
'|******************************************************************
'# Cumulative
Static Input As New List(Of Single)
Static Smooth As New List(Of Single)
Static Detrender As New List(Of Single)
Static Q1 As New List(Of Single)
Static I1 As New List(Of Single)
Static J1 As New List(Of Single)
Static jQ As New List(Of Single)
Static I2 As New List(Of Single)
Static J2 As New List(Of Single)
Static Q2 As New List(Of Single)
Static Re As New List(Of Single)
Static Im As New List(Of Single)
Static Period As New List(Of Single)
Static SmoothPeriod As New List(Of Single)
Static Deg As Single
If isFirstBar Then
Input.Clear
Smooth.Clear
Detrender.Clear
Q1.Clear
I1.Clear
J1.Clear
jQ.Clear
I2.Clear
J2.Clear
Q2.Clear
Re.Clear
Im.Clear
Period.Clear
Period.Add(6 )
SmoothPeriod.Clear
Deg = 180 / System.Math.Pi
End If
Input.Add((Price.High + Price.Low) / 2)
If Input.Count = 4 Then
Smooth.Add((4 * Input(3) + 3 * Input(2) + 2 * Input(1) + Input(0)) / 10)
Input.RemoveAt(0)
End If
If Smooth.Count >= 7 Then
Detrender.Add((.0962 * Smooth(Smooth.Count - 1) + _
.5769 * Smooth(Smooth.Count - 3) - _
.5769 * Smooth(Smooth.Count - 5) - _
.0962 * Smooth(Smooth.Count - 7)) * (.075 * Period(0) + .54))
If Smooth.Count > 50 Then
Smooth.RemoveAt(0)
End If
End If
'Compute InPhase and Quadrature components
If Detrender.Count >= 4 Then
I1.Add(Detrender(Detrender.Count - 4))
End If
If Detrender.Count = 7 Then
Q1.Add((.0962 * Detrender(6 ) + .5769 * Detrender(4) - _
.5769 * Detrender(2) - .0962 * Detrender(0)) * (.075 * Period(0) + .54))
Detrender.RemoveAt(0)
End If
'Advance the phase of I1 and Q1 by 90 degrees
If I1.Count = 7 Then
J1.Add((.0962 * I1(6 ) + .5769 * I1(4) - _
.5769 * I1(2) - .0962 * I1(0)) * (.075 * Period(0) + .54))
I1.RemoveAt(0)
If J1.Count > 1 Then
J1.RemoveAt(0)
End If
End If
If Q1.Count = 7 Then
jQ.Add((.0962 * Q1(6 ) + .5769 * Q1(4) - _
.5769 * Q1(2) - .0962 * Q1(0)) * (.075 * Period(0) + .54))
Q1.RemoveAt(0)
If jQ.Count > 1 Then
jQ.RemoveAt(0)
End If
End If
'Phasor addition for 3 bar averaging
If I1.Count >= 1 AndAlso jQ.Count = 1 Then
I2.Add(I1(I1.Count - 1) + jQ(0))
End If
If Q1.Count >= 1 AndAlso J1.Count = 1 Then
Q2.Add(Q1(Q1.Count - 1) + J1(0))
End If
'Smooth the I and Q components before applying the discriminator
If I2.Count >= 2 Then
I2(1) = .2 * I2(1) + .8 * I2(0)
End If
If Q2.Count >= 2 Then
Q2(1) = .2 * Q2(1) + .8 * Q2(0)
End If
'Homodyne Discriminator
If I2.Count = 2 AndAlso Q2.Count = 2 Then
Re.Add(I2(1) * I2(0) + Q2(1) * Q2(0))
Im.Add(I2(1) * Q2(0) - Q2(1) * I2(0))
End If
If Re.Count = 2 Then
Re(1) = .2 * Re(1) + .8 * Re(0)
Re.RemoveAt(0)
End If
If Im.Count = 2 Then
Im(1) = .2 * Im(1) + .8 * Im(0)
Im.RemoveAt(0)
End If
If I2.Count = 2 Then
I2.RemoveAt(0)
End If
If Q2.Count = 2 Then
Q2.RemoveAt(0)
End If
If Re.Count = 1 AndAlso Re(0) <> 0 AndAlso _
Im.Count = 1 AndAlso Im(0) <> 0 Then
Period.Add(360 / (Deg * System.Math.Atan(Im(0) / Re(0))))
End If
If Period.Count >= 2 Then
If Period(Period.Count - 1) > 1.5 * Period(Period.Count - 2) Then
Period(Period.Count - 1) = 1.5 * Period(Period.Count - 2)
End If
If Period(Period.Count - 1) < .67 * Period(Period.Count - 2) Then
Period(Period.Count - 1) = .67 * Period(Period.Count - 2)
End If
If Period(Period.Count - 1) < 6 Then
Period(Period.Count - 1) = 6
End If
If Period(Period.Count - 1) > 50 Then
Period(Period.Count - 1) = 50
End If
Period(Period.Count - 1) = .2 * Period(Period.Count - 1) + _
.8 * Period(Period.Count - 2)
Period.RemoveAt(0)
Else
Period.Add(Period(Period.Count - 1))
End If
SmoothPeriod.Add(Period(0))
If SmoothPeriod.Count = 2 Then
SmoothPeriod(1) = .33 * SmoothPeriod(1) + .67 * SmoothPeriod(0)
SmoothPeriod.RemoveAt(0)
End If
'Compute Dominant Cycle Phase
Dim DCPeriod As Integer = System.Math.Floor(SmoothPeriod(0) + .5)
DCPeriod = System.Math.Min(DCPeriod, Smooth.Count)
If DCPeriod >= 6 Then
Dim RealPart As Single = 0
Dim ImagPart As Single = 0
For count As Integer = 0 To DCPeriod - 1
RealPart += System.Math.Cos((360 * count / DCPeriod) / Deg) _
* (Smooth(Smooth.Count - 1 - count))
ImagPart += System.Math.Sin((360 * count / DCPeriod) / Deg) _
* (Smooth(Smooth.Count - 1 - count))
Next
Dim DCPhase As Single
If System.Math.Abs(RealPart) > 0.001 Then
DCPhase = Deg * System.Math.Atan(ImagPart / RealPart)
Else
DCPhase = 90 * System.Math.Sign(ImagPart)
End If
DCPhase += 90
'Compensate for one bar lag of weighted moving average
DCPhase += 360 / SmoothPeriod(0)
If ImagPart < 0 Then
DCPhase += 180
End If
If DCPhase > 315 Then
DCPhase -= 360
End If
OpenValue = System.Math.Sin((DCPhase + 45) / Deg)
HighValue = System.Math.Sin(DCPhase / Deg)
LowValue = System.Math.Sin(DCPhase / Deg)
Plot = System.Math.Sin(DCPhase / Deg)
Else
OpenValue = Single.NaN
HighValue = Single.NaN
LowValue = Single.NaN
Plot = Single.NaN
End If
-Bruce Personal Criteria Formulas TC2000 Support Articles
|
|
Registered User Joined: 10/7/2004 Posts: 816
|
Hi Bruce
You are correct that there are 2 periods referenced : Period and Period(1) - I just didn't realize you were providing initial values
DCPhase + DCPhase + 360*SmoothPeriod should have been a divide as you correctly changed it
One of the things that caught my eye was If Detrender.Count = 7 Then - shouldn't that be >= 7 ?
Also If I1.Count = 7 ; If Q1.Count = 7
At first I couldn't find the I1 = Detrender(3) but I think this is the way you did that:
If Detrender.Count >= 4 Then
I1.Add(Detrender(Detrender.Count - 4))
End If
Thanks for the hard work on this - I would have had a hard time figuring out that the first item in a list would be the oldest
Regards
BobMc
|
|
Worden Trainer
Joined: 10/7/2004 Posts: 65,138
|
The counts should never be greater than 7 for those with = 7 instead of >= 7 because we are constantly removing the oldest Value.
You are correct about where I1 = Detrender(3) happens and how.
-Bruce Personal Criteria Formulas TC2000 Support Articles
|
|
Registered User Joined: 1/28/2005 Posts: 6,049
|
Typ : Indicator, Name : Sine Wave Indicator
Inputs:
Price((H+L)/2);
Vars:
InPhase(0),
Quadrature(0),
Phase(0),
DeltaPhase(0),
count(0),
InstPeriod(0),
Period(0),
DCPhase(0),
RealPart(0),
ImagPart(0);
If CurrentBar > 5 then begin
{Compute InPhase and Quadrature components}
Value1 = Price - Price[6];
Value2 =Value1[3];
Value3 =.75*(Value1 - Value1[6]) + .25*(Value1[2] - Value1[4]);
InPhase = .33*Value2 + .67*InPhase[1];
Quadrature = .2*Value3 + .8*Quadrature[1];
{Use ArcTangent to compute the current phase}
If AbsValue(InPhase +InPhase[1]) > 0 then Phase =
ArcTangent(AbsValue((Quadrature+Quadrature[1]) / (InPhase+InPhase[1])));
{Resolve the ArcTangent ambiguity}
If InPhase < 0 and Quadrature > 0 then Phase = 180 - Phase;
If InPhase < 0 and Quadrature < 0 then Phase = 180 + Phase;
If InPhase > 0 and Quadrature < 0 then Phase = 360 - Phase;
{Compute a differential phase, resolve phase wraparound, and limit delta phase errors}
DeltaPhase = Phase[1] - Phase;
If Phase[1] < 90 and Phase > 270 then DeltaPhase = 360 + Phase[1] - Phase;
If DeltaPhase < 1 then DeltaPhase = 1;
If DeltaPhase > 60 then Deltaphase = 60;
{Sum DeltaPhases to reach 360 degrees. The sum is the instantaneous period.}
InstPeriod = 0;
Value4 = 0;
For count = 0 to 40 begin
Value4 = Value4 + DeltaPhase[count];
If Value4 > 360 and InstPeriod = 0 then begin
InstPeriod = count;
end;
end;
{Resolve Instantaneous Period errors and smooth}
If InstPeriod = 0 then InstPeriod = InstPeriod[1];
Value5 = .25*InstPeriod + .75*Value5[1];
{Compute Dominant Cycle Phase, Sine of the Phase Angle, and Leadsine}
Period = IntPortion(Value5);
RealPart = 0;
ImagPart = 0;
For count = 0 To Period - 1 begin
RealPart = RealPart + Sine(360 * count / Period) * (Price[count]);
ImagPart = ImagPart + Cosine(360 * count / Period) * (Price[count]);
end;
If AbsValue(ImagPart) > 0.001 then DCPhase = Arctangent(RealPart / ImagPart);
If AbsValue(ImagPart) <= 0.001 then DCPhase = 90 * Sign(RealPart);
DCPhase = DCPhase + 90;
If ImagPart < 0 then DCPhase = DCPhase + 180;
If DCPhase > 315 then DCPhase = DCPhase - 360;
Plot1(Sine(DCPhase), "Sine");
Plot2(Sine(DCPhase + 45), "LeadSine");
end;
===============================================================
Dont know if this helps, I think its a later version. (by Ehlers)
To my eye it seems simpler to calculate.
(Remarks are in red)
Thanks
diceman
|
|
Worden Trainer
Joined: 10/7/2004 Posts: 65,138
|
Here's my first literal interpretation for the version posted by Diceman. It looks a lot more like what I would think of as a reasonable Indicator (as with my first interpretation of the originally posted code, there is quite a bit of optimization which could be done if the results are correct).
'|******************************************************************
'|*** StockFinder RealCode Indicator - Version 5.0 www.worden.com
'|*** Copy and paste this header and code into StockFinder *********
'|*** Indicator:Sine Wave Indicator
'|******************************************************************
'# Cumulative
Static Input As New List(Of Single)
Static Value1 As New List(Of Single)
Static Value2 As New List(Of Single)
Static Value3 As New List(Of Single)
Static InPhase As New List(Of Single)
Static Quadrature As New List(Of Single)
Static Phase As New List(Of Single)
Static DeltaPhase As New List(Of Single)
Static InstPeriod As New List(Of Single)
Static Value4 As New List(Of Single)
Static Value5 As New List(Of Single)
Static Deg As Single
Static Count As Integer
If isFirstBar Then
Input.Clear
Value1.Clear
Value2.Clear
Value3.Clear
InPhase.Clear
Quadrature.Clear
Phase.Clear
DeltaPhase.Clear
InstPeriod.Clear
Value4.Clear
Value5.Clear
Deg = 180 / System.Math.Pi
End If
Input.Add((Price.High + Price.Low) / 2)
'Compute InPhase and Quadrature components
If Input.Count >= 7 Then
Value1.Add(Input(Input.Count - 1) - Input(Input.Count - 7))
End If
If Value1.Count >= 4 Then
Value2.Add(Value1(Value1.Count - 4))
End If
If Value1.Count >= 7 Then
Value3.Add(.75 * (Value1(Value1.Count - 1) - Value1(Value1.Count - 7)) _
+ .25 * (Value1(Value1.Count - 3) - Value1(Value1.Count - 5)))
End If
If Value2.Count >= 1 Then
If InPhase.Count >= 1 Then
InPhase.Add(.33 * Value2(Value2.Count - 1) + .67 * InPhase(InPhase.Count - 1))
Else
InPhase.Add(Value2(Value2.Count - 1))
End If
End If
If Value3.Count >= 1 Then
If Quadrature.Count >= 1 Then
Quadrature.Add(.2 * Value3(Value3.Count - 1) + _
.8 * Quadrature(Quadrature.Count - 1))
Else
Quadrature.Add(Value3(Value3.Count - 1))
End If
End If
'Use ArcTangent to compute the current phase
If InPhase.Count >= 2 AndAlso Quadrature.Count >= 2 AndAlso _
System.Math.Abs(InPhase(InPhase.Count - 1) + _
InPhase(InPhase.Count - 2)) > 0 Then
Phase.Add((System.Math.Atan((Quadrature(Quadrature.Count - 1) + _
Quadrature(Quadrature.Count - 2)) / _
(InPhase(InPhase.Count - 1) + InPhase(InPhase.Count - 2)))) * Deg)
End If
'Resolve the ArcTangent ambiguity
If Phase.Count >= 1 Then
If InPhase(InPhase.Count - 1) < 0 AndAlso _
Quadrature(Quadrature.Count - 1) > 0 Then
Phase(Phase.Count - 1) = 180 - Phase(Phase.Count - 1)
Else If InPhase(InPhase.Count - 1) < 0 AndAlso _
Quadrature(Quadrature.Count - 1) < 0 Then
Phase(Phase.Count - 1) = 180 + Phase(Phase.Count - 1)
Else If InPhase(InPhase.Count - 1) > 0 AndAlso _
Quadrature(Quadrature.Count - 1) < 0 Then
Phase(Phase.Count - 1) = 360 - Phase(Phase.Count - 1)
End If
End If
'Compute a differential phase, resolve phase wraparound, and limit delta phase errors
If Phase.Count >= 2 Then
DeltaPhase.Add(Phase(Phase.Count - 2) - Phase(Phase.Count - 1))
If Phase(Phase.Count - 2) < 90 AndAlso _
Phase(Phase.Count - 1) > 270 Then
DeltaPhase(DeltaPhase.Count - 1) = _
360 + Phase(Phase.Count - 2) - Phase(Phase.Count - 1)
End If
If DeltaPhase(DeltaPhase.Count - 1) < 1 Then
DeltaPhase(DeltaPhase.Count - 1) = 1
End If
If DeltaPhase(DeltaPhase.Count - 1) > 60 Then
DeltaPhase(DeltaPhase.Count - 1) = 60
End If
End If
'Sum DeltaPhases to reach 360 degrees. The sum is the instantaneous period.
If DeltaPhase.Count >= 41 Then
InstPeriod.Add(0)
Value4.Add(0)
For Count = 0 To 40
Value4(Value4.Count - 1) = Value4(Value4.Count - 1) + _
DeltaPhase(DeltaPhase.Count - 1 - Count)
If Value4(Value4.Count - 1) > 360 AndAlso _
InstPeriod(InstPeriod.Count - 1) = 0 Then
InstPeriod(InstPeriod.Count - 1) = Count
Exit For
End If
Next
End If
'Resolve Instantaneous Period errors and smooth
If InstPeriod.Count >= 2 Then
If InstPeriod(InstPeriod.Count - 1) = 0 Then
InstPeriod(InstPeriod.Count - 1) = InstPeriod(InstPeriod.Count - 2)
End If
Else If InstPeriod.Count = 1 AndAlso _
InstPeriod(InstPeriod.Count - 1) = 0 Then
InstPeriod.RemoveAt(0)
End If
If InstPeriod.Count >= 1 Then
If Value5.Count >= 1 Then
Value5.Add(.25 * InstPeriod(InstPeriod.Count - 1) + _
.75 * Value5(Value5.Count - 1))
Else
Value5.Add(InstPeriod(InstPeriod.Count - 1))
End If
End If
'Compute Dominant Cycle Phase, Sine of the Phase Angle, and Leadsine
If Value5.Count >= 1 Then
Dim Period As Integer = System.Math.Floor(Value5(Value5.Count - 1))
If Input.Count >= Period Then
Dim RealPart As Single = 0
Dim ImagPart As Single = 0
For Count = 0 To Period - 1
RealPart = RealPart + System.Math.Sin(360 * count / Period / Deg) * _
Input(Input.Count - 1 - Count)
ImagPart = ImagPart + System.Math.Cos(360 * count / Period / Deg) * _
Input(Input.Count - 1 - Count)
Next
Dim DCPhase As Single
If System.Math.Abs(ImagPart) > 0.001 Then
DCPhase = System.Math.Atan(RealPart / ImagPart) * Deg
Else
DCPhase = 90 * System.Math.Sign(RealPart)
End If
DCPhase = DCPhase + 90
If ImagPart < 0 Then
DCPhase = DCPhase + 180
End If
If DCPhase > 315 Then
DCPhase = DCPhase - 360
End If
OpenValue = System.Math.Sin((DCPhase + 45) / Deg)
HighValue = System.Math.Sin(DCPhase / Deg)
LowValue = System.Math.Sin(DCPhase / Deg)
Plot = System.Math.Sin(DCPhase / Deg)
Else
OpenValue = Single.NaN
HighValue = Single.NaN
LowValue = Single.NaN
Plot = Single.NaN
End If
Else
OpenValue = Single.NaN
HighValue = Single.NaN
LowValue = Single.NaN
Plot = Single.NaN
End If
-Bruce Personal Criteria Formulas TC2000 Support Articles
|
|
Registered User Joined: 10/7/2004 Posts: 816
|
Thanks Diceman and Bruce
This plots much more like the Metastock version ( different tho - because I think the metastock one doesn't calculate the dominant cycle phase but allows the user to change that value)
I added the lead sine which Ehler's indicates is the same logic except the plot being Sine(DCPhase + 45) which I think relates to Bruce's code System.Math.Sin((DCPhase + 45) / Deg)
I checked it against the sp-500 and it does seem to identify the cycle phase (some crossovers of leadsine vs sine) from mid-june 2010 thru mid august and then the trending phase ( few crossovers) from aug thru feb 2011.
Looks like my original version was the Picasso indicator and Diceman's is Rembrant.
Perhaps the ability to make other indicators adaptable to current market conditions ( i.e. using the dominant market cycle) is the most valuable result of this sinewave indicator.
Ehler's give examples of adaptive RSI, Stochastics and CCI.
In the case of the RSI the "only variable is the observation period" For maximum effectiveness he suggests an observation period of 1/2 the dominant cycle period - but suggests a user variable for fine tuning.
In his coding example he calculates "SmoothPeriod" and uses 1/2 that for the RSI calculation. but in the new code I've lost track of that. Is DCPhase the same thing - (sounds like it) and could we add the RSI adaptive version to the code.
Thanks Again
Regards
BobMc
|
|
Worden Trainer
Joined: 10/7/2004 Posts: 65,138
|
QUOTE (BobMc) Is DCPhase the same thing - (sounds like it) and could we add the RSI adaptive version to the code.
I have no idea.
-Bruce Personal Criteria Formulas TC2000 Support Articles
|
|
Registered User Joined: 10/7/2004 Posts: 816
|
Bruce,
I was able to create an indicator from your original code that I'm going to use as the dominant Cycle period (= smoothperiod). It plots fine as a positive single or double number.
I want to use it to control the iterations of another realcode indicator (via drag and drop ) with an adjustment thru a positive userinput variable (e.g. .5). Since the smoothperiod is not an integer and even if it was, the adjustment value could generate a value that is not an integer - I need to round it and create an integer. I was following a format used in your first code example -
Dim DCPeriod As Integer = System.Math.Floor(SmoothPeriod(0) + .5)
- keep getting compile error(s)
This is what I have which I thought was fairly straightforward
'# Cumulative
'# AdjValue = UserInput.single = .5
'# SP = chart.EhlersSmoothPeriod
Dim SP2 As Integer = System.Math.Floor(SP + .5) ' error on this line
For count = 0 To SP2
' RSI logic
Next
' plot rsi
I've tried a number of different things and that line is still a problem
The error message I get is - Operator '*' is not defined for types "wbi.commonblocks.scriptingLine" and double
When I add the userinput multiplier within the parens, the message becomes - Operator is not defined for types single and wbi.commonblocks.scriptingLine
I'd appreciate some more help here - with the loop. I believe I can get the rsi portion.
Thanks
BobMc
|
|
Worden Trainer
Joined: 10/7/2004 Posts: 65,138
|
Please try the following instead:
Dim SP2 As Integer = System.Math.Floor(SP.Value + .5)
-Bruce Personal Criteria Formulas TC2000 Support Articles
|
|
Registered User Joined: 10/7/2004 Posts: 816
|
Thanks Bruce,
I keep forgetting about the " .value" parameter
With your correction I'm able to plot SP2 as an integer
however when I try the looping with SP2
"For count = 0 To SP2.value
Next"
I get 2 errors - "loop control variable cannot be a property or a late bound indexed array"
and "value is not a member of integer"
if I make it just "For count = 0 To SP2" I get the "loop control" error message
Do I have to SP2 into another integer for the looping?
Regards
BobMc
|
|
Worden Trainer
Joined: 10/7/2004 Posts: 65,138
|
The following does not return any error messages for me (of course it doesn't actually do anything either):
'# Cumulative
'# AdjValue = UserInput.single = .5
'# SP = chart.EhlersSmoothPeriod
Dim SP2 As Integer = System.Math.Floor(SP.Value + .5)
For Count As Integer = 0 To SP2
Next
Please keep in mind that I am not a programmer.
-Bruce Personal Criteria Formulas TC2000 Support Articles
|
|
Registered User Joined: 10/7/2004 Posts: 816
|
Thanks Bruce
In one of my earlier tries I had count defined but somewhere along with my various tries apparently I nuked it.
Regards
BobMc
|
|
Worden Trainer
Joined: 10/7/2004 Posts: 65,138
|
You're welcome.
-Bruce Personal Criteria Formulas TC2000 Support Articles
|
|
Guest-1 |