// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © HeWhoMustNotBeNamed
//@version=5
indicator('Auto Harmonic Patterns - Open Source', shorttitle='Auto Patterns', overlay=true, max_bars_back=1000, max_lines_count=500, max_labels_count=500)
Length = input.int(10, minval=0, step=5)
DeviationThreshold = 0
errorPercent = input.int(10, minval=5, step=5, maxval=20)
showPivots = input(false)
showRatios = input(false)
showZigZag = input(false)
bullishColor = input(color.green)
bullTrapColor = input(color.orange)
bearishColor = input(color.red)
bearTrapColor = input(color.lime)
MaxRiskPerReward = input.int(40, title='Max Risk Per Reward (Double Top/Bottom)', step=10, minval=0)
abcdClassic = input(true)
abEQcd = input(true)
abcdExt = input(true)
doubleTopBottom = input(true)
gartley = input(true)
crab = input(true)
deepCrab = input(true)
bat = input(true)
butterfly = input(true)
shark = input(true)
cypher = input(true)
threeDrives = input(true)
fiveZero = input(true)
var abcdlines = array.new_line(3)
var abcdtype = array.new_int(2, 1)
var wmlines = array.new_line(4)
var wmtype = array.new_int(2, 1)
var wmLabels = array.new_bool(9, false)
var patterncount = array.new_int(26, 0)
var zigzaglines = array.new_line(0)
var zigzaglabels = array.new_label(0)
var zigzagdir = array.new_int(0)
var zigzagratios = array.new_float(0)
int max_array_size = 10
transparent = color.new(#FFFFFF, 100)
err_min = (100 - errorPercent) / 100
err_max = (100 + errorPercent) / 100
pivots(length) =>
float ph = ta.highestbars(high, length) == 0 ? high : na
float pl = ta.lowestbars(low, length) == 0 ? low : na
dir = 0
iff_1 = pl and na(ph) ? -1 : dir[1]
dir := ph and na(pl) ? 1 : iff_1
[dir, ph, pl]
get_edir(dir, y2) =>
eDir = dir
if array.size(zigzaglines) > 0
lastLine = array.get(zigzaglines, 0)
lastPivot = line.get_y1(lastLine)
eDir := (dir * y2 > dir * lastPivot ? 2 : 1) * dir
eDir
lineColor = eDir == 2 ? bullishColor : eDir == 1 ? bullTrapColor : eDir == -1 ? bearTrapColor : bearishColor
[eDir, lineColor]
add_to_zigzaglines(x1, y1, x2, y2, dir) =>
[eDir, lineColor] = get_edir(dir, y2)
color = showZigZag ? lineColor : color.new(#FFFFFF, 100)
zline = line.new(x1=x1, y1=y1, x2=x2, y2=y2, color=color, width=2, style=line.style_solid)
array.unshift(zigzaglines, zline)
add_to_zigzaglabels(x1, x2, y1, y2, dir) =>
[eDir, lineColor] = get_edir(dir, y2)
pivotLabel = eDir == 2 ? 'HH' : eDir == 1 ? 'LH' : eDir == -1 ? 'HL' : 'LL'
lastLineLen = 0.0
currentLineLen = math.abs(y2 - y1)
if array.size(zigzaglines) > 0
lastLine = array.get(zigzaglines, 0)
lastLineLen := math.abs(line.get_y2(lastLine) - line.get_y1(lastLine))
lastLineLen
ratio = math.round(lastLineLen != 0 ? currentLineLen / lastLineLen : 0, 3)
labelText = (showPivots ? pivotLabel : '') + (showPivots and showRatios ? ' - ' : '') + (showRatios ? str.tostring(ratio) : '')
yloc = dir > 0 ? yloc.abovebar : yloc.belowbar
labelStyle = dir > 0 ? label.style_label_down : label.style_label_up
labelSize = showRatios and showPivots ? size.normal : size.small
zlabel = label.new(x=x2, y=y2, text=labelText, xloc=xloc.bar_index, yloc=yloc, color=lineColor, size=labelSize, style=labelStyle)
array.unshift(zigzaglabels, zlabel)
array.unshift(zigzagdir, eDir)
array.unshift(zigzagratios, ratio)
if not showRatios and not showPivots
label.delete(zlabel)
add_to_zigzag(dir, dirchanged, ph, pl, index) =>
value = dir == 1 ? ph : pl
y1 = dir == 1 ? ta.lowest(Length) : ta.highest(Length)
x1 = bar_index + (dir == 1 ? ta.lowestbars(Length) : ta.highestbars(Length))
x2 = index
y2 = value
skip = false
if array.size(zigzaglines) > 0
if not dirchanged
lastline = array.get(zigzaglines, 0)
lasty2 = line.get_y2(lastline)
if lasty2 * dir > y2 * dir
skip := true
skip
else
line.delete(array.shift(zigzaglines))
label.delete(array.shift(zigzaglabels))
array.shift(zigzagdir)
array.shift(zigzagratios)
skip := false
skip
if array.size(zigzaglines) > 0
lastLine = array.get(zigzaglines, 0)
x1 := line.get_x2(lastLine)
y1 := line.get_y2(lastLine)
y1
outsideDeviationThreshold = math.abs(y1 - y2) * 100 / y1 > DeviationThreshold
if outsideDeviationThreshold and not skip
add_to_zigzaglabels(x1, x2, y1, y2, dir)