Interactive trendline - Proximity Doji & 3LS
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Blockhead305

//@version=5
indicator("Interactive trendline - Proximity Doji & 3LS", overlay = true)

atr_mul = input.int(defval=2, title="ATR muntiplte")
source = input.source(defval=close, title="canlde source in atr zone")
plot_above_below = input.string(defval="below", title="plot above or below", options=["below", "above"])
x_1 = input.time(defval = 1, title = "X 1", confirm = true)
y_1 = input.price(defval = 1, title = "Y 1", confirm = true)
x_2 = input.time(defval = 1, title = "X 2", confirm = true)
y_2 = input.price(defval = 1, title = "Y 2", confirm = true)
run_input = input.int(defval=0, title="run")
extend = input.bool(true, title="extnd trendline")


var int bar_index_x_1_table = 0
var int bar_index_x_2_table = 0

if time == x_1
    bar_index_x_1_table := bar_index
if time == x_2
    bar_index_x_2_table := bar_index
rise = (math.max(y_1, y_2) - math.min(y_1, y_2))
slope = rise / run_input

var float plot_line = na
var int bar_count = 0

if time == x_1 and barstate.isconfirmed
    plot_line := y_1
if time > x_1
    if y_2 > y_1
        plot_line := plot_line + slope
    else
        plot_line := plot_line - slope
    if time <= x_2
        bar_count += 1
if time > x_2 and extend == false
    plot_line := na

plot(run_input != 0 ? plot_line : na)
plot(run_input != 0 ? (y_2 < y_1 ? plot_line - ta.atr(10) * atr_mul : plot_line + ta.atr(10) * atr_mul) : na)

if barstate.isconfirmed
	var table3 = table.new(position = position.top_right, columns = 30, rows = 30, bgcolor = color.yellow, border_width = 1)
	table.cell(table_id = table3, column = 0, row = 1, text = "run")
	table.cell(table_id = table3, column = 1, row = 1, text = str.tostring(bar_index_x_2_table - bar_index_x_1_table))

close_in_bear_atr = y_2 > y_1 and source < plot_line + ta.atr(10) * atr_mul
close_in_bull_atr = y_2 < y_1 and source > plot_line - ta.atr(10) * atr_mul



// Inputs
//
// ### 3 Line Strike
//
showBear3LS = input.bool(title='Show Bearish 3 Line Strike', defval=true, group='3 Line Strike', tooltip="The Bearish 3 Line Strike (3LS-Bear) is a candlestick pattern comprised of 3 bullish (green) candles, " +
         "followed by a bearish engulfing candle (see 'Big A$$ Candles' below).\n\n" +
         "This pattern tends to be best used as a signal of the end of a retracement period as part of a trend continuation strategy.\n\n" +
         "Default: Checked")
showBull3LS = input.bool(title='Show Bullish 3 Line Strike', defval=true, group='3 Line Strike', tooltip="The Bullish 3 Line Strike (3LS-Bull) is a candlestick pattern comprised of 3 bearish (red) candles, " +
         "followed by a bullish engulfing candle (see 'Big A$$ Candles' below).\n\n" +
         "This pattern tends to be best used as a signal of the end of a retracement period as part of a trend continuation strategy.\n\n" +
         "Default: Checked")
showMemeChars = input.bool(title="Plot 3 Line Strike meme symbols", defval=false, group="3 Line Strike", tooltip="If disabled (default), standard shapes will be plotted instead, which can then be further customized on the 'Styles' tab of the indicator settings.\n\n" +
         "If enabled, meme icons hand-selected by Arty himself (🍆 and 🍑) will be plotted for 3LS signals instead of the more typical shapes.\n\n" +
         "Default: Unchecked")
//
//### Engulfing Candles
//
showBearEngulfing= input.bool(title='Show Bearish Big A$$ Candles', defval=false, group='Big A$$ Candles', tooltip="Bearish 'Big A$$ Candles' are the same as Bearish Engulfing candles.")
showBullEngulfing= input.bool(title='Show Bullish Big A$$ Candles', defval=false, group='Big A$$ Candles', tooltip="Bullish 'Big A$$ Candles' are the same as Bullish Engulfing candles.")
//
//### Alerts

showDominantUpperWick= input.bool(title='Show Dominant upper wick', defval=false, group='Dominant')
showDominantLowerWick= input.bool(title='Show Dominant lower wick', defval=false, group='Dominant')
//
//
// This won't actually DO anything, just popping it to note the behavior of the "Any alert() function call" alert type
void = input.bool(title="The new 'Any alert() function call' (dynamic) alerts will be based on what signals are enabled in the indicator settings.", defval=true, tooltip="This does nothing - it's only here to clarify alert functionality.")
//
// End Inputs ###

// Function definitions...
//
// Derive candle "color".  For simplicity, I originally wanted to make this a true/false and have any true doji candles (where open and close are exactly the same)
// either inherit the previous value, or invalidate the setup (which was the original behavior), but that behavior wasn't working as expected.  So for now, we're
// going to do a hack and make this a numeric return instead, where...
//
// -1 -> Red/Bearish
//  0 -> Doji
// +1 -> Green/BUllish
//
getCandleColorIndex(barIndex) =>
    int ret = na
    if (close[barIndex] > open[barIndex])
        ret := 1
    else if (close[barIndex] < open[barIndex])
        ret := -1
    else
        ret := 0
    ret

//
// Check for engulfing candles
isEngulfing(checkBearish) =>
    // In an effort to try and make this a bit more consistent, we're going to calculate and compare the candle body sizes
    // to inform the engulfing or not decision, and only use the open vs close comparisons to identify the candle "color"
    ret = false
    sizePrevCandle = close[1] - open[1] // negative numbers = red, positive numbers = green, 0 = doji
    sizeCurrentCandle = close - open    // negative numbers = red, positive numbers = green, 0 = doji
    isCurrentLagerThanPrevious = (math.abs(sizeCurrentCandle) > math.abs(sizePrevCandle)) ? true : false
    // We now have the core info to evaluate engulfing candles
    switch checkBearish
        true => 
            // Check for bearish engulfing (green candle followed by a larger red candle)
            isGreenToRed = ((getCandleColorIndex(0) < 0) and (getCandleColorIndex(1) > 0)) ? true : false
            ret := (isCurrentLagerThanPrevious and isGreenToRed) ? true : false
        false => 
            // Check for bullish engulfing (red candle followed by a larger green candle)
            isRedToGreen = ((getCandleColorIndex(0) > 0) and (getCandleColorIndex(1) < 0)) ? true : false
            ret := (isCurrentLagerThanPrevious and isRedToGreen) ? true : false
        => ret := false // This should be impossible to trigger...
    ret
//
// Helper functions that wraps the isEngulfing above...
isBearishEngulfuing() =>
    ret = isEngulfing(true)
    ret
//
isBullishEngulfuing() =>
    ret = isEngulfing(false)
    ret
//
// Functions to check for 3 consecutive candles of one color, followed by an engulfing candle of the opposite color
//
// Bearish 3LS = 3 green candles immediately followed by a bearish engulfing candle
is3LSBear() =>
    ret = false
    is3LineSetup = ((getCandleColorIndex(1) > 0) and (getCandleColorIndex(2) > 0) and (getCandleColorIndex(3) > 0)) ? true : false
    ret := (is3LineSetup and isBearishEngulfuing()) ? true : false
    ret
//
// Bullish 3LS = 3 red candles immediately followed by a bullish engulfing candle
is3LSBull() =>
    ret = false
    is3LineSetup = ((getCandleColorIndex(1) < 0) and (getCandleColorIndex(2) < 0) and (getCandleColorIndex(3) < 0)) ? true : false
    ret := (is3LineSetup and isBullishEngulfuing()) ? true : false
    ret


// ### 3 Line Strike
is3LSBearSig = is3LSBear()
is3LSBullSig = is3LSBull()

// Meme plots for the 3LS signal

// close_in_bear_atr = y_2 < y_1 and close > plot_line - ta.atr(10) * atr_mul
// close_in_bull_atr = y_2 > y_1 and close < plot_line + ta.atr(10) * atr_mul
plotchar(close_in_bear_atr and showBull3LS and showMemeChars ? is3LSBullSig : na, char="🍆", color=color.rgb(0, 255, 0, 0), location=location.belowbar, size=size.tiny, text='3LS-Bull', title='3 Line Strike Up (Meme Icon)', editable=false)
plotchar(close_in_bull_atr and showBear3LS and showMemeChars ? is3LSBearSig : na, char="🍑", color=color.rgb(255, 0, 0, 0), location=location.abovebar, size=size.tiny, text='3LS-Bear', title='3 Line Strike Down (Meme Icon)', editable=false)
//
// Standard plots for the 3LS signal

plotshape(close_in_bear_atr and showBull3LS and not showMemeChars ? is3LSBullSig : na, style=shape.triangleup, color=color.rgb(0, 255, 0, 0), location=location.belowbar, size=size.small, text='3LS-Bull', title='3 Line Strike Up')
plotshape(close_in_bull_atr and showBear3LS and not showMemeChars ? is3LSBearSig : na, style=shape.triangledown, color=color.rgb(255, 0, 0, 0), location=location.abovebar, size=size.small, text='3LS-Bear', title='3 Line Strike Down')
// 
// # Alerts
//
// Old-style Alert Conditions
alertcondition(close_in_bear_atr and showBull3LS and is3LSBullSig, title='Bullish 3 Line Strike', message='{{exchange}}:{{ticker}} {{interval}} - Bullish 3 Line Strike')
alertcondition(close_in_bull_atr and showBear3LS and is3LSBearSig, title='Bearish 3 Line Strike', message='{{exchange}}:{{ticker}} {{interval}} - Bearish 3 Line Strike')
//
// New-style alerts
if (close_in_bear_atr and showBull3LS and is3LSBullSig)
    m = syminfo.tickerid + ' ' + timeframe.period + ' - Bullish 3 Line Strike'
    alert(message=str.tostring(m), freq=alert.freq_once_per_bar_close)
if (close_in_bull_atr and showBear3LS and is3LSBearSig)
    m = syminfo.tickerid + ' ' + timeframe.period + ' - Bearish 3 Line Strike'
    alert(message=str.tostring(m), freq=alert.freq_once_per_bar_close)   

// End ###

//### Engulfing Candles

//If current bar open is less than equal to the previous bar close AND current bar open is less than previous bar open AND current bar close is greater than previous bar open THEN True
isBullEngulfingSig = isBullishEngulfuing()
//If current bar open is greater than equal to previous bar close AND current bar open is greater than previous bar open AND current bar close is less than previous bar open THEN True
isBearEngulfingSig = isBearishEngulfuing()

//bullishEngulfing/isBearEngulfingSig return a value of 1 or 0; if 1 then plot on chart, if 0 then don't plot
plotshape(close_in_bear_atr and showBullEngulfing ? isBullEngulfingSig : na, style=shape.triangleup, location=location.belowbar, color=color.rgb(0, 255, 0, 0), size=size.tiny, title='Big A$$ Candle Up')
plotshape(close_in_bull_atr and showBearEngulfing ? isBearEngulfingSig : na, style=shape.triangledown, location=location.abovebar, color=color.rgb(255, 0, 0, 0), size=size.tiny, title='Big A$$ Candle Down')

// Alerts
//
// Old-style alert conditions...
alertcondition(close_in_bear_atr and showBullEngulfing and isBullEngulfingSig, title='Bullish Engulfing', message='{{exchange}}:{{ticker}} {{interval}} - Bullish candle engulfing previous candle')
alertcondition(close_in_bull_atr and showBearEngulfing and isBearEngulfingSig, title='Bearish Engulfing', message='{{exchange}}:{{ticker}} {{interval}} - Bearish candle engulfing previous candle')
//
// New-style alert() functions
// New-style alerts
if (close_in_bear_atr and showBullEngulfing and isBullEngulfingSig)
    m = syminfo.tickerid + ' ' + timeframe.period + ' - Bullish candle engulfing previous candle'
    alert(message=str.tostring(m), freq=alert.freq_once_per_bar_close)
if (close_in_bull_atr and showBearEngulfing and isBearEngulfingSig)
    m = syminfo.tickerid + ' ' + timeframe.period + ' - Bearish candle engulfing previous candle'
    alert(message=str.tostring(m), freq=alert.freq_once_per_bar_close)  

// End ###




//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////wick candle
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


dominant_wick_multiple = input.float(defval = 2.0, title = "dominant wick multiple", minval = 1.0, maxval = 10.0, step = 0.1, group = "candlestick")
recessive_wick_multiple = input.float(defval = 2.0, title = "recessive wick multiple", minval = 0.1, maxval = 10.0, step = 0.1, group = "candlestick")
body_multiple = input.float(defval = 5.0, title = "body multiple", minval = 0.1, maxval = 10.0, step = 0.1, group = "candlestick")

body = math.abs(close - open)
upper_wick = math.abs(math.max(open, close) - high)
lower_wick = math.abs(math.min(open, close) - low)

ATR_upper_wick = ta.sma(upper_wick, 200)
ATR_lower_wick = ta.sma(lower_wick, 200)
ATR_body = ta.sma(body, 200)

// close_in_bear_atr = y_2 > y_1 and source < plot_line + ta.atr(10) * atr_mul
// close_in_bull_atr = y_2 < y_1 and source > plot_line - ta.atr(10) * atr_mul

upper_wick_dominant = (upper_wick > body) and (upper_wick > (ATR_upper_wick * dominant_wick_multiple)) and (body < (ATR_body * body_multiple)) and (lower_wick < (ATR_lower_wick * recessive_wick_multiple)) and close_in_bull_atr
lower_wick_dominant = (lower_wick > body) and (lower_wick > (ATR_lower_wick * dominant_wick_multiple)) and (body < (ATR_body * body_multiple)) and (upper_wick < (ATR_upper_wick * recessive_wick_multiple)) and close_in_bear_atr

plotshape(upper_wick_dominant, title = "upper wick dominant", location = location.abovebar, text = "S", color = color.red, textcolor = color.red)
plotshape(lower_wick_dominant, title = "lower wick dominant", location = location.belowbar, text = "B", color = color.green, textcolor = color.green)


if showDominantUpperWick and barstate.isconfirmed
    alert("Dominant Upper Wick", freq = alert.freq_once_per_bar_close)
if showDominantLowerWick and barstate.isconfirmed
    alert("Dominant Lower Wick", freq = alert.freq_once_per_bar_close)