double top or double bottem for tradestation?

Discussion in 'Trading Software' started by Gary186, Oct 24, 2017.

  1. Gary186

    Gary186

    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:)
     
  2. Gary186

    Gary186

  3. wrbtrader

    wrbtrader

  4. Gary186

    Gary186

    yes, It works. but I need add more code into it.
     
  5. mokwit

    mokwit

    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.
     
  6. Gary186

    Gary186

    @mokwit thank you. very valuable information. thanks again.
     
  7. mokwit

    mokwit

    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;
     
  8. xdsawzsecsq and Fonz like this.
  9. Fonz

    Fonz

    PoundTheRock likes this.