Typ : Function, Name : HilbertPeriod
{ ----------------------------------------------------------
HilbertPeriod (Function) by John Ehlers (7/22/00)
This is the Hilbert Cycle Period Function used by the Hilbert
Channel Breakout System. It must be named "HilbertPeriod".
---------------------------------------------------------- }
Inputs: Price(numeric);
Vars: Smoother(0), Detrender(0), I1(0), Q1(0), jI(0), jQ(0), I2(0),Q2(0), X1(0),
X2(0), Y1(0), Y2(0), Re(0), Im(0), Period(0);
If CurrentBar >5 then begin
Smoother = (4*Price + 3*Price[1] + 2*Price[2] + Price[3])/10;
Detrender = (.25*Smoother + .75*Smoother[2] - .75*Smoother[4] -
.25*Smoother[6])*(.046*Period[1] + .332);
{Compute InPhase and Quadrature components}
Q1 = (.25*Detrender + .75*Detrender[2] - .75*Detrender[4] -
.25*Detrender[6])*(.046*Period[1] + .332);
I1 = Detrender[3];
{advance the phase of I1 and Q1 by 90 degrees}
jI = .25*I1 + .75*I1[2] - .75*I1[4] - .25*I1[6];
jQ = .25*Q1 + .75*Q1[2] - .75*Q1[4] - .25*Q1[6];
{Phasor addition to equalize amplitude due to quadrature calculations
(and 3 bar averaging)}
I2 = I1 - jQ;
Q2 = Q1 + jI;
{Smooth the I and Q components before applying the discriminator}
I2 = .15*I2 + .85*I2[1];
Q2 = .15*Q2 + .85*Q2[1];
{Homodyne Discriminator}
{Complex Conjugate Multiply}
X1 = I2*I2[1];
X2 = I2*Q2[1];
Y1 = Q2*Q2[1];
Y2 = Q2*I2[1];
Re = X1 + Y1;
Im = X2 - Y2;
{Smooth to remove undesired cross products}
Re = .2*Re + .8*Re[1];
Im = .2*Im + .8*Im[1];
{Compute Cycle Period}
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 < .67*Period[1] then Period = .67*Period[1];
If Period < 6 then Period = 6;
If Period > 50 then Period = 50;
Period = .2*Period + .8*Period[1];
{END CORE CODE}
HilbertPeriod = Period;
end;
Typ : Signal, Name : Hilbert Channel
{************************************************************
Hilbert_Channel (Signal)
This is the signal for the Hilbert Channel Breakout System.
If "EntryVal" or "ExitVal" have values greater than 0,
then
those values will be used for the entry / exit lookback
periods. If either input "EntryVal" or "ExitVal" is 0, then
the entry or exit lookback period will be the product of a
fractional constant times the cycle period, "EntryK*Period"
or "ExitK*Period."
Optimize for highest Total Net Profit / Return on Account:
1. Optimize EntryVal, and then ExitVal. (Optimum values are
often between 10 and 45.)
2. Change ExitVal to 0 and optimize ExitK. (Optimum value
is often between 1.5 and 4.5.)
3. Change EntryVal to 0 and optimize EntryK. (Optimum value
is often between .1 and 1.)
4. Repeat steps 2 and 3 until results of optimizing are
stable.
*********************************************************** }
inputs: Price((H + L)/2),
EntryVal(15),
EntryK(0),
ExitVal(15),
ExitK(0);
vars: Period(0),
count(0),
EntryLookBack(0),
ExitLookBack(0),
EntryChannel(0),
ExitChannel(0);
Period = HilbertPeriod(Price);
If EntryVal <> 0 then EntryLookBack = EntryVal else EntryLookBack = EntryK*Period;
if EntryLookBack < 1 then EntryLookBack = 1;
If ExitVal <> 0 then ExitLookBack = ExitVal else ExitLookBack = ExitK*Period;
if ExitLookBack < 1 then ExitLookBack = 1;
EntryChannel = 0;
for count = 1 to EntryLookBack begin
if EntryChannel < High[count] then EntryChannel = High[count];
end;
ExitChannel = 100000;
for count = 1 to ExitLookBack begin
if ExitChannel > Low[count] then ExitChannel = Low[count];
end;
If MarketPosition = 0 and High > EntryChannel then Buy;
If MarketPosition = 1 and Low < ExitChannel then ExitLong;
#BeginCmtry
var: textString(" flat.");
If CheckCommentary then BEGIN
if MarketPosition = 1 then textString = " long.";
if MarketPosition = 0 then textString = " flat.";
commentary("Market position is", textString, NewLine);
commentary("High is", high, ", channel", EntryChannel, ",
lookback",
ceiling(EntryLookBack), " bars.", NewLine);
commentary("Low is", low, ", channel", ExitChannel, ",
lookback",
ceiling(ExitLookBack), " bars.", NewLine);
End;
#End;