[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [amibroker] Ehlers Dominant Cycle



PureBytes Links

Trading Reference Links

Hi Andy,

In Rocket Science, Ehlers shows 3 methods to compute the cycle period. Then he tests them against each other and determines that the Homodyne Discriminator method had the the best characteristics of the 3, so he uses that code as a basis for the indicators that follow. The 3 yeilded fairly similar results, so when my graph looked wrong, I figured the code from the library should give me a rough idea of what mine should look like even though it is created through a different technique. I still think there is something wrong with mine, it should look much more like the other one. Maybe I will be able to just substitute your code for mine and build from there. Is the one in Cybernetics supposed to be better? I ordered that book too, but it got delayed and I just found out that it shipped today. Thanks for the code!

Steve
  ----- Original Message ----- 
  From: Andy Davidson 
  To: amibroker@xxxxxxxxxxxxxxx 
  Sent: Thursday, October 05, 2006 1:46 PM
  Subject: Re: [amibroker] Ehlers Dominant Cycle


  Steve,
  I think you're getting confused between Ehler's two books. As far as I recall (books not to hand right now) he makes the confusion easy as there is a "Dominant Cycle" indicator in both 'Rocket Science' and 'Cybernetic', which are based on different methods. Looks to me like the top one on your plot is the former and the bottom is the latter. I personally have used the latter...the code is copied below, which is probably nearly identical to the posted AFL library version as I used that as a starting point when I worked through it myself.
  Can't help you with the 'Rocket Science' version I'm afraid.
  Andy


  // Ehler's Dominant Cycle Period
  // Cybernetic Analysis for Stocks and Futures
  // Chapter 9, p. 107. Code on p. 111.

  //Global Parameters
  X = Param("MP[1] Close[2]",1,1,2,1); 
  Z1 = IIf(X==1, (H+L)/2 , C);
  Z2 = Param("Alpha", .07, .01, 1, .01);

  function CyclePeriod(price, alpha)
  {
   instperiod = deltaphase = cycle = period = 0;
   Cycle = ( price[2] - 2*price[1] + price[0] )/4;   //initialise arrays
   smooth = ( price + 2*Ref(price,-1) + 2*Ref(price,-2) + Ref(price,-3) )/6;
   
   for (i=6 ; i<BarCount ; i++)
    {  
     Cycle[i] = (1-alpha/2)^2 * ( smooth[i] - 2*smooth[i-1] + smooth[i-2] ) + 
                2*(1-alpha)*Cycle[i-1] - (1-alpha)^2*Cycle[i-2];

     Q1[i] = (.0962*cycle[i] + .5769*cycle[i-2] -.5769*cycle[i-4] - .0962*cycle[i-6])*(.5 + .08*InstPeriod[i-1]);
     I1[i] = cycle[i-3];

     if(Q1[i] != 0 AND Q1[i-1] != 0) 
     DeltaPhase[i] = (I1[i]/Q1[i] - I1[i-1]/Q1[i-1])/(1 + I1[i]*I1[i-1]/(Q1[i]*Q1[i-1]));
     //limit Delta Phase High/Low (0.09rads = 69bars, 1.1rads = 6bars...per page 117)
     if(DeltaPhase[i] < 0.09) 
      DeltaPhase[i] = 0.09;
     if(DeltaPhase[i] > 1.1) 
      DeltaPhase[i] = 1.1;
      
     //---Begin median calculation (placed inline for speed). 
     //Hardcoded as length=5 as higher values would be out of range due to start-up period in main loop
     for(k=4; k>=0; k--)  
      { temparray[k] = DeltaPhase[i-k]; } //create new array with last 5 values of DeltaPhase
     temp = 0;
     for(k=4; k>0; k--)  //this series of loops re-organises temparray into ascending order
     { for (j=4; j>0; j--)  
       { if (temparray[j-1] > temparray[j]) //swap values in array if previous value is greater
         { temp = temparray[j-1];
           temparray[j-1] = temparray[j];
           temparray[j] = temp;
     }}}
     MedianDelta[i] = temparray[2]; //returns the middle (third) element of temparray
     //---End median calculation

     DC[i] = Nz( 6.28318 / MedianDelta[i] + .5, 15 );

     InstPeriod[i] = .33*DC[i] + .67*InstPeriod[i-1];
     Period[i] = .15*InstPeriod[i] + .85*Period[i-1];
     }
   for (i=0; i<7; i++)
    { Period[i] = 1; }
   return Period;
  }

  Plot( CyclePeriod(Z1,Z2) , "CyberCycle", colorRed );



  Steve Dugas wrote: 
    Hi All,

    I wonder if anyone has ever tried to code Ehlers Dominant Cycle - the one based on the Homodyne Discriminator, pp. 68-69 in Rocket Science. I have never used TradeStation and this is my first shot at translating EasyLanguage. As far as I can see the code looks OK to me but what do I know? Anyway, the graph it produces ( middle one ) looks pretty bad. For comparison, I plotted the Dominant Cycle code from the AFL library on the bottom ( but I believe this uses a different method ).  I would like to go on and code the rest of the indicators in the book but many are built on this so I need to get this right first. Any thoughts or working code would be greatly appreciated. I have enclosed my code below.Thank you!

    Steve

    // Dominant Cycle

    SetBarsRequired( 10000, 10000 );

    // USER DEFINED PARAMS

    Price = ( High + Low ) / 2;

    // FORMULA

    // initialize variables

    Smooth = Detrender = I1 = Q1 = jI = jQ = I2 = Q2 = Re = Im = Period = SmoothPeriod = 0;

    // calculate dominant cycle period

    for ( i = 6; i < BarCount; i++ )

    {

    // smooth price data with 4-bar WMA

    Smooth[i] = ( 4 * Price[i] + 3 * Price[i-1] + 2 * Price[i-2] + Price[i-3] ) / 10;

    // compute amplitude correction

    AmpCorr[i] = 0.075 * Period[i-1] + 0.54;

    // compute detrended price data and Quadrature component with 7-bar Hilbert Transform

    Detrender[i] = ( 0.0962 * Smooth[i] + 0.5769 * Smooth[i-2] - 0.5769 * Smooth[i-4] - 0.0962 * Smooth[i-6] ) * AmpCorr[i];

    Q1[i] = ( 0.0962 * Detrender[i] + 0.5769 * Detrender[i-2] - 0.5769 * Detrender[i-4] - 0.0962 * Detrender[i-6] ) * AmpCorr[i];

    // compute InPhase component by referencing center bar of Hilbert Transformer ( 3 bars ago )

    I1[i] = Detrender[i-3];

    // advance the phase of I1 and Q1 by 90 degrees with 7-bar Hilbert Transform

    jI[i] = ( 0.0962 * I1[i] + 0.5769 * I1[i-2] - 0.5769 * I1[i-4] - 0.0962 * I1[i-6] ) * AmpCorr[i];

    jQ[i] = ( 0.0962 * Q1[i] + 0.5769 * Q1[i-2] - 0.5769 * Q1[i-4] - 0.0962 * Q1[i-6] ) * AmpCorr[i];

    // perform Phasor addition for 3-bar averaging

    I2[i] = I1[i] - jQ[i];

    Q2[i] = Q1[i] + jI[i];

    // smooth the I and Q components

    I2[i] = 0.2 * I2[i] + 0.8 * I2[i-1];

    Q2[i] = 0.2 * Q2[i] + 0.8 * Q2[i-1];

    // apply the Homodyne Discriminator

    Re[i] = I2[i] * I2[i-1] + Q2[i] * Q2[i-1];

    Im[i] = I2[i] * Q2[i-1] - Q2[i] * I2[i-1];

    // smooth the Re and Im components

    Re[i] = 0.2 * Re[i] + 0.8 * Re[i-1];

    Im[i] = 0.2 * Im[i] + 0.8 * Im[i-1];

    // compute Dominant Cycle period

    if ( Im[i] != 0 AND Re[i] != 0 )

    Period[i] = 360 / atan( Im[i] / Re[i] );

    // limit ROC of the cycle period to +/- 50% of previous cycle period

    if ( Period[i] > 1.5 * Period[i-1] )

    Period[i] = 1.5 * Period[i-1];

    if ( Period[i] < 0.67 * Period[i-1] )

    Period[i] = 0.67 * Period[i-1];

    // limit the cycle period to be > 6 or < 50

    if ( Period[i] < 6 )

    Period[i] = 6;

    if ( Period[i] > 50 )

    Period[i] = 50;

    // smooth the cycle period

    Period[i] = 0.2 * Period[i] + 0.8 * Period[i-1];

    SmoothPeriod[i] = 0.33 * Period[i] + 0.67 * SmoothPeriod[i-1];

    }

    Plot( SmoothPeriod, "Dominant Cycle", colorWhite, styleLine|styleOwnScale );

    //Plot( Re, "Re", colorBlue, styleLine|styleOwnScale );

    //Plot( Im, "Im", colorSkyblue, styleLine|styleOwnScale );

    //Plot( Im/Re, "Im/Re", colorDarkGreen, styleLine|styleOwnScale );

    //Plot( atan(Im/Re), "atan(Im/Re)", colorBrightGreen, styleLine|styleOwnScale );

    //Plot( Period, "Period", colorYellow, styleLine|styleOwnScale );



----------------------------------------------------------------------------