double top or double bottem for tradestation?

I want to write some code for picking up "double tops / double bottoms" in tradestation?
anybody can share some "double tops / double bottoms" code for me, thanks:-)
 
There is viable code for this in Mark Conway's Professional Stock Trading Book - he is very skilled at translating pattern recognition to code i.e. the essence of what a pattern really is for it to be coded. Another not so good in Pruitts Building Winning trading systems with TS. Try Googling Markos Katsanos to see if anything on his website.

Key point is don't try and get too geometrically/eyeball precise with the code - keep it slightly fuzzy - you have to code for the very essence of what a patter is and accept there will be many alerts for patterns that fit the code but not your expectations.
 
These might need some non library functions if so get back to me with name.
Conway double top
Inputs:
LookbackBars(20),
Strength(4),
RangeFactor(0.3),
MALength(50);

Variables:
DTBar(-1),
DTLine(-1),
AlertString("");

DTBar = AcmeDoubleTop(LookbackBars, Strength, RangeFactor);
If DTBar <> -1 Then Begin
DTLine = TL_New(Date[0], Time[0], High, Date[DTBar], Time[DTBar], High);
If DTLine >= 0 Then Begin
TL_SetColor(DTLine, Magenta);
TL_SetSize(DTLine, 1);
End;
AlertString = "Acme Double Top";
If DMIPlus(LookbackBars) > DMIMinus(LookbackBars) Then
Condition1 = AbsValue(Low - Average(Close, MALength)) <= RangeFactor * Volatility(LookbackBars)
Else If DMIPlus(LookbackBars) < DMIMinus(LookbackBars) Then
Condition1 = AbsValue(High - Average(Close, MALength)) <= RangeFactor * Volatility(LookbackBars);
If Condition1 Then
AlertString = AlertString + " Near " + NumToStr(MALength, 0) + " Bar Moving Average";
If AlertEnabled or Condition1 Then
Alert(AlertString);
End;

=======================================================

conway double bottom
Inputs:
LookbackBars(20),
Strength(4),
RangeFactor(0.3),
MALength(50);

Variables:
DBBar(-1),
DBLine(-1),
AlertString("");

DBBar = AcmeDoubleBottom(LookbackBars, Strength, RangeFactor);
If DBBar <> -1 Then Begin
DBLine = TL_New(Date[0], Time[0], Low, Date[DBBar], Time[DBBar], Low);
If DBLine >= 0 Then Begin
TL_SetColor(DBLine, Magenta);
TL_SetSize(DBLine, 1);
End;
AlertString = "Acme Double Bottom";
If DMIPlus(LookbackBars) > DMIMinus(LookbackBars) Then
Condition1 = AbsValue(Low - Average(Close, MALength)) <= RangeFactor * Volatility(LookbackBars)
Else If DMIPlus(LookbackBars) < DMIMinus(LookbackBars) Then
Condition1 = AbsValue(High - Average(Close, MALength)) <= RangeFactor * Volatility(LookbackBars);
If Condition1 Then
AlertString = AlertString + " Near " + NumToStr(MALength, 0) + " Bar Moving Average";
If AlertEnabled or Condition1 Then
Alert(AlertString);
End;
=====================================================

Pruitt Dbl btm
Vars: state(0),tenDayATR(0),barCount(0),firstLowPivot(0);
Vars: secLowPivot(0),firstLowPivotPos(0),secLowPivotPos(0);

tenDayATR= AvgTrueRange(10);
if(Low[1] =Lowest(Low[1],20) and
state = 0 and Low > Low[1]) then
begin
state = 1;
barCount = 0;
firstLowPivot = Low[1];
firstLowPivotPos = barNumber;
end;
if(state = 1) then
begin
barCount = barCount + 1;
if(High[1] = Highest(High[1],5) and
High < High[1]) then
begin
state = 2;
barCount = barCount - 1; {subtract one bar - we will add one in state 2}
end;
if(Low < firstLowPivot) then state = 0;
end;
if(state = 2)then
begin
barcount = barCount + 1;
if(barCount > 30) then state = 0; {pattern not completed within 30 bars}
if(Low[2]>Low[1] and
Low > Low[1] and
(Low[1] < firstLowPivot + tenDayATR and
Low[1] > firstLowPivot - tenDayATR)) then
begin
state = 3;
secLowPivot = Low[1];
secLowPivotPos = barNumber;
barCount = barCount - 1;
end;
end;
if(state = 3) then
begin
barCount = barCount + 1;
if(barCount > 30) then state = 0;
if(High > secLowPivot + 2*tenDayAtr) then state = 4;
if(Low < secLowPivot) then state = 0;
end;
if(state = 4) then
begin
Plot1[BarNumber - firstLowPivotPos+1](firstLowPivot,"DoubleBottom");
Plot2[BarNumber - secLowPivotPos+1](secLowPivot,"DoubleBottom");
state = 0; {Job is done - start over}
end;

===================================================
Pruitt dbl top (maybe I did the reversal on this)
Vars: state(0),tenDayATR(0),barCount(0),firstLowPivot(0);
Vars: secLowPivot(0),firstLowPivotPos(0),secLowPivotPos(0);

tenDayATR= AvgTrueRange(10);
if(Low[1] =Lowest(Low[1],20) and
state = 0 and Low > Low[1]) then
begin
state = 1;
barCount = 0;
firstLowPivot = Low[1];
firstLowPivotPos = barNumber;
end;
if(state = 1) then
begin
barCount = barCount + 1;
if(High[1] = Highest(High[1],5) and
High < High[1]) then
begin
state = 2;
barCount = barCount - 1; {subtract one bar - we will add one in state 2}
end;
if(Low < firstLowPivot) then state = 0;
end;
if(state = 2)then
begin
barcount = barCount + 1;
if(barCount > 30) then state = 0; {pattern not completed within 30 bars}
if(Low[2]>Low[1] and
Low > Low[1] and
(Low[1] < firstLowPivot + tenDayATR and
Low[1] > firstLowPivot - tenDayATR)) then
begin
state = 3;
secLowPivot = Low[1];
secLowPivotPos = barNumber;
barCount = barCount - 1;
end;
end;
if(state = 3) then
begin
barCount = barCount + 1;
if(barCount > 30) then state = 0;
if(High > secLowPivot + 2*tenDayAtr) then state = 4;
if(Low < secLowPivot) then state = 0;
end;
if(state = 4) then
begin
Plot1[BarNumber - firstLowPivotPos+1](firstLowPivot,"DoubleBottom");
Plot2[BarNumber - secLowPivotPos+1](secLowPivot,"DoubleBottom");
state = 0; {Job is done - start over}
end;
=====================================================

Misc DBL bottom (don't think I ever tested this)
Inputs:
Length(100),
MinStrength(3),
MaxStrength(10),
NoticeBar(2),
MinPctRunToBottom(20),
NeckLineBreak(1),
ThinFan(1),
BottomColor(Blue);

variables:
msg(""), ret_val(0), indicator_name("WBottom"), MySwingStrength(0), FoundIt(false),
MyBottomColor(0);

Variables:
F1(0.618),
F2(0.786),
F3(1.27),
F4(1.618),
P1Bar(-1), { Peak Bar 1 }
P2Bar(-1), { Peak Bar 2 }
T1Bar(-1), { Trough Bar 1 }
T2Bar(-1), { Trough Bar 2 }
P1(0.0),
P2(0.0),
T1(0.0),
T2(0.0),
PTValid(False),
HLValid(False),
InZone(False),
GD(0.0),
XA(0.0),
AB(0.0),
BC(0.0),
CD(0.0),
AD(0.0),
C1(False),
C2(False),
C3(False),
C4(False),
ABdXA(0.0),
BCdAB(0.0),
CDdBC(0.0),
ADdXA(0.0),
TL1(-1),
TL2(-1),
TL3(-1),
TL4(-1),
TL5(-1),
TL6(-1),
TLsize(1);

{ Find 2 swing highs and 2 swing lows (i.e. peak bars and trough bars). Note that we
allow for the strength of the most recent swing to be different so that "early
detection" can be dialed in. In a "W" bottom, the time order of the peaks and
troughs will be: P2 T2 P1 T1
}
FoundIt = False;

for MySwingStrength = MaxStrength downto MinStrength begin

{MyBottomColor = MySwingStrength + 6;} { add 6 to get past both green and red for contrast }
MyBottomColor = MySwingStrength ;
T1Bar = -1 ;

P1Bar = SwingHighBar(1, High, MySwingStrength, Length); { most recent swing high }
P2Bar = SwingHighBar(2, High, MySwingStrength, Length); { 2nd most recent swing high }
{T1Bar = SwingLowBar(1, Low, MySwingStrength, Length); { most recent swing low }}
Value1 = Pivot( Low, Length, MySwingStrength, NoticeBar, 1, -1, T1, T1Bar ) ;
T2Bar = SwingLowBar(1, Low, MySwingStrength, Length)[T1Bar]; { 2nd most recent swing low }

If P1Bar <> -1 and
P2Bar <> -1 and
T1Bar <> -1 and
T2Bar <> -1 Then Begin

{ Test for "W" bottom }
T2 = Low[T2Bar];
P2 = High[P2Bar];
T1 = Low[T1Bar];
P1 = High[P1Bar];

GD = High;
{ verify peak-trough-peak-trough sequence that forms a "W" }
PTValid = T1Bar < P1Bar and P1Bar < T2Bar and T2Bar < P2Bar;
{ verify 2nd peak below first, and 2nd trough above first }
HLValid = T1 > T2 and P1 < P2 and T1 < P1;

{InZone = GD > P1 and GD < P2 and T2 <= Lowest(Low, P2Bar);}
{ verify T2 was the lowest point in the formation, and rise from T1 has begun }
InZone = GD > T1 and GD < P2 and T2 <= Lowest(Low, P2Bar);
{ verify minimum percentage run to bottom }
InZone = InZone and T2 < (P2 - PercentOf(P2,MinPctRunToBottom)) ;
if NeckLineBreak = 1 then InZone = InZone and close > P1 ;
if ThinFan = 1 then InZone = InZone and close > close[1] ;

If PTValid and HLValid and InZone Then Begin
{msg = "W hit" + " MySwingStrength: " + NumToStr(MySwingStrength,0) + " T1Bar: " + NumToStr(T1Bar,0) ;
ret_val = SBJ_pmsg( indicator_name, msg);}

if NeckLineBreak = 1 then Alert("W bottom complete");

XA = P2 - T2;
AB = P1 - T2;
BC = P1 - T1;
CD = GD - T1;
AD = GD - T2;

{ This commented out code is from the Gartley 222, and shows one way of performing
further analysis on a "W" }
{
ABdXA = AB / XA; {AB should be 61.8% of XA}
C1 = ABdXA > F1 - Tolerance and ABdXA < F1 + Tolerance;
BCdAB = BC / AB; {BC should be 61.8-78.6% of AB}
C2 = BCdAB > F1 - Tolerance and BCdAB < F2 + Tolerance;
CDdBC = CD / BC; {CD should be 127-161.8% of BC}
C3 = CDdBC > F3 - Tolerance and CDdBC < F4 + Tolerance;
ADdXA = AD / XA; {AD should be 78.6% of XA}
C4 = ADdXA > F2 - Tolerance and ADdXA < F2 + Tolerance;
}

{ if the proportions are correct, to within Tolerance, plot the formation }
{If C1 and C2 and C3 and C4 Then Begin}
If True Then Begin
TL1 = TL_New(Date[P2Bar], Time[P2Bar], P2, Date[T2Bar], Time[T2Bar], T2);
If TL1 >= 0 Then Begin
TL_SetColor(TL1, MyBottomColor);
TL_SetStyle(TL1, Tool_Solid);
TL_SetSize(TL1, TLsize);
End;
TL2 = TL_New(Date[T2Bar], Time[T2Bar], T2, Date[P1Bar], Time[P1Bar], P1);
If TL2 >= 0 Then Begin
TL_SetColor(TL2, MyBottomColor);
TL_SetStyle(TL2, Tool_Solid);
TL_SetSize(TL2, TLsize);
End;
TL3 = TL_New(Date[P1Bar], Time[P1Bar], P1, Date[T1Bar], Time[T1Bar], T1);
If TL3 >= 0 Then Begin
TL_SetColor(TL3, MyBottomColor);
TL_SetStyle(TL3, Tool_Solid);
TL_SetSize(TL3, TLsize);
End;
TL4 = TL_New(Date[T1Bar], Time[T1Bar], T1, Date, Time, GD);
If TL4 >= 0 Then Begin
TL_SetColor(TL4, MyBottomColor);
TL_SetStyle(TL4, Tool_Dotted);
TL_SetSize(TL4, TLsize);
End;

End;
End;
End;
End;

======================================================
Misc DBL Top
Inputs:
Length(100),
MinStrength(3),
MaxStrength(10),
NoticeBar(2),
MinPctRunToTop(50),
NeckLineBreak(1),
ThinFan(1),
TopColor(Red);

variables:
msg(""), ret_val(0), indicator_name("MTop"), MySwingStrength(0), FoundIt(false),
MyTopColor(0);

Variables:
F1(0.618),
F2(0.786),
F3(1.27),
F4(1.618),
P1Bar(-1), { Peak Bar 1 }
P2Bar(-1), { Peak Bar 2 }
T1Bar(-1), { Trough Bar 1 }
T2Bar(-1), { Trough Bar 2 }
P1(0.0),
P2(0.0),
T1(0.0),
T2(0.0),
PTValid(False),
HLValid(False),
InZone(False),
GD(0.0),
XA(0.0),
AB(0.0),
BC(0.0),
CD(0.0),
AD(0.0),
C1(False),
C2(False),
C3(False),
C4(False),
ABdXA(0.0),
BCdAB(0.0),
CDdBC(0.0),
ADdXA(0.0),
TL1(-1),
TL2(-1),
TL3(-1),
TL4(-1),
TL5(-1),
TL6(-1),
TLsize(1);

{ Find 2 swing highs and 2 swing lows (i.e. peak bars and trough bars). Note that we
allow for the strength of the most recent swing to be different so that "early
detection" can be dialed in. In an "M" top the time order of peaks and troughs will
be: T2 P2 T1 P1 .}

FoundIt = False;

{for MySwingStrength = MinStrength to MaxStrength begin}
for MySwingStrength = MaxStrength downto MinStrength begin

{MyTopColor = MySwingStrength + 6;} { add 6 to get past both green and red for contrast }
MyTopColor = mod(MySwingStrength,16) ; { modulo needed to accomodate very large SwingStrengths }

{P1Bar = SwingHighBar(1, High, MySwingStrength, Length); { most recent swing high }}
Value1 = Pivot( High, Length, MySwingStrength, NoticeBar, 1, 1, P1, P1Bar ) ;
P2Bar = SwingHighBar(1, High, MySwingStrength, Length)[P1Bar]; { 2nd most recent swing high }
T1Bar = SwingLowBar(1, Low, MySwingStrength, Length); { most recent swing low }
T2Bar = SwingLowBar(2, Low, MySwingStrength, Length); { 2nd most recent swing low }

If P1Bar <> -1 and
P2Bar <> -1 and
T1Bar <> -1 and
T2Bar <> -1 Then Begin

{ Test for "M" top }
T2 = Low[T2Bar];
P2 = High[P2Bar];
T1 = Low[T1Bar];
P1 = High[P1Bar];

GD = Low;
{ verify trough-peak-trough-peak sequence that forms an "M" }
PTValid = P1Bar < T1Bar and T1Bar < P2Bar and P2Bar < T2Bar;
{ verify 2nd peak below first, and 2nd trough above first }
HLValid = P1 < P2 and T1 > T2 and P1 > T1;

{InZone = GD < T1 and GD > T2 and P2 >= Highest(High, T2Bar);}
{ verify P2 was the highest point in the formation, and decline from P1 has begun }
InZone = GD < P1 and GD > T2 and P2 >= Highest(High, T2Bar);
{ verify minimum percentage run to top }
InZone = InZone and P2 > (T2 + PercentOf(T2,MinPctRunToTop)) ;
{ verify move below neckline }
if NeckLineBreak = 1 then InZone = InZone and close < T1 ;
if ThinFan = 1 then InZone = InZone and close < close[1] ;

If PTValid and HLValid and InZone Then Begin
FoundIt = True;

if NeckLineBreak = 1 then Alert("M Top complete");

XA = P2 - T2;
AB = P2 - T1;
BC = P1 - T1;
CD = P1 - GD;
AD = P2 - GD;

{ This commented out code is from the Gartley 222, and shows one way of performing
further analysis on an "M" }
{
ABdXA = AB / XA; {AB should be 61.8% of XA}
C1 = ABdXA > F1 - Tolerance and ABdXA < F1 + Tolerance;
BCdAB = BC / AB; {BC should be 61.8-78.6% of AB}
C2 = BCdAB > F1 - Tolerance and BCdAB < F2 + Tolerance;
CDdBC = CD / BC; {CD should be 127-161.8% of BC}
C3 = CDdBC > F3 - Tolerance and CDdBC < F4 + Tolerance;
ADdXA = AD / XA; {AD should be 78.6% of XA}
C4 = ADdXA > F2 - Tolerance and ADdXA < F2 + Tolerance;
}

{ if the proportions are correct, to within Tolerance, plot the formation }
{If C1 and C2 and C3 and C4 Then Begin}
If True Then Begin
TL1 = TL_New(Date[T2Bar], Time[T2Bar], T2, Date[P2Bar], Time[P2Bar], P2);
If TL1 >= 0 Then Begin
TL_SetColor(TL1, MyTopColor);
TL_SetStyle(TL1, Tool_Solid);
TL_SetSize(TL1, TLsize);
End;
TL2 = TL_New(Date[P2Bar], Time[P2Bar], P2, Date[T1Bar], Time[T1Bar], T1);
If TL2 >= 0 Then Begin
TL_SetColor(TL2, MyTopColor);
TL_SetStyle(TL2, Tool_Solid);
TL_SetSize(TL2, TLsize);

if MinStrength = MaxStrength then begin
Value1 = Text_New(Date[P2Bar], Time[P2Bar], low[P2Bar], NumToStr(MySwingStrength,0)) ;
Text_SetColor(value1, MyTopColor);
end;
End;
TL3 = TL_New(Date[T1Bar], Time[T1Bar], T1, Date[P1Bar], Time[P1Bar], P1);
If TL3 >= 0 Then Begin
TL_SetColor(TL3, MyTopColor);
TL_SetStyle(TL3, Tool_Solid);
TL_SetSize(TL3, TLsize);
End;
TL4 = TL_New(Date[P1Bar], Time[P1Bar], P1, Date, Time, GD);
If TL4 >= 0 Then Begin
TL_SetColor(TL4, MyTopColor);
TL_SetStyle(TL4, Tool_Solid);
TL_SetSize(TL4, TLsize);
End;

End;
End;
End;

{if FoundIt then MySwingStrength = 0 ; } { found the pattern, we're done }
End;
 
Back
Top