Download software Tutorial videos
Subscription & data-feed pricing Class schedule


New account application Trading resources
Margin rates Stock & option commissions

Attention: Discussion forums are read-only for extended maintenance until further notice.
Welcome Guest, please sign in to participate in a discussion. Search | Active Topics |

Ehler's Sinewave Indicator Rate this Topic:
Previous Topic · Next Topic Watch this topic · Print this topic ·
BobMc
Posted : Monday, February 14, 2011 5:36:12 PM
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
 
 
BobMc
Posted : Monday, February 14, 2011 5:45:41 PM
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

Bruce_L
Posted : Tuesday, February 15, 2011 6:28:17 PM


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
BobMc
Posted : Wednesday, February 16, 2011 12:48:56 PM
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

BobMc
Posted : Wednesday, February 16, 2011 6:40:55 PM
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


Bruce_L
Posted : Thursday, February 17, 2011 8:24:52 AM


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
BobMc
Posted : Thursday, February 17, 2011 12:20:12 PM
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 = 7If 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
Bruce_L
Posted : Thursday, February 17, 2011 12:28:17 PM


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
diceman
Posted : Thursday, February 17, 2011 7:27:44 PM
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

Bruce_L
Posted : Friday, February 18, 2011 12:39:52 PM


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
BobMc
Posted : Friday, February 18, 2011 2:37:11 PM
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

 
Bruce_L
Posted : Friday, February 18, 2011 2:54:49 PM


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
BobMc
Posted : Saturday, February 19, 2011 4:55:31 PM
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

Bruce_L
Posted : Monday, February 21, 2011 8:51:40 AM


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
BobMc
Posted : Monday, February 21, 2011 1:04:50 PM
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
Bruce_L
Posted : Monday, February 21, 2011 1:16:53 PM


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
BobMc
Posted : Monday, February 21, 2011 3:34:14 PM
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
Bruce_L
Posted : Monday, February 21, 2011 3:41:49 PM


Worden Trainer

Joined: 10/7/2004
Posts: 65,138
You're welcome.

-Bruce
Personal Criteria Formulas
TC2000 Support Articles
Users browsing this topic
Guest-1

Forum Jump
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.