Stock Portfolio Organizer
The ultimate porfolio management solution.
WiseTrader Toolbox
#1 Selling Amibroker Plugin featuring:
HARMONIC PATTERN DETECTION using ATR type Peaks and Troughs for Amibroker (AFL)
/* HARMONIC PATTERN DETECTION using ATR type Peaks and Troughs
Automatic Detection of Harmonic Patterns – Gartley, Bat, Butterfly and Crab.
Original code by joy.edakad@gmail.com, see:
http://www.inditraders.com/amibroker/1934-afl-harmonic-patterns.html
file: Harmonic1.1.afl (2009)
Modernized by E.M.Pottasch (Dec 2016).
- Using ATR based pivots instead of fractal based
- Improved visualisation of the patterns.
- Nomenclature of variables, constants and arrays, adjusted
following code from David Keleher.
- uncompleted pivots given white color
- multiple issues of the original code corrected for
The original code was based on “fractal type pivots”, this
code uses “ATR type pivots”. This code also includes a time
frame factor. To fully understand how to interpret a pattern
use the Amibroker playback utility and see how the patterns
develop. */
Screenshots
Indicator / Formula
/* HARMONIC PATTERN DETECTION using ATR type Peaks and Troughs Automatic Detection of Harmonic Patterns - Gartley, Bat, Butterfly and Crab. Original code by joy.edakad@gmail.com, see: http://www.inditraders.com/amibroker/1934-afl-harmonic-patterns.html file: Harmonic1.1.afl (2009) Modernized by E.M.Pottasch (Dec 2016). - Using ATR based pivots instead of fractal based - Improved visualisation of the patterns. - Nomenclature of variables, constants and arrays, adjusted following code from David Keleher. - uncompleted pivots given white color - multiple issues of the original code corrected for The original code was based on "fractal type pivots", this code uses "ATR type pivots". This code also includes a time frame factor. To fully understand how to interpret a pattern use the Amibroker playback utility and see how the patterns develop. */ Version( 6.0 ); GfxSetCoordsMode( 1 ); GfxSetOverlayMode( 1 ); BullBat4 = BullButterfly4 = BullCrab4 = BullGartley4 = 0; BullBat = BullButterfly = BullCrab = BullGartley = 0; BearBat4 = BearButterfly4 = BearCrab4 = BearGartley4 = 0; BearBat = BearButterfly = BearCrab = BearGartley = 0; pk = tr = pkn = trn = 0; bi = BarIndex(); fvb = FirstVisibleValue( bi ); lvb = LastVisibleValue( bi ); GraphXSpace = 5; SetChartBkColor( colorBlack ); SetChartOptions( 1, chartShowDates, chartGridMiddle, 0, 0, 0 ); SetBarFillColor( IIf( C > O, ColorRGB( 0, 75, 0 ), IIf( C <= O, ColorRGB( 75, 0, 0 ), colorLightGrey ) ) ); Plot( C, "", IIf( C > O, ColorRGB( 0, 255, 0 ), IIf( C <= O, ColorRGB( 255, 0, 0 ), colorLightGrey ) ), 64, Null, Null, 0, 0, 1 ); _SECTION_BEGIN( "Patterns" ); perBull = Param( "Bullish ATR Period", 20, 1, 150, 1 ); perBear = Param( "Bearish ATR Period", 20, 1, 150, 1 ); multBull = Param( "Bullish ATR Multiple", 2, 1, 4, 0.05 ); multBear = Param( "Bearish ATR Multiple", 2, 1, 4, 0.05 ); trailValueClose = ParamToggle( "Trail value", "High/Low|Close", 1 ); //tfrm = in1Minute * Param( "Time Frame (min)", 5, 1, 1440 * 10, 1 ); // 1440 minutes is 1 day tfrm = in1Minute * Interval() / 60 * Param( "Chart Time Frame Factor", 1, 1, 10, 1 ); // factor 1 uses timeframe of chart showATRPivots = ParamToggle( "Show ATR Pivots", "Off|On", 0 ); showLabels = ParamToggle( "Show ATR Pivot Labels", "Off|On", 0 ); bu = ParamToggle( "Show Bullish Pattern", "Off|On", 1 ); be = ParamToggle( "Show Bearish Pattern", "Off|On", 1 ); nBull = Param( "Max Number of Bullish Patterns", 10, 0, 100, 1 ); nBear = Param( "Max Number of Bearish Patterns", 10, 0, 100, 1 ); dBat = ParamToggle( "Draw Bat", "Off|On", 1 ); dBut = ParamToggle( "Draw Buterfly", "Off|On", 1 ); dCrab = ParamToggle( "Draw Crab", "Off|On", 1 ); dGart = ParamToggle( "Draw Gartley", "Off|On", 1 ); showPatternDevelopmentPoints = ParamToggle( "Show Points of Pattern Development", "Off|On", 1 ); showPatternLabels = ParamToggle( "Show Pattern Labels", "Off|On", 0 ); showPatternName = ParamToggle( "Show Pattern Name", "Off|On", 1 ); _SECTION_END(); _SECTION_BEGIN( "Gartley" ); GBmin = Param( "Swing B Min.", 0.55, 0.3, 1, 0.01 ); GBmax = Param( "Swing B Max.", 0.72, 0.4, 1, 0.01 ); GCmin = Param( "Swing C Min.", 0.38, 0.3, 1.27, 0.01 ); GCmax = Param( "Swing C Max.", 1.0, 0.4, 1.27, 0.01 ); GDmin = Param( "Swing D Min.(XA)", 0.55, 0.3, 1, 0.01 ); GDmax = Param( "Swing D Max.(XA)", 1.0, 0.4, 1.0, 0.01 ); _SECTION_END(); _SECTION_BEGIN( "Bat" ); BatBmin = Param( "Swing B Min.", 0.38, 0.3, 1, 0.01 ); BatBmax = Param( "Swing B Max.", 0.55, 0.4, 1, 0.01 ); BatCmin = Param( "Swing C Min.", 0.38, 0.3, 1.62, 0.01 ); BatCmax = Param( "Swing C Max.", 1.27, 0.4, 1.62, 0.01 ); BatDmin = Param( "Swing D Min.(XA)", 0.5, 0.3, 1, 0.01 ); BatDmax = Param( "Swing D Max.(XA)", 1.0, 0.4, 1.0, 0.01 ); _SECTION_END(); _SECTION_BEGIN( "Butterfly" ); BtBmin = Param( "Swing B Min.", 0.55, 0.3, 1, 0.01 ); BtBmax = Param( "Swing B Max.", 0.9, 0.4, 1, 0.01 ); BtCmin = Param( "Swing C Min.", 0.38, 0.3, 1.62, 0.01 ); BtCmax = Param( "Swing C Max.", 1.27, 0.4, 1.62, 0.01 ); BtDmin = Param( "Swing D Min.(XA)", 1, 1, 1.8, 0.01 ); BtDmax = Param( "Swing D Max.(XA)", 1.38, 1, 1.8, 0.01 ); _SECTION_END(); _SECTION_BEGIN( "Crab" ); CBmin = Param( "Swing B Min.", 0.38, 0.3, 1, 0.01 ); CBmax = Param( "Swing B Max.", 0.65, 0.4, 1, 0.01 ); CCmin = Param( "Swing C Min.", 0.38, 0.3, 1.62, 0.01 ); CCmax = Param( "Swing C Max.", 1.270, 0.4, 1.62, 0.01 ); CDmin = Param( "Swing D Min.(XA)", 1.25, 1, 1.8, 0.01 ); CDmax = Param( "Swing D Max.(XA)", 1.8, 1, 2, 0.01 ); _SECTION_END(); function ATRtrail_func() { // Trail code largely from: // http://traders.com/Documentation/FEEDbk_docs/2009/06/TradersTips.html if( trailValueClose ) { tvHigh = C; tvLow = C; } else { tvHigh = H; tvLow = L; } sup = tvHigh - multBull * ATR( perBull ); res = tvLow + multBear * ATR( perBear ); trailARRAY = Null; trailstop = 0; for( i = 1; i < BarCount; i++ ) { if( C[ i ] > trailstop AND C[ i - 1 ] > trailstop ) trailstop = Max( trailstop, sup[ i ] ); else if( C[ i ] < trailstop AND C[ i - 1 ] < trailstop ) trailstop = Min( trailstop, res[ i ] ); else trailstop = IIf( C[ i ] > trailstop, sup[ i ], res[ i ] ); trailARRAY[ i ] = trailstop; } return trailARRAY; } TimeFrameSet( tfrm ); trBull = multBull * ATR( perBull ); trBear = multBear * ATR( perBear ); trailArray = ATRtrail_func(); ts = IIf( trailArray > C, trailArray, Null ); // dntrend tl = IIf( trailArray < C, trailArray, Null ); // uptrend TimeFrameRestore(); ts = TimeFrameExpand( ts, tfrm, expandlast ); tl = TimeFrameExpand( tl, tfrm, expandlast ); lll = LLV( L, BarsSince( !IsEmpty( tl ) ) ); lll = IIf( ts, lll, Null ); trn = ts AND L == lll; hhh = HHV( H, BarsSince( !IsEmpty( ts ) ) ); hhh = IIf( tl, hhh, Null ); pkn = tl AND H == hhh; tr = ExRem( Reverse( trn ), Reverse( pkn ) ); pk = ExRem( Reverse( pkn ), Reverse( trn ) ); tr = Reverse( tr ); pk = Reverse( pk ); for( i = 0; i < 3; i++ ) { VarSet( "px" + i, ValueWhen( pk, bi, i ) ); VarSet( "tx" + i, ValueWhen( tr, bi, i ) ); VarSet( "ph" + i, ValueWhen( pk, H, i ) ); VarSet( "tl" + i, ValueWhen( tr, L, i ) ); } ll = tr AND tl1 < tl2; hl = tr AND tl1 > tl2; hh = pk AND ph1 > ph2; lh = pk AND ph1 < ph2; dt = pk AND ph1 == ph2; db = tr AND tl1 == tl2; if( showATRPivots ) { PlotShapes( shapeSmallCircle * tr, IIf( tx1 < px0, ColorRGB( 0, 0, 255 ), colorWhite ), 0, L, -10 ); PlotShapes( shapeSmallCircle * pk, IIf( px1 < tx0, ColorRGB( 255, 0, 0 ), colorWhite ), 0, H, 10 ); } // +++ Bullish Patterns PTvalid = ( px1 > tx1 AND tx1 > px2 AND px2 > tx2 ) AND pk; if( dGart AND bu ) { BullGartley4 = PTvalid AND( ph2 - tl1 ) / ( ph2 - tl2 ) > GBmin AND( ph2 - tl1 ) / ( ph2 - tl2 ) < GBmax AND( ph1 - tl1 ) / ( ph2 - tl1 ) > GCMin AND( ph1 - tl1 ) / ( ph2 - tl1 ) < GCMax; BullGartley = IIf( Nz( LowestSince( BullGartley4, L ) ) < Nz( ValueWhen( BullGartley4, ph2 ) ) - ( Nz( ValueWhen( BullGartley4, ph2 ) ) - Nz( ValueWhen( BullGartley4, tl2 ) ) ) * GDmin AND Nz( LowestSince( bullGartley4, L ) ) > Nz( ValueWhen( BullGartley4, ph2 ) ) - ( Nz( ValueWhen( BullGartley4, ph2 ) ) - Nz( ValueWhen( BullGartley4, tl2 ) ) ) * GDmax AND Nz( HighestSince( BullGartley4, H ) ) <= Nz( ValueWhen( BullGartley4, ph1 ) ) AND Nz( LowestSince( BullGartley4, L ) ) < Nz( ValueWhen( BullGartley4, tl1 ) ) AND Nz( trn ) AND Nz( LowestSince( bullGartley4, L ) ) == L, True, False ); } if( dBat AND bu ) { BullBat4 = PTvalid AND( ph2 - tl1 ) / ( ph2 - tl2 ) > BatBmin AND( ph2 - tl1 ) / ( ph2 - tl2 ) < BatBmax AND( ph1 - tl1 ) / ( ph2 - tl1 ) > BatCMin AND( ph1 - tl1 ) / ( ph2 - tl1 ) < BatCMax; BullBat = IIf( Nz( LowestSince( BullBat4, L ) ) < Nz( ValueWhen( BullBat4, ph2 ) ) - ( Nz( ValueWhen( BullBat4, ph2 ) ) - Nz( ValueWhen( BullBat4, tl2 ) ) ) * BatDmin AND Nz( LowestSince( BullBat4, L ) ) > Nz( ValueWhen( BullBat4, ph2 ) ) - ( Nz( ValueWhen( BullBat4, ph2 ) ) - Nz( ValueWhen( BullBat4, tl2 ) ) ) * BatDmax AND Nz( HighestSince( BullBat4, H ) ) <= Nz( ValueWhen( BullBat4, ph1 ) ) AND Nz( LowestSince( BullBat4, L ) ) < Nz( ValueWhen( BullBat4, tl1 ) ) AND Nz( trn ) AND Nz( LowestSince( BullBat4, L ) ) == L, True, False ); } if( dBut AND bu ) { BullButterfly4 = PTvalid AND( ph2 - tl1 ) / ( ph2 - tl2 ) > BtBmin AND( ph2 - tl1 ) / ( ph2 - tl2 ) < BtBMax AND( ph1 - tl1 ) / ( ph2 - tl1 ) > BtCmin AND( ph1 - tl1 ) / ( ph2 - tl1 ) < BtCmax; BullButterfly = IIf( Nz( LowestSince( BullButterfly4, L ) ) < Nz( ValueWhen( BullButterfly4, ph2 ) ) - ( Nz( ValueWhen( BullButterfly4, ph2 ) ) - Nz( ValueWhen( BullButterfly4, tl2 ) ) ) * BtDMin AND Nz( LowestSince( BullButterfly4, L ) ) > Nz( ValueWhen( BullButterfly4, ph2 ) ) - ( Nz( ValueWhen( BullButterfly4, ph2 ) ) - Nz( ValueWhen( BullButterfly4, tl2 ) ) ) * BtDmax AND Nz( HighestSince( BullButterfly4, H ) ) <= Nz( ValueWhen( BullButterfly4, ph1 ) ) AND Nz( LowestSince( BullButterfly4, L ) ) < Nz( ValueWhen( BullButterfly4, tl2 ) ) AND Nz( trn ) AND Nz( LowestSince( bullButterfly4, L ) ) == L, True, False ); } if( dCrab AND bu ) { BullCrab4 = PTvalid AND( ph2 - tl1 ) / ( ph2 - tl2 ) > CBmin AND( ph2 - tl1 ) / ( ph2 - tl2 ) < CBmax AND( ph1 - tl1 ) / ( ph2 - tl1 ) > CCmin AND( ph1 - tl1 ) / ( ph2 - tl1 ) < CCmax; BullCrab = IIf( Nz( LowestSince( BullCrab4, L ) ) < Nz( ValueWhen( BullCrab4, ph2 ) ) - ( Nz( ValueWhen( BullCrab4, ph2 ) ) - Nz( ValueWhen( BullCrab4, tl2 ) ) ) * CDmin AND Nz( LowestSince( BullCrab4, L ) ) > Nz( ValueWhen( BullCrab4, ph2 ) ) - ( Nz( ValueWhen( BullCrab4, ph2 ) ) - Nz( ValueWhen( BullCrab4, tl2 ) ) ) * CDmax AND Nz( HighestSince( BullCrab4, H ) ) <= Nz( ValueWhen( BullCrab4, ph1 ) ) AND Nz( LowestSince( BullCrab4, L ) ) < Nz( ValueWhen( BullCrab4, tl2 ) ) AND Nz( trn ) AND Nz( LowestSince( bullGartley4, L ) ) == L, True, False ); } BullCrab = BullCrab AND IIf( Nz( ValueWhen( BullCrab4, bi ) ) >= Nz( ValueWhen( BullGartley4, bi ) ) AND Nz( ValueWhen( BullCrab4, bi ) ) >= Nz( ValueWhen( BullBat4, bi ) ) AND Nz( ValueWhen( BullCrab4, bi ) ) >= Nz( ValueWhen( BullButterfly4, bi ) ), 1, 0 ); BullBat = BullBat AND IIf( Nz( ValueWhen( BullBat4, bi ) ) >= Nz( ValueWhen( BullGartley4, bi ) ) AND Nz( ValueWhen( BullBat4, bi ) ) >= Nz( ValueWhen( BullCrab4, bi ) ) AND Nz( ValueWhen( BullBat4, bi ) ) >= Nz( ValueWhen( BullButterfly4, bi ) ), 1, 0 ); BullButterfly = BullButterfly AND IIf( Nz( ValueWhen( BullButterfly4, bi ) ) >= Nz( ValueWhen( BullGartley4, bi ) ) AND Nz( ValueWhen( BullButterfly4, bi ) ) >= Nz( ValueWhen( BullCrab4, bi ) ) AND Nz( ValueWhen( BullButterfly4, bi ) ) >= Nz( ValueWhen( BullBat4, bi ) ), 1, 0 ); BullGartley = BullGartley AND IIf( Nz( ValueWhen( BullGartley4, bi ) ) >= Nz( ValueWhen( BullBat4, bi ) ) AND Nz( ValueWhen( BullGartley4, bi ) ) >= Nz( ValueWhen( BullCrab4, bi ) ) AND Nz( ValueWhen( BullGartley4, bi ) ) >= Nz( ValueWhen( BullButterfly4, bi ) ), 1, 0 ); BullHar4 = BullGartley4 OR BullButterfly4 OR BullBat4 OR BullCrab4 ; BullHar = BullGartley OR BullButterfly OR BullBat OR BullCrab ; buXy = ValueWhen( BullHar4, tl2 ); buXx = ValueWhen( BullHar4, tx2 ); buAy = ValueWhen( BullHar4, ph2 ); buAx = ValueWhen( BullHar4, px2 ); buBy = ValueWhen( BullHar4, tl1 ); buBx = ValueWhen( BullHar4, tx1 ); buCy = ValueWhen( BullHar4, ph1 ); buCx = ValueWhen( BullHar4, px1 ); buDy = ValueWhen( BullHar, L ); buDx = ValueWhen( BullHar, bi ); buABdXA = ( buAy - buBy ) / ( buAy - buXy ); buBCdAB = ( buCy - buBy ) / ( buAy - buBy ); buADdXA = ( buAy - buDy ) / ( buAy - buXy ); buBCdCD = ( buCy - buDy ) / ( buCy - buBy ); function drawBullishPattern( i, patternName ) { GfxSelectSolidBrush( ColorRGB( 0, 0, 50 ) ); GfxSetBkColor( colorBlack ); GfxSelectPen( ColorRGB( 0, 0, 255 ), 2, 0 ); GfxMoveTo( buXx[i], buXy[i] ); GfxLineTo( buAx[i], buAy[i] ); GfxMoveTo( buAx[i], buAy[i] ); GfxLineTo( buBx[i], buBy[i] ); GfxMoveTo( buBx[i], buBy[i] ); GfxLineTo( buCx[i], buCy[i] ); GfxMoveTo( buCx[i], buCy[i] ); GfxLineTo( buDx[i], buDy[i] ); GfxMoveTo( buXx[i], buXy[i] ); GfxLineTo( buAx[i], buAy[i] ); GfxSelectPen( ColorRGB( 0, 0, 255 ), 1, 2 ); GfxMoveTo( buXx[i], buXy[i] ); GfxLineTo( buBx[i], buBy[i] ); GfxMoveTo( buAx[i], buAy[i] ); GfxLineTo( buCx[i], buCy[i] ); GfxMoveTo( buBx[i], buBy[i] ); GfxLineTo( buDx[i], buDy[i] ); GfxMoveTo( buXx[i], buXy[i] ); GfxLineTo( buDx[i], buDy[i] ); GfxPolygon( buXx[i], buXy[i], buAx[i], buAy[i], buBx[i], buBy[i], buCx[i], buCy[i], buDx[i], buDy[i], buBx[i], buBy[i], buXx[i], buXy[i] ); if( showPatternName ) { GfxSetTextColor( ColorRGB( 0, 0, 0 ) ); GfxSelectFont( "Helvetica", 10, 700 ); GfxSetBkColor( ColorRGB( 0, 0, 255 ) ); GfxSetTextAlign( 0 | 8 ); GfxTextOut( patternName, buCx[i] + 3, buCy[i] ); } GfxSetTextAlign( 0 | 0 ); GfxSetTextColor( ColorRGB( 0, 0, 255 ) ); GfxSetBkColor( ColorRGB( 0, 0, 0 ) ); GfxSelectFont( "Helvetica", 8, 700 ); GfxTextOut( "" + Prec( buABdXA[i], 2 ), ( buBx[i] + buXx[i] ) / 2, ( buBy[i] + buXy[i] ) / 2 ); GfxTextOut( "" + Prec( buBCdAB[i], 2 ), ( buCx[i] + buAx[i] ) / 2, ( buCy[i] + buAy[i] ) / 2 ); GfxTextOut( "" + Prec( buADdXA[i], 2 ), ( buDx[i] + buXx[i] ) / 2, ( buDy[i] + buXy[i] ) / 2 ); GfxTextOut( "" + Prec( buBCdCD[i], 2 ), ( buBx[i] + buDx[i] ) / 2, ( buBy[i] + buDy[i] ) / 2 ); if( showPatternLabels ) { GfxSetTextColor( ColorRGB( 0, 0, 0 ) ); GfxSelectFont( "Helvetica", 9, 700 ); GfxSetBkColor( ColorRGB( 0, 0, 255 ) ); GfxSetTextAlign( 0 | 24 ); GfxTextOut( "X", buXx[i] - 2, buXy[i] ); GfxTextOut( "A", buAx[i] - 2, buAy[i] ); GfxTextOut( "B", buBx[i] - 2, buBy[i] ); GfxTextOut( "C", buCx[i] + 1, buCy[i] ); GfxTextOut( "D", buDx[i] + 1, buDy[i] ); } } function drawBullishPatterns() { flag1 = 1; flag2 = 0; cnt = 0; for( i = lvb; i > fvb; i-- ) { if( BullHar[i] AND flag1 AND cnt < nBull ) { flag1 = 0; flag2 = 1; cnt = cnt + 1; if( BullButterfly[i] AND bu AND dBut ) { drawBullishPattern( i, "Bullish Butterfly" ); } if( BullCrab[i] AND bu AND dCrab ) { drawBullishPattern( i, "Bullish Crab" ); } if( BullBat[i] AND bu AND dBat ) { drawBullishPattern( i, "Bullish Bat" ); } if( BullGartley[i] AND bu AND dGart ) { drawBullishPattern( i, "Bullish Gartley" ); } } if( BullHar4[i] AND flag2 ) { flag1 = 1; flag2 = 0; } } } drawBullishPatterns(); // +++ Bearish Patterns PTvalid = ( tx1 > px1 AND px1 > tx2 AND tx2 > px2 ) AND tr; if( dGart AND be ) { BearGartley4 = PTvalid AND( ph1 - tl2 ) / ( ph2 - tl2 ) > GBmin AND( ph1 - tl2 ) / ( ph2 - tl2 ) < GBmax AND ( ph1 - tl1 ) / ( ph1 - tl2 ) > GCmin AND( ph1 - tl1 ) / ( ph1 - tl2 ) < GCmax; BearGartley = IIf( Nz( HighestSince( bearGartley4, H ) ) > Nz( ValueWhen( BearGartley4, tl2 ) ) + ( Nz( ValueWhen( BearGartley4, ph2 ) ) - Nz( ValueWhen( BearGartley4, tl2 ) ) ) * GDmin AND Nz( HighestSince( bearGartley4, H ) ) < Nz( ValueWhen( BearGartley4, tl2 ) ) + ( Nz( ValueWhen( BearGartley4, ph2 ) ) - Nz( ValueWhen( BearGartley4, tl2 ) ) ) * GDMax AND Nz( LowestSince( BearGartley4, L ) ) >= Nz( ValueWhen( BearGartley4, tl1 ) ) AND Nz( HighestSince( BearGartley4, H ) ) > Nz( ValueWhen( BearGartley4, ph1 ) ) AND Nz( pkn ) AND Nz( HighestSince( BearGartley4, H ) ) == H, True, False ); } if( dBat AND be ) { BearBat4 = PTvalid AND( ph1 - tl2 ) / ( ph2 - tl2 ) > BatBmin AND( ph1 - tl2 ) / ( ph2 - tl2 ) < BatBmax AND ( ph1 - tl1 ) / ( ph1 - tl2 ) > BatCmin AND( ph1 - tl1 ) / ( ph1 - tl2 ) < BatCmax; BearBat = IIf( Nz( HighestSince( BearBat4, H ) ) > Nz( ValueWhen( BearBat4, tl2 ) ) + ( Nz( ValueWhen( BearBat4, ph2 ) ) - Nz( ValueWhen( BearBat4, tl2 ) ) ) * BatDmin AND Nz( HighestSince( BearBat4, H ) ) < Nz( ValueWhen( BearBat4, tl2 ) ) + ( Nz( ValueWhen( BearBat4, ph2 ) ) - Nz( ValueWhen( BearBat4, tl2 ) ) ) * BatDMax AND Nz( LowestSince( BearBat4, L ) ) >= Nz( ValueWhen( BearBat4, tl1 ) ) AND Nz( HighestSince( BearBat4, H ) ) > Nz( ValueWhen( BearBat4, ph1 ) ) AND Nz( pkn ) AND Nz( HighestSince( BearBat4, H ) ) == H, True, False ); } if( dBut AND be ) { BearButterfly4 = PTvalid AND( ph1 - tl2 ) / ( ph2 - tl2 ) > BtBmin AND( ph1 - tl2 ) / ( ph2 - tl2 ) < BtBmax AND ( ph1 - tl1 ) / ( ph1 - tl2 ) > BtCmin AND( ph1 - tl1 ) / ( ph1 - tl2 ) < BtCmax; BearButterfly = IIf( Nz( HighestSince( BearButterfly4, H ) ) > Nz( ValueWhen( BearButterfly4, tl2 ) ) + ( Nz( ValueWhen( BearButterfly4, ph2 ) ) - Nz( ValueWhen( BearButterfly4, tl2 ) ) ) * BtDmin AND Nz( HighestSince( BearButterfly4, H ) ) < Nz( ValueWhen( BearButterfly4, tl2 ) ) + ( Nz( ValueWhen( BearButterfly4, ph2 ) ) - Nz( ValueWhen( BearButterfly4, tl2 ) ) ) * BtDMax AND Nz( LowestSince( BearButterfly4, L ) ) >= Nz( ValueWhen( BearButterfly4, tl1 ) ) AND Nz( HighestSince( BearButterfly4, H ) ) > Nz( ValueWhen( BearButterfly4, ph2 ) ) AND Nz( pkn ) AND Nz( HighestSince( BearButterfly4, H ) ) == H, True, False ); } if( dCrab AND be ) { BearCrab4 = PTvalid AND( ph1 - tl2 ) / ( ph2 - tl2 ) > CBmin AND( ph1 - tl2 ) / ( ph2 - tl2 ) < CBmax AND ( ph1 - tl1 ) / ( ph1 - tl2 ) > CCmin AND( ph1 - tl1 ) / ( ph1 - tl2 ) < CCmax; BearCrab = IIf( Nz( HighestSince( BearCrab4, H ) ) > Nz( ValueWhen( BearCrab4, tl2 ) ) + ( Nz( ValueWhen( BearCrab4, ph2 ) ) - Nz( ValueWhen( BearCrab4, tl2 ) ) ) * CDmin AND Nz( HighestSince( BearCrab4, H ) ) < Nz( ValueWhen( BearCrab4, tl2 ) ) + ( Nz( ValueWhen( BearCrab4, ph2 ) ) - Nz( ValueWhen( BearCrab4, tl2 ) ) ) * CDMax AND Nz( LowestSince( BearCrab4, L ) ) >= Nz( ValueWhen( BearCrab4, tl1 ) ) AND Nz( HighestSince( BearCrab4, H ) ) > Nz( ValueWhen( BearCrab4, ph2 ) ) AND Nz( pkn ) AND Nz( HighestSince( BearCrab4, H ) ) == H, True, False ); } BearCrab = BearCrab AND IIf( Nz( ValueWhen( BearCrab4, bi ) ) >= Nz( ValueWhen( BearGartley4, bi ) ) AND Nz( ValueWhen( BearCrab4, bi ) ) >= Nz( ValueWhen( BearBat4, bi ) ) AND Nz( ValueWhen( BearCrab4, bi ) ) >= Nz( ValueWhen( BearButterfly4, bi ) ), 1, 0 ); BearBat = BearBat AND IIf( Nz( ValueWhen( BearBat4, bi ) ) >= Nz( ValueWhen( BearGartley4, bi ) ) AND Nz( ValueWhen( BearBat4, bi ) ) >= Nz( ValueWhen( BearCrab4, bi ) ) AND Nz( ValueWhen( BearBat4, bi ) ) >= Nz( ValueWhen( BearButterfly4, bi ) ), 1, 0 ); BearButterfly = BearButterfly AND IIf( Nz( ValueWhen( BearButterfly4, bi ) ) >= Nz( ValueWhen( BearGartley4, bi ) ) AND Nz( ValueWhen( BearButterfly4, bi ) ) >= Nz( ValueWhen( BearCrab4, bi ) ) AND Nz( ValueWhen( BearButterfly4, bi ) ) >= Nz( ValueWhen( BearBat4, bi ) ), 1, 0 ); BearGartley = BearGartley AND IIf( Nz( ValueWhen( BearGartley4, bi ) ) >= Nz( ValueWhen( BearBat4, bi ) ) AND Nz( ValueWhen( BearGartley4, bi ) ) >= Nz( ValueWhen( BearCrab4, bi ) ) AND Nz( ValueWhen( BearGartley4, bi ) ) >= Nz( ValueWhen( BearButterfly4, bi ) ), 1, 0 ); BearHar4 = BearGartley4 OR BearButterfly4 OR BearBat4 OR BearCrab4 ; BearHar = BearGartley OR BearButterfly OR BearBat OR BearCrab ; beXy = ValueWhen( BearHar4, ph2 ); beXx = ValueWhen( BearHar4, px2 ); beAy = ValueWhen( BearHar4, tl2 ); beAx = ValueWhen( BearHar4, tx2 ); beBy = ValueWhen( BearHar4, ph1 ); beBx = ValueWhen( BearHar4, px1 ); beCy = ValueWhen( BearHar4, tl1 ); beCx = ValueWhen( BearHar4, tx1 ); beDy = ValueWhen( BearHar, H ); beDx = ValueWhen( BearHar, bi ); beABdXA = ( beBy - beAy ) / ( beXy - beAy ); beBCdAB = ( beBy - beCy ) / ( beBy - beAy ); beADdXA = ( beDy - beAy ) / ( beXy - beAy ); beBCdCD = ( beDy - beCy ) / ( beBy - beCy ); function drawBearishPattern( i, patternName ) { GfxSelectSolidBrush( ColorRGB( 50, 0, 0 ) ); GfxSetBkColor( colorBlack ); GfxSelectPen( ColorRGB( 255, 0, 0 ), 2, 0 ); GfxMoveTo( beXx[i], beXy[i] ); GfxLineTo( beAx[i], beAy[i] ); GfxMoveTo( beAx[i], beAy[i] ); GfxLineTo( beBx[i], beBy[i] ); GfxMoveTo( beBx[i], beBy[i] ); GfxLineTo( beCx[i], beCy[i] ); GfxMoveTo( beCx[i], beCy[i] ); GfxLineTo( beDx[i], beDy[i] ); GfxMoveTo( beXx[i], beXy[i] ); GfxLineTo( beAx[i], beAy[i] ); GfxSelectPen( ColorRGB( 255, 0, 0 ), 1, 2 ); GfxMoveTo( beXx[i], beXy[i] ); GfxLineTo( beBx[i], beBy[i] ); GfxMoveTo( beAx[i], beAy[i] ); GfxLineTo( beCx[i], beCy[i] ); GfxMoveTo( beBx[i], beBy[i] ); GfxLineTo( beDx[i], beDy[i] ); GfxMoveTo( beXx[i], beXy[i] ); GfxLineTo( beDx[i], beDy[i] ); GfxPolygon( beXx[i], beXy[i], beAx[i], beAy[i], beBx[i], beBy[i], beCx[i], beCy[i], beDx[i], beDy[i], beBx[i], beBy[i], beXx[i], beXy[i] ); if( showPatternName ) { GfxSetTextColor( ColorRGB( 0, 0, 0 ) ); GfxSelectFont( "Helvetica", 10, 700 ); GfxSetBkColor( ColorRGB( 255, 0, 0 ) ); GfxSetTextAlign( 0 | 0 ); GfxTextOut( patternName, beCx[i] + 3, beCy[i] ); } GfxSetTextAlign( 0 | 0 ); GfxSetTextColor( ColorRGB( 255, 0, 0 ) ); GfxSetBkColor( ColorRGB( 0, 0, 0 ) ); GfxSelectFont( "Helvetica", 8, 700 ); GfxTextOut( "" + Prec( beABdXA[i], 2 ), ( beBx[i] + beXx[i] ) / 2, ( beBy[i] + beXy[i] ) / 2 ); GfxTextOut( "" + Prec( beBCdAB[i], 2 ), ( beCx[i] + beAx[i] ) / 2, ( beCy[i] + beAy[i] ) / 2 ); GfxTextOut( "" + Prec( beADdXA[i], 2 ), ( beDx[i] + beXx[i] ) / 2, ( beDy[i] + beXy[i] ) / 2 ); GfxTextOut( "" + Prec( beBCdCD[i], 2 ), ( beBx[i] + beDx[i] ) / 2, ( beBy[i] + beDy[i] ) / 2 ); if( showPatternLabels ) { GfxSetTextColor( ColorRGB( 0, 0, 0 ) ); GfxSelectFont( "Helvetica", 9, 700 ); GfxSetBkColor( ColorRGB( 255, 0, 0 ) ); GfxSetTextAlign( 0 | 24 ); GfxTextOut( "X", beXx[i] - 2, beXy[i] ); GfxTextOut( "A", beAx[i] - 2, beAy[i] ); GfxTextOut( "B", beBx[i] - 2, beBy[i] ); GfxTextOut( "C", beCx[i] + 1, beCy[i] ); GfxTextOut( "D", beDx[i] + 1, beDy[i] ); } } function drawBearishPatterns() { flag1 = 1; flag2 = 0; cnt = 0; for( i = lvb; i > fvb; i-- ) { if( BearHar[i] AND flag1 AND cnt < nBear ) { flag1 = 0; flag2 = 1; cnt = cnt + 1; if( BearButterfly[i] AND be AND dBut ) { drawBearishPattern( i, "Bearish Butterfly" ); } if( BearCrab[i] AND be AND dCrab ) { drawBearishPattern( i, "Bearish Crab" ); } if( BearBat[i] AND be AND dBat ) { drawBearishPattern( i, "Bearish Bat" ); } if( BearGartley[i] AND be AND dGart ) { drawBearishPattern( i, "Bearish Gartley" ); } } if( BearHar4[i] AND flag2 ) { flag1 = 1; flag2 = 0; } } } drawBearishPatterns(); function drawPivotLabels() { sz = 5; for( i = lvb; i > fvb; i-- ) { { if( ll[i] ) PlotTextSetFont( "LL", "Arial Black", sz, i, L[i], colorBlue, colorDefault, -25 ); if( hl[i] ) PlotTextSetFont( "HL", "Arial Black", sz, i, L[i], colorBlue, colorDefault, -25 ); if( db[i] ) PlotTextSetFont( "DB", "Arial Black", sz, i, L[i], colorLightBlue, colorDefault, -25 ); if( hh[i] ) PlotTextSetFont( "HH", "Arial Black", sz, i, H[i], colorRed, colorDefault, 20 ); if( lh[i] ) PlotTextSetFont( "LH", "Arial Black", sz, i, H[i], colorRed, colorDefault, 20 ); if( dt[i] ) PlotTextSetFont( "DT", "Arial Black", sz, i, H[i], colorOrange, colorDefault, 20 ); } } } if( showLabels ) drawPivotLabels(); if( showPatternDevelopmentPoints ) { if( bu ) { PlotShapes( shapeDigit4 * BullHar4, colorBlue, O, H, 35 ); PlotShapes( shapeSmallCircle * BullHar, ColorLightBlue, O, L, -10 ); } if( be ) { PlotShapes( shapeDigit4 * BearHar4, colorRed, O, L, -35 ); PlotShapes( shapeSmallCircle * BearHar, colorOrange, O, H, 10 ); } } Title = Name() + " | " + Now( 2 ) + " | " + "PIVOT TIMEFRAME: " + tfrm / 60 + " Minutes or " + tfrm / 3600 + " Hours or " + tfrm / ( 3600 * 24 ) + " Days ";
24 comments
Leave Comment
Please login here to leave a comment.
Back
Will check
made a minor change in the display of the patterns:
http://wisestocktrader.com/indicatorpasties/1748-harmonic-pattern-+-atr-piv-update
error in formula detect on ami 6
my gosh you guys, I am shocked this is all I get, “error in formula”. I guess this will be my last post. Quite frankly this is superb code. But this will be the last I post, fed up with these “error in formula” posts and people just not responding. Why do you think I post this? Just for the idiots. Good luck
Dear Mr. Pottasch,
Please stay!
“I”, and I’m sure “WE” all, value your studies and afl sharing. Albeit, this is not a discussion board, so often reports are curt with no further explanation. This is compounded by the fact that most, if not all Wisestocktrader members, have English as a secondary language, which in itself creates issues in formula coding. Some probably cannot write English and are too shy to express themselves in descriptive sentences.
Please DO remain here, and continue to post your valuable experience, insight and afl codes.
With appreciation and gratefully yours – ‘Parfumeur’ in PA, USA
Thanks for the great formula! I hope you will stay too. There are definitely those of us who appreciate what you have posted.
you do whatever you want,but letting your emotions fall prey to they posts of error codes is demeening to all of us that know your ideas and programming skills are unequalled here or anywhere else. Do not let yourself fall prey to those that are jellous of your skill. Best of luck and good health in 2017
Thank you, Mr. Pottasch for your brilliant formula.
That is how formulas should be coded.
What I noticed: Bearish Crab overwritten on Bearish Butterfly.
(We shall study the formula and improve it a little.)
Good luck !
ok guys, thanks for the replies, I lost my cool a bit here (never post a comment when drinking beer ….).
with respect to double names, crab overwritten on Butterfly. Yes that sometimes may occur. Try to do a playback. Then you will see that first the Butterfly will appear and later the Crab will appear. In some cases both patterns are valid. This is how it is setup. This is done not by me but by the original author with respect to the parameter constraints. These patterns are only distinguished by the retracement ratios.
This is one of the points I am still working on. The original author uses ranges like GBmin en GBmax. But I am not sure if this is correct and it is hard to figure out what one needs to use. Like in Scott Carneys book Vol1 he says that for a Gartley B retracement over leg XA should be a precise 61.8%. In the code I posted a range is used => 55% to 72%. Maybe this is good enough.
thank you so much for a nice piece of code and for your time .
Crave, will post latest code soon
this is the latest code on this.
it includes entry zones using the parameter settings
http://wisestocktrader.com/indicatorpasties/1754-harmonics-plus-zones
sometimes you see 1 pattern and multiple zones. To understand this do Playback. I only draw the latest pattern originating from point C. But sometimes a pattern starts off as a gartley, moves to a Butterfly and then a Crab. All these zones are displayd but not all the patterns, since this would get messy.
Thank you Ed, This is amazing code! Mark
someone found small error, corrected for:
http://wisestocktrader.com/indicatorpasties/1755-harmonics-plus-zones-2
Thank you for taking the time to code this. It is greatly appreciated.
I was wondering if the script like this one is as reliable as manual harmonic pattern detection, done by a decent human trader ?
so far I did not do any tests with these patterns. I just use the parameter constraints the original author uses. But it would be great to get feedback from people who actually use these type of patterns for trading. Or maybe someone just uses 1 type of pattern and has more information about the parameters to use.
I have just been eyeballing the patterns and the impression I get is that the Gartley and Bat (and to lesser extent the Butterfly) seem to be most reliable especially as a trend continuation pattern
on some bars there were more than 1 pattern, like a Crab and a Butterfly. This sometimes led to a mess when drawing the entry zones. I now removed any overlap
http://wisestocktrader.com/indicatorpasties/1757-harmonics-plus-zones-overlap-removed
dear empottasch is it possible to add exploration code with this chart so that we can scan the stocks to detect potential harmonic patterns with PRZ?
hi
the formula has many error up till now
1st error in line 6
thanks
Sir,
does this http://wisestocktrader.com/indicatorpasties/1755-harmonics-plus-zones-2 supersedes previous versions ?
thanks
hello sir.
can yo help me how to use this in amibroker 6?
i got error.
thanks
GOD Level work, Thank you very much Mr. empottasch :)
Hi,i tried this on my ami..but it doesnt work :(
Hello Empottasch, I found your code snippets in this topic: https://forum.amibroker.com/t/how-to-get-the-most-traded-area-value-of-previous-day-intraday-data/2472/56, and I’m really glad to have come across them. First of all, I want to thank you for writing those lines of code. Since the topic is closed, I’m reaching out to you here to ask for your opinion on the Volume Profile. I have used that code and it has been really helpful for me. However, I don’t know how to retrieve the values of POC (Point of Control), VAL (Value Area Low), and VAH (Value Area High) for specific years using Amibroker’s Analysis. For example, how can I retrieve those values for the previous year? And when the price crosses POC, VAL, or VAH, how can I utilize Analysis? I truly appreciate your answer. I am new to Amibroker, and this part is quite challenging for me. I hope you can assist me. Thank you very much.