Unlock Precision in Trading with Harmonic Patterns Detection in Pine Script
January 3, 2025 | by admin

//@version=5
indicator('Harmonic Patterns', overlay=true, max_bars_back=1000, max_lines_count=500, max_labels_count=500)
//
CRAK1 = input.int(13, step=10)
CRAK2 = input.int(17, step=10)
CRAK3 = input.int(110, step=10)
CRAK4 = input.int(109, step=10)
CRAK5 = input.int(103, step=10)
CRAK6 = input.int(1, step=10)
CRAK7 = input.int(1, step=10)
CRAK8 = input.int(9, step=10)
CRAK9 = input.int(11, step=10)
CRAK10 = input.int(120, step=10)
CRAK11 = input.int(200, step=10)
CRAK12 = input.int(200, step=10)
CRAK13 = input.int(110, step=10)
CRAK14 = input.int(11, step=10)
CRAK15 = input.int(12, step=10)
CRAK16 = input.int(2, step=10)
CRAK17 = input.int(1, step=10)
CRAK18 = input.int(2, step=10)
CRAK19 = input.int(1, step=10)
CRAK20 = input.int(2, step=10)
///
DETECT3 = input.int(18, step=10)
PATTERN1 = input(true)
PATTERN10 = input.int(18, step=5, minval=1)
COLORP1 = input(color.rgb(43, 52, 146, 55))
zigzag1Width = 1
zigzag1Style = line.style_dotted
PATTERN2 = input(true)
PATTERN20 = input.int(24, step=5, minval=1)
COLORP2 = input(color.rgb(43, 52, 146, 55))
zigzag2Width = 1
zigzag2Style = line.style_dotted
PATTERN3 = input(true)
PATTERN30 = input.int(32, step=5, minval=1)
COLORP3 = input(color.rgb(43, 52, 146, 55))
zigzag3Width = 1
zigzag3Style = line.style_dotted
PATTERN4 = input(true)
PATTERN40 = input.int(38, step=5, minval=1)
COLORP4 = input(color.rgb(43, 52, 146, 55))
zigzag4Width = 1
zigzag4Style = line.style_dotted
P11 = input(true)
P22 = input(true)
P33 = input(true)
P44 = input(true)
P55 = input(true)
P66 = input(true)
DETECTM = input.int(18, minval=5, step=5, maxval=200)
//
DATAC = input.int(350, step=10)
DATAC2 = input.int(400, step=10)
//
MaxRiskPerReward = input.int(29, title='DETECT/PER', step=10, minval=0)
//
//
E1 = input.int(370, step=10)
E2 = input.int(390, step=10)
showStatTable = false
CANCLE_PATTERNS = input(false)
//
CRAKD90 = input.int(200, step=10)
CRAKFALSE200 = input.int(200, step=10)
CRAKFALSE100 = input.int(300, step=10)
///
BULL_PATTERNS = input(color.silver)
BEAR_PATTERNS = input(color.blue)
err_min = (100 - DETECTM) / 100
err_max = (100 + DETECTM) / 100
var zigzagpivots1 = array.new_float(0)
var zigzagpivotbars1 = array.new_int(0)
var zigzagpivotdirs1 = array.new_int(0)
var zigzagpivots2 = array.new_float(0)
var zigzagpivotbars2 = array.new_int(0)
var zigzagpivotdirs2 = array.new_int(0)
var zigzagpivots3 = array.new_float(0)
var zigzagpivotbars3 = array.new_int(0)
var zigzagpivotdirs3 = array.new_int(0)
var zigzagpivots4 = array.new_float(0)
var zigzagpivotbars4 = array.new_int(0)
var zigzagpivotdirs4 = array.new_int(0)
var wmlines1 = array.new_line(8)
var wmtype1 = array.new_int(2, 1)
var wmLabels1 = array.new_bool(13, false)
var wmLabel1 = array.new_label(1)
var wmlines2 = array.new_line(8)
var wmtype2 = array.new_int(2, 1)
var wmLabels2 = array.new_bool(13, false)
var wmLabel2 = array.new_label(1)
var wmlines3 = array.new_line(8)
var wmtype3 = array.new_int(2, 1)
var wmLabels3 = array.new_bool(13, false)
var wmLabel3 = array.new_label(1)
var wmlines4 = array.new_line(8)
var wmtype4 = array.new_int(2, 1)
var wmLabels4 = array.new_bool(13, false)
var wmLabel4 = array.new_label(1)
pivots(length) =>
float phigh = ta.highestbars(high, length) == 0 ? high : na
float plow = ta.lowestbars(low, length) == 0 ? low : na
dir = 0
iff_1 = plow and na(phigh) ? -1 : dir[1]
dir := phigh and na(plow) ? 1 : iff_1
[dir, phigh, plow]
zigzag(length, zigzagpivots, zigzagpivotbars, zigzagpivotdirs) =>
[dir, phigh, plow] = pivots(length)
dirchanged = ta.change(dir)
if phigh or plow
value = dir == 1 ? phigh : plow
bar = bar_index
newDir = dir
if not dirchanged and array.size(zigzagpivots) >= 1
pivot = array.shift(zigzagpivots)
pivotbar = array.shift(zigzagpivotbars)
pivotdir = array.shift(zigzagpivotdirs)
useNewValues = value * pivotdir < pivot * pivotdir
value := useNewValues ? pivot : value
bar := useNewValues ? pivotbar : bar
bar
if array.size(zigzagpivots) >= 2
LastPoint = array.get(zigzagpivots, 1)
newDir := dir * value > dir * LastPoint ? dir * 2 : dir
newDir
array.unshift(zigzagpivots, value=value)
array.unshift(zigzagpivotbars, bar)
array.unshift(zigzagpivotdirs, newDir)
if array.size(zigzagpivots) > DETECT3
array.pop(zigzagpivots)
array.pop(zigzagpivotbars)
array.pop(zigzagpivotdirs)
get_harmonic_label(wmLabels, dir, price, bar) =>
isP11 = array.get(wmLabels, 0)
isP22 = array.get(wmLabels, 1)
isP33 = array.get(wmLabels, 2)
isP44 = array.get(wmLabels, 3)
isP55 = array.get(wmLabels, 4)
isP66 = array.get(wmLabels, 5)
labelText = isP11 ? 'Gartley' : ''
labelText := labelText + (isP22 ? (labelText == '' ? '' : '\n') + 'Crab' : '')
labelText := labelText + (isP33 ? (labelText == '' ? '' : '\n') + 'Deep Crab' : '')
labelText := labelText + (isP44 ? (labelText == '' ? '' : '\n') + 'Bat' : '')
labelText := labelText + (isP55 ? (labelText == '' ? '' : '\n') + 'Butterfly' : '')
labelText := labelText + (isP66 ? (labelText == '' ? '' : '\n') + 'Shark' : '')
trendColor = dir > 0 ? BULL_PATTERNS : BEAR_PATTERNS
baseLabel = label.new(x=bar, y=price, text=labelText, yloc=yloc.price, color=trendColor, style=dir < 1 ? label.style_label_down : label.style_label_up, textcolor=color.black, size=size.normal)
baseLabel
detect_harmonic_pattern(zigzagpivots, zigzagpivotbars, zigzagpivotdirs, wmlines, wmlabel, wmtype, wmLabels, zigzagColor, zigzagWidth, zigzagStyle, showZigZag) =>
start = CANCLE_PATTERNS ? 1 : 0
wm_pattern = false
abcd_pattern = false
double_pattern = false
if array.size(zigzagpivots) >= 6 + start and showZigZag
d = array.get(zigzagpivots, start + 0)
dBar = array.get(zigzagpivotbars, start + 0)
dDir = array.get(zigzagpivotdirs, start + 0)
c = array.get(zigzagpivots, start + 1)
cBar = array.get(zigzagpivotbars, start + 1)
cDir = array.get(zigzagpivotdirs, start + 1)
b = array.get(zigzagpivots, start + 2)
bBar = array.get(zigzagpivotbars, start + 2)
bDir = array.get(zigzagpivotdirs, start + 2)
a = array.get(zigzagpivots, start + 3)
aBar = array.get(zigzagpivotbars, start + 3)
aDir = array.get(zigzagpivotdirs, start + 3)
x = array.get(zigzagpivots, start + 4)
xBar = array.get(zigzagpivotbars, start + 4)
xDir = array.get(zigzagpivotdirs, start + 4)
y = array.get(zigzagpivots, start + 5)
yBar = array.get(zigzagpivotbars, start + 5)
yDir = array.get(zigzagpivotdirs, start + 5)
highPoint = math.max(x, a, b, c, d)
lowPoint = math.min(x, a, b, c, d)
dir = c > d ? 1 : -1
xabRatio = math.abs(b - a) / math.abs(x - a)
abcRatio = math.abs(c - b) / math.abs(a - b)
bcdRatio = math.abs(d - c) / math.abs(b - c)
xadRatio = math.abs(d - a) / math.abs(x - a)
yxaRatio = math.abs(a - x) / math.abs(y - x)
abTime = math.abs(aBar - bBar)
cdTime = math.abs(cBar - dBar)
abPrice = math.abs(a - b)
cdPrice = math.abs(c - d)
time_ratio = cdTime / abTime
price_ratio = cdPrice / abPrice
abcdDirection = a < b and a < c and c < b and c < d and a < d and b < d ? 1 : a > b and a > c and c > b and c > d and a > d and b > d ? -1 : 0
risk = math.abs(b - d)
reward = math.abs(c - d)
riskPerReward = risk * 100 / (risk + reward)
if b < highPoint and b > lowPoint
//gartley
if P11 and xabRatio >= 0.588 * err_min and xabRatio <= 0.648 * err_max and abcRatio >= 0.382 * err_min and abcRatio <= 0.886 * err_max and xadRatio >= 0.786 * err_min and xadRatio <= 0.886 * err_max
wm_pattern := true
array.set(wmLabels, 0, true)
else
array.set(wmLabels, 0, false)
//Crab
if P22 and xabRatio >= 0.382 * err_min and xabRatio <= 0.618 * err_max and abcRatio >= 0.382 * err_min and abcRatio <= 0.886 * err_max and xadRatio >= 1.618 * err_min and xadRatio <= 1.902 * err_max
wm_pattern := true
array.set(wmLabels, 1, true)
else
array.set(wmLabels, 1, false)
//Deep Crab
if P33 and xabRatio >= 0.886 * err_min and xabRatio <= 0.936 * err_max and abcRatio >= 0.382 * err_min and abcRatio <= 0.886 * err_max and xadRatio >= 1.618 * err_min and xadRatio <= 1.902 * err_max
wm_pattern := true
array.set(wmLabels, 2, true)
else
array.set(wmLabels, 2, false)
//Bat
if P44 and xabRatio >= 0.382 * err_min and xabRatio <= 0.55 * err_max and abcRatio >= 0.382 * err_min and abcRatio <= 0.886 * err_max and xadRatio >= 0.886 * err_min and xadRatio <= 0.886 * err_max
wm_pattern := true
array.set(wmLabels, 3, true)
else
array.set(wmLabels, 3, false)
//Butterfly
if P55 and xabRatio >= 0.755 * err_min and xabRatio <= 0.816 * err_max and abcRatio >= 0.382 * err_min and abcRatio <= 0.886 * err_max and xadRatio >= 1.272 * err_min and xadRatio <= 1.272 * err_max
wm_pattern := true
array.set(wmLabels, 4, true)
else
array.set(wmLabels, 4, false)
//Shark
if P66 and xabRatio >= 0.382 * err_min and xabRatio <= 0.618 * err_max and abcRatio >= 1.13 * err_min and abcRatio <= 1.618 * err_max and xadRatio >= 0.886 * err_min and xadRatio <= 1.13 * err_max
wm_pattern := true
array.set(wmLabels, 5, true)
else
array.set(wmLabels, 5, false)
cancelW = false
cancelA = false
cancelD = false
if wm_pattern[1] and x == x[1] and a == a[1] and b == b[1] and c == c[1]
line.delete(array.get(wmlines, 0))
line.delete(array.get(wmlines, 1))
line.delete(array.get(wmlines, 2))
line.delete(array.get(wmlines, 3))
line.delete(array.get(wmlines, 4))
line.delete(array.get(wmlines, 5))
line.delete(array.get(wmlines, 6))
line.delete(array.get(wmlines, 7))
label.delete(array.get(wmlabel, 0))
cancelW := true
cancelW
if abcd_pattern[1] and a == a[1] and b == b[1] and c == c[1]
line.delete(array.get(wmlines, 1))
line.delete(array.get(wmlines, 2))
line.delete(array.get(wmlines, 3))
label.delete(array.get(wmlabel, 0))
cancelA := true
cancelA
if double_pattern[1] and a == a[1] and b == b[1] and c == c[1]
line.delete(array.get(wmlines, 5))
label.delete(array.get(wmlabel, 0))
cancelD := true
cancelD
if wm_pattern
xa = line.new(y1=x, y2=a, x1=xBar, x2=aBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
ab = line.new(y1=a, y2=b, x1=aBar, x2=bBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
bc = line.new(y1=b, y2=c, x1=bBar, x2=cBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
cd = line.new(y1=c, y2=d, x1=cBar, x2=dBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
xb = line.new(y1=x, y2=b, x1=xBar, x2=bBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
bd = line.new(y1=b, y2=d, x1=bBar, x2=dBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
xd = line.new(y1=x, y2=d, x1=xBar, x2=dBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
ac = line.new(y1=a, y2=c, x1=aBar, x2=cBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
array.set(wmlines, 0, xa)
array.set(wmlines, 1, ab)
array.set(wmlines, 2, bc)
array.set(wmlines, 3, cd)
array.set(wmlines, 4, xb)
array.set(wmlines, 5, bd)
array.set(wmlines, 6, xd)
array.set(wmlines, 7, ac)
array.set(wmtype, 0, dir)
linefill.new(xa, xb, color=color.rgb(44, 93, 136, 94))
linefill.new(bc, bd, color=color.rgb(44, 93, 136, 94))
if abcd_pattern and not wm_pattern
ab = line.new(y1=a, y2=b, x1=aBar, x2=bBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
bc = line.new(y1=b, y2=c, x1=bBar, x2=cBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
cd = line.new(y1=c, y2=d, x1=cBar, x2=dBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
array.set(wmlines, 1, ab)
array.set(wmlines, 2, bc)
array.set(wmlines, 3, cd)
array.set(wmtype, 0, dir)
if double_pattern and not wm_pattern
bd = line.new(y1=b, y2=d, x1=bBar, x2=dBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
array.set(wmlines, 5, bd)
array.set(wmtype, 0, dir)
if wm_pattern or abcd_pattern or double_pattern
array.set(wmlabel, 0, get_harmonic_label(wmLabels, dir, d, dBar))
pattern = wm_pattern and not wm_pattern[1] or abcd_pattern and not abcd_pattern[1] or double_pattern and not double_pattern[1]
pattern
zigzag(PATTERN10, zigzagpivots1, zigzagpivotbars1, zigzagpivotdirs1)
zigzag(PATTERN20, zigzagpivots2, zigzagpivotbars2, zigzagpivotdirs2)
zigzag(PATTERN30, zigzagpivots3, zigzagpivotbars3, zigzagpivotdirs3)
zigzag(PATTERN40, zigzagpivots4, zigzagpivotbars4, zigzagpivotdirs4)
wm_pattern1 = detect_harmonic_pattern(zigzagpivots1, zigzagpivotbars1, zigzagpivotdirs1, wmlines1, wmLabel1, wmtype1, wmLabels1, COLORP1, zigzag1Width, zigzag1Style, PATTERN1)
wm_pattern2 = detect_harmonic_pattern(zigzagpivots2, zigzagpivotbars2, zigzagpivotdirs2, wmlines2, wmLabel2, wmtype2, wmLabels2, COLORP2, zigzag2Width, zigzag2Style, PATTERN2)
wm_pattern3 = detect_harmonic_pattern(zigzagpivots3, zigzagpivotbars3, zigzagpivotdirs3, wmlines3, wmLabel3, wmtype3, wmLabels3, COLORP3, zigzag3Width, zigzag3Style, PATTERN3)
wm_pattern4 = detect_harmonic_pattern(zigzagpivots4, zigzagpivotbars4, zigzagpivotdirs4, wmlines4, wmLabel4, wmtype4, wmLabels4, COLORP4, zigzag4Width, zigzag4Style, PATTERN4)
alertcondition(wm_pattern1 or wm_pattern2 or wm_pattern3 or wm_pattern4, title='Harmonic Alert', message='Harmonic Alert {{ticker}}')
var stats = table.new(position=position.top_right, columns=8, rows=DETECT3 + 2, border_width=1)
if barstate.islast and showStatTable
if PATTERN1
table.cell(table_id=stats, column=0, row=0, text='Zigzag ' + str.tostring(PATTERN10), bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=0, row=1, text='Price', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=1, row=1, text='BarIndex', bgcolor=color.black, text_color=color.white)
for i = 0 to array.size(zigzagpivots1) - 1 by 1
bgcolor = array.get(zigzagpivotdirs1, i) == 1 ? color.lime : color.orange
table.cell(table_id=stats, column=0, row=i + 2, text=str.tostring(array.get(zigzagpivots1, i)), bgcolor=bgcolor)
table.cell(table_id=stats, column=1, row=i + 2, text=str.tostring(array.get(zigzagpivotbars2, i)), bgcolor=bgcolor)
if PATTERN2
table.cell(table_id=stats, column=2, row=0, text='Zigzag ' + str.tostring(PATTERN20), bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=2, row=1, text='Price', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=3, row=1, text='BarIndex', bgcolor=color.black, text_color=color.white)
for i = 0 to array.size(zigzagpivots2) - 1 by 1
bgcolor = array.get(zigzagpivotdirs2, i) == 1 ? color.lime : color.orange
table.cell(table_id=stats, column=2, row=i + 2, text=str.tostring(array.get(zigzagpivots2, i)), bgcolor=bgcolor)
table.cell(table_id=stats, column=3, row=i + 2, text=str.tostring(array.get(zigzagpivotbars2, i)), bgcolor=bgcolor)
if PATTERN3
table.cell(table_id=stats, column=4, row=0, text='Zigzag ' + str.tostring(PATTERN30), bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=4, row=1, text='Price', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=5, row=1, text='BarIndex', bgcolor=color.black, text_color=color.white)
for i = 0 to array.size(zigzagpivots3) - 1 by 1
bgcolor = array.get(zigzagpivotdirs3, i) == 1 ? color.lime : color.orange
table.cell(table_id=stats, column=4, row=i + 2, text=str.tostring(array.get(zigzagpivots3, i)), bgcolor=bgcolor)
table.cell(table_id=stats, column=5, row=i + 2, text=str.tostring(array.get(zigzagpivotbars3, i)), bgcolor=bgcolor)
if PATTERN4
table.cell(table_id=stats, column=6, row=0, text='Zigzag ' + str.tostring(PATTERN40), bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=6, row=1, text='Price', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=7, row=1, text='BarIndex', bgcolor=color.black, text_color=color.white)
for i = 0 to array.size(zigzagpivots4) - 1 by 1
bgcolor = array.get(zigzagpivotdirs4, i) == 1 ? color.lime : color.orange
table.cell(table_id=stats, column=6, row=i + 2, text=str.tostring(array.get(zigzagpivots4, i)), bgcolor=bgcolor)
table.cell(table_id=stats, column=7, row=i + 2, text=str.tostring(array.get(zigzagpivotbars4, i)), bgcolor=bgcolor)
/////////
//'
//fiboLevel= b + (1.618 * (c - b))
//line.new(x1=dBar+1, y1=fiboLevel, x2=dBar+40, y2=fiboLevel, color=color.red, width=1)
//isP11 = array.get(wmLabels, 0)
//isP22 = array.get(wmLabels, 1)
//isP33 = array.get(wmLabels, 2)
//isP44 = array.get(wmLabels, 3)
//isP55 = array.get(wmLabels, 4)
//isP66 = array.get(wmLabels, 5)
How to Apply Pine Script in TradingView:
- Open TradingView and log in to your account.
- Go to the Pine Script Editor at the bottom of the screen.
- Copy the provided Pine Script code.
- Paste it into the editor.
- Click Save and name it, e.g., “Harmonic Patterns Detector.”
- Click Add to Chart to apply the indicator to your selected chart.
- Adjust the input parameters to match your trading preferences and timeframe.
Key Features of the Script:
- Harmonic Pattern Detection:
- Identifies popular harmonic patterns such as Gartley, Crab, Deep Crab, Bat, Butterfly, and Shark.
- Automatically detects patterns using price ratios and pivot points.
- Customizable Zigzag Settings:
- Includes multi-layered zigzag detection for pattern identification.
- Adjustable parameters to fine-tune the sensitivity of pattern recognition.
- Visualized Harmonic Patterns:
- Draws lines connecting pivot points to outline detected harmonic structures.
- Highlights bullish and bearish patterns with customizable color schemes.
- Risk/Reward Analysis:
- Calculates risk-to-reward ratios for each pattern.
- Displays price levels for potential entries, stops, and targets.
- Alerts for Detected Patterns:
- Built-in alert conditions for real-time notifications of detected harmonic patterns.
- Comprehensive Table Display:
- Tabulates data for each pattern including price, bar index, and zigzag pivots.
- Helps track multiple patterns simultaneously.
- High Customization:
- Offers numerous input settings for controlling detection accuracy, colors, and display preferences.
- Users can toggle specific patterns and adjust error margins for precise analysis.
Recommended Usage:
- Advanced Chart Analysis:
- Use this script to enhance your chart analysis by identifying complex harmonic patterns.
- Ideal for traders specializing in technical analysis and pattern-based strategies.
- Entry and Exit Signals:
- Leverage the detected patterns to time entries and exits based on price projections and risk management.
- Scalping and Swing Trading:
- Effective for both short-term scalping and longer-term swing trades.
- Customize the zigzag settings to adapt to different timeframes.
- Risk Management:
- Utilize the risk/reward ratios provided by the script to set stop-loss and take-profit levels.
RELATED POSTS
View all