EWave -target
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © HeWhoMustNotBeNamed

//@version=4
study("Elliot Wave - Impulse", shorttitle="MA50-200+EW TARGET", overlay=true, max_lines_count=500, max_labels_count=500)
source=input(close)
len2 = input(50, minval=1, title="Length")
src2 = input(close, title="Source")
out2 = sma(src2, len2)
len = input(200, minval=1, title="Length")
src = input(close, title="Source")
out = sma(src, len)
plot(out, color=#0b6ce5, title="MA200")
plot(out2, color=#ff4500, title="MA50")
zigzagLength = input(10, minval=0, step=5)
errorPercent = input(5, minval=2, step=5, maxval=20)
entryPercent = input(30, minval=10, step=10, maxval=100)
zigzagWidth = input(2, step=1, minval=1)
zigzagStyle = input(defval=line.style_dotted, options=[line.style_dashed, line.style_dotted, line.style_solid])
waitForConfirmation = true

max_pivot_size = 10
zigzagColor = color.black
showZigZag = true

var zigzagpivots = array.new_float(0)
var zigzagpivotbars = array.new_int(0)
var zigzagpivotdirs = array.new_int(0)
var waveLinesArray = array.new_line(2)
var targetLabels = array.new_label(0)
var targetLines = array.new_line(0)

var wavelines = array.new_line(0)
transparent = color.new(#FFFFFF, 100)
int max_array_size = 100
err_min = (100-errorPercent)/100
err_max = (100+errorPercent)/100
entry_range = (entryPercent)/100
var patterncount = array.new_int(2,0)

pivots(length)=>
    float phigh = highestbars(high, length) == 0 ? high : na
    float plow = lowestbars(low, length) == 0 ? low : na
    dir = 0
    dir := iff(phigh and na(plow), 1, iff(plow and na(phigh), -1, dir[1]))
    [dir, phigh, plow]

zigzag(length, zigzagpivots, zigzagpivotbars, zigzagpivotdirs)=>
    [dir, phigh, plow] = pivots(length)
    dirchanged = change(dir)
    
    if(phigh or plow)
        value = (dir == 1? phigh : plow)
        bar = bar_index
        if(not dirchanged and array.size(zigzagpivots) >=1)
            pivot = array.shift(zigzagpivots)
            pivotbar = array.shift(zigzagpivotbars)
            pivotdir = array.shift(zigzagpivotdirs)
            value:= value*pivotdir < pivot*pivotdir? pivot : value
            bar:= value*pivotdir < pivot*pivotdir? pivotbar : bar
        
        if(array.size(zigzagpivots) >=2)
            LastPoint = array.get(zigzagpivots,1)
            dir := dir*value > dir*LastPoint? dir*2 : dir
        
        array.unshift(zigzagpivots, value = value)
        array.unshift(zigzagpivotbars, bar)
        array.unshift(zigzagpivotdirs, dir)
        
        if(array.size(zigzagpivots) > max_pivot_size)
            array.pop(zigzagpivots)
            array.pop(zigzagpivotbars)
            array.pop(zigzagpivotdirs)

draw_zigzag(zigzagpivots, zigzagpivotbars, zigzagcolor, zigzagwidth, zigzagstyle, showZigZag)=>
    if(array.size(zigzagpivots) > 2 and showZigZag)
        for i=0 to array.size(zigzagpivots)-2
            y1 = array.get(zigzagpivots, i)
            y2 = array.get(zigzagpivots, i+1)
            x1 = array.get(zigzagpivotbars, i)
            x2 = array.get(zigzagpivotbars, i+1)
            zline = line.new(x1=x1, y1=y1, 
                         x2 = x2, y2=y2,
                         color=zigzagcolor, width=zigzagwidth, style=zigzagstyle)

//////////////////////////////////// Draw Lines with labels //////////////////////////////////////////////////
f_drawLinesWithLabels(target, lbl, linecolor)=>
    timeDiffEnd = time - time[10]
    timeDiffLabel = time - time[5]
    
    line_x1 = time
    line_x2 = time+timeDiffEnd
    label_x = time+timeDiffLabel
    targetLine = line.new(x1=line_x1, y1=target, x2=line_x2, y2=target, color=linecolor, xloc=xloc.bar_time)
    targetLabel = label.new(x=label_x, y=target, text=lbl + " : "+tostring(target), xloc=xloc.bar_time, style=label.style_none, textcolor=color.black, size=size.normal)
    [targetLine,targetLabel]

//////////////////////////////////// Delete Lines with labels //////////////////////////////////////////////////
f_deleteLinesWithLabels(targetLine, targetLabel)=>
    line.delete(targetLine)
    label.delete(targetLabel)
    
ew_impulse(zigzagpivots, zigzagpivotbars, zigzagpivotdirs, zigzagWidth, zigzagStyle, showZigZag, waveLinesArray, targetLines, targetLabels)=>
    start = waitForConfirmation? 1: 0
    waveFound = false
    if(array.size(zigzagpivots) >= 3+start and showZigZag)
        Point2 = array.get(zigzagpivots, start)
        Point2Bar = array.get(zigzagpivotbars, start)
        Point2Dir = array.get(zigzagpivotdirs, start)
        
        Point1 = array.get(zigzagpivots, start+1)
        Point1Bar = array.get(zigzagpivotbars, start+1)
        Point1Dir = array.get(zigzagpivotdirs, start+1)
        
        Point0 = array.get(zigzagpivots, start+2)
        Point0Bar = array.get(zigzagpivotbars, start+2)
        Point0Dir = array.get(zigzagpivotdirs, start+2)
        
        W1Length = abs(Point1-Point0)
        W2Length = abs(Point2-Point1)
        r2 = W2Length/W1Length
            
        existingW1 = array.get(waveLinesArray, 0)
        existingW2 = array.get(waveLinesArray, 1)
            
        existing0 = line.get_y1(existingW1)
        existing1 = line.get_y1(existingW2)
        existing2 = line.get_y2(existingW2)
            
        dir = Point0 > Point1? -1 : 1
        entry = Point2 + dir*entry_range*W2Length
        stop = Point0
        tstop = Point2 - dir*entry_range*W2Length
        
        target1 = Point2 + dir*1.618*W2Length
        target2 = Point2 + dir*2.0*W2Length
        target3 = Point2 + dir*2.618*W2Length
        target4 = Point2 + dir*3.236*W2Length
    
        stopColor = dir == 1? color.red : color.red
        targetColor = dir == 1? color.green : color.green
        
        ignore = false
        patternMatched = false
        dirMatched = false
        if(existing0 == Point0 or existing1 == Point1 or existing2 == Point2)
            ignore := true

        if(r2 > 0.50*err_min and r2 < 0.50*err_max) or (r2 > 0.618*err_min and r2 < 0.618*err_max) or
                 (r2 > 0.764*err_min and r2 < 0.764*err_max) or (r2 > 0.854*err_min and r2 < 0.854*err_max)
            patternMatched := true

        if(Point1Dir == 2 and Point2Dir == -1) or (Point1Dir == -2 and Point2Dir == 1)
            dirMatched := true
        directionColor = Point1 > Point2 ? color.green : color.red
        if(not ignore and patternMatched and dirMatched)
            w1 = line.new(y1=Point0, y2=Point1, x1=Point0Bar, x2=Point1Bar, color=directionColor, width=zigzagWidth, style=zigzagStyle)
            w2 = line.new(y1=Point1, y2=Point2, x1=Point1Bar, x2=Point2Bar, color=directionColor, width=zigzagWidth, style=zigzagStyle)
            array.set(waveLinesArray,0,w1)
            array.set(waveLinesArray,1,w2)
            
            if(array.size(targetLines) > 0)
                for i=0 to array.size(targetLines)-1
                    line.delete(array.shift(targetLines))
                for i=0 to array.size(targetLabels)-1
                    label.delete(array.shift(targetLabels))
            
            [entryLine,entryLabel] = f_drawLinesWithLabels(entry, "Entry", color.blue)
            [stopLine,stopLabel] = f_drawLinesWithLabels(stop, "Stop", stopColor)
            [tstopLine,tstopLabel] = f_drawLinesWithLabels(tstop, "T.Stop", stopColor)
            [t1Line,t1Label] = f_drawLinesWithLabels(target1, "Target - 1", targetColor)
            [t2Line,t2Label] = f_drawLinesWithLabels(target2, "Target - 2", targetColor)
            [t3Line,t3Label] = f_drawLinesWithLabels(target3, "Target - 3", targetColor)
            [t4Line,t4Label] = f_drawLinesWithLabels(target4, "Target - 4", targetColor)
            
            array.unshift(targetLines, entryLine)
            array.unshift(targetLines, stopLine)
            array.unshift(targetLines, tstopLine)
            array.unshift(targetLines, t1Line)
            array.unshift(targetLines, t2Line)
            array.unshift(targetLines, t3Line)
            array.unshift(targetLines, t4Line)
            
            array.unshift(targetLabels, entryLabel)
            array.unshift(targetLabels, stopLabel)
            array.unshift(targetLabels, tstopLabel)
            array.unshift(targetLabels, t1Label)
            array.unshift(targetLabels, t2Label)
            array.unshift(targetLabels, t3Label)
            array.unshift(targetLabels, t4Label)
            
            count_index = dir==1?0:1
            array.set(patterncount, count_index, array.get(patterncount, count_index)+1)
            waveFound := true
            if(existing0 == Point0 and existing1 == Point1 and existing2 == Point2) and waveFound[1]
                line.delete(existingW1)
                line.delete(existingW2)
                array.set(patterncount, count_index, array.get(patterncount, count_index)-1)
    waveFound
zigzag(zigzagLength, zigzagpivots, zigzagpivotbars, zigzagpivotdirs)
waveFormed = ew_impulse(zigzagpivots, zigzagpivotbars, zigzagpivotdirs, zigzagWidth, zigzagStyle, showZigZag, waveLinesArray, targetLines, targetLabels)

alertcondition(waveFormed, title='New impulse wave alert', message='New impulse wave detected on {{ticker}}')
var stats = table.new(position = position.top_right, columns = 3, rows = max_pivot_size+2, border_width = 1)

if(barstate.islast)
    table.cell(table_id = stats, column = 1, row = 0 , text = "Bullish", bgcolor=color.black, text_color=color.white)
    table.cell(table_id = stats, column = 2, row = 0 , text = "Bearish", bgcolor=color.black, text_color=color.white)

    dtColor = color.white
    for type = 1 to (array.size(patterncount)/2)
        for direction = 0 to 1
            count_index = (type*2 - 2) + direction
            row = type
            column = direction+1
            text = tostring(array.get(patterncount, count_index))
            table.cell(table_id = stats, column = column, row = row, text = text, bgcolor=dtColor)
        