Stock Portfolio Organizer

The ultimate porfolio management solution.

Shares, Margin, CFD's, Futures and Forex
EOD and Realtime
Dividends and Trust Distributions
And Much More ....
For Portfolio Manager Click Here

WiseTrader Toolbox

#1 Selling Amibroker Plugin featuring:

Advanced Adaptive Indicators
Advanced Pattern Exploration
Neural Networks
And Much More ....
Find Out More Here

HARMONIC PATTERN DETECTION using ATR type Peaks and Troughs for Amibroker (AFL)

Rating:
4 / 5 (Votes 7)
Tags:
amibroker, pattern, pivots, Harmonic

/* 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

Copy & Paste Friendly
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
/* 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

1. manaskumarpan@gmail.com

Will check

2. empottasch

made a minor change in the display of the patterns:

http://wisestocktrader.com/indicatorpasties/1748-harmonic-pattern-+-atr-piv-update

3. szgolyas

error in formula detect on ami 6

4. empottasch

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

5. parfumeur

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

6. money12

Thanks for the great formula! I hope you will stay too. There are definitely those of us who appreciate what you have posted.

7. davidalan

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

8. crave

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 !

9. empottasch

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.

10. mashraf

thank you so much for a nice piece of code and for your time .

11. empottasch

Crave, will post latest code soon

12. empottasch

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.

13. Mark Brown

Thank you Ed, This is amazing code! Mark

14. empottasch

someone found small error, corrected for:

http://wisestocktrader.com/indicatorpasties/1755-harmonics-plus-zones-2

15. epicbud

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 ?

16. empottasch

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

17. empottasch

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

18. indraji2001

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?

19. gelgel128

hi
the formula has many error up till now
1st error in line 6
thanks

20. crkumar

Sir,
does this http://wisestocktrader.com/indicatorpasties/1755-harmonics-plus-zones-2 supersedes previous versions ?
thanks

21. bhudizhu

hello sir.
can yo help me how to use this in amibroker 6?
i got error.
thanks

22. kaka365

GOD Level work, Thank you very much Mr. empottasch :)

23. modkore

Hi,i tried this on my ami..but it doesnt work :(

24. toihocgiaodich

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.

Leave Comment

Please login here to leave a comment.

Back