LazerALERT V1
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//@version=5
indicator('LaserALERT V1', shorttitle='LaserALERT', overlay=true, max_bars_back=4900)


import livingdraculaog/CandleStore/10 as CandleStore

////# import candle analytics
redCandle           = CandleStore.redCandle()
greenCandle         = CandleStore.greenCandle()

//         _
//      __| |___
//   .' _| |__ '.u
//  .' .- |    -. '.
// .' |   |( |\  | '.
// | <    |  | |  | |
// '. |   |( |/  | .'
//  '. '-_|____-' .'
//   '.________.'
//
//
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// Desc: This script is designed to spot trade with weak signals and short/long with trend.
// // © livingdraculaog
// ////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////
// // Components Used in this Strategy
// // Features:
// // 1. RSI Support & Resistance - helps should where the ceiling and floor are as well as when an asset is overbought / oversold. Originally by DGT © dgtrd ()
// // 2. Triple Moving Average forcasting - helps predict death crosses and golden crosses
// // 3. Retracement price - if the current price exceeds this, it will continue in the same directio. Originally by TLB
// // 4. EMA Candle Colors with Volume-based opacity - helps show the strength and momentum of a candle
// // 5. Market Band and Pivot lines - to determine the long term trend
// // 6. Custom UI values and estimating profitably of any given position you may want to take.
// // 7. Wick Analysis
// ////////////////////////////////////////////////////////////////////

__groupUI = 'UI Display'
groupPivots = 'Scalping Length'
ScalpingDescription = 'This will change the time frame for Pivot lines and conseqently change every other estimate.'
showPivots          = input.bool(defval=false, title='Scalping Lines 🔪', group=__groupUI, inline='00')
higherTF            = input.timeframe('', title='Time Frame', inline='00', group=__groupUI, tooltip=ScalpingDescription)
showRSI             = input.bool(defval=false, title='Show RSI', group=__groupUI, inline='01')
// useMAtable          = input.bool(false, title="show MA", type=input.bool, group=__groupUI, inline="01")
useRetracement      = input.bool(false, title='show Retracement', group=__groupUI, inline='01')



groupCustom = 'Custom Settings'
useQuantity     = input.float(100.0, title='Quantity', group=groupCustom, inline='00')
useFEE          = input.float(0.02, title='Fee', group=groupCustom, inline='00')
useRound        = input.int(2, title='Round', group=groupCustom, inline='00')

useCustomEntry  = input.float(1.0, title='Entry: ', group=groupCustom, inline='01')
useCustomExit   = input.float(2.0, title='Exit: ', group=groupCustom, inline='01')
useCustom       = input.bool(false, title='Use Custom?', group=groupCustom, inline='01')

_groupMA = 'MTF Triple MA Forcasting'
useMAline           = input.bool(false, title='show MA', group=_groupMA, inline='00')
maForecast          = input.bool(true, title=' Forecast', group=_groupMA, inline='00')
maResolution        = input.timeframe('', title='', group=_groupMA, inline='00')
useMAwidth          = input.int(2, title='', inline='00', group=_groupMA)
useEntryOptions     = input.string("MA1","Entry↕", inline = "01", group =_groupMA, options = ["MA1","MA2","MA3","_pMA1a","_pMA1b","_pMA2a","_pMA2b","_pMA3a","_pMA3b"])
useExitOptions      = input.string("MA2","EXIT↕", inline = "01", group =_groupMA, options = ["MA1","MA2","MA3","_pMA1a","_pMA1b","_pMA2a","_pMA2b","_pMA3a","_pMA3b"])
useforcast          = input.int(2, title='forcast', inline='01', group=_groupMA)

ma1Color            = input.color(title='MA1', defval=color.blue, group=_groupMA, inline='MA1')
ma1Type             = input.string('EMA', title='', options=['DEMA', 'EMA', 'HMA', 'LSMA', 'MA', 'RMA', 'SMA', 'SWMA', 'TEMA', 'TMA', 'VWMA', 'WMA'], group=_groupMA, inline='MA1')
ma1Length           = input.int(title='', defval=10, minval=1, group=_groupMA, inline='MA1')
ma1Source           = input.source(title='', defval=close, group=_groupMA, inline='MA1')

ma2Color            = input.color(title='MA2', defval=color.green, group=_groupMA, inline='MA2')
ma2Type             = input.string('EMA', title='', options=['DEMA', 'EMA', 'HMA', 'LSMA', 'MA', 'RMA', 'SMA', 'SWMA', 'TEMA', 'TMA', 'VWMA', 'WMA'], group=_groupMA, inline='MA2')
ma2Length           = input.int(title='', defval=50, minval=1, group=_groupMA, inline='MA2')
ma2Source           = input.source(title='', defval=close, group=_groupMA, inline='MA2')

ma3Color            = input.color(title='MA3', defval=color.red, group=_groupMA, inline='MA3')
ma3Type             = input.string('EMA', title='', options=['DEMA', 'EMA', 'HMA', 'LSMA', 'MA', 'RMA', 'SMA', 'SWMA', 'TEMA', 'TMA', 'VWMA', 'WMA'], group=_groupMA, inline='MA3')
ma3Length           = input.int(title='', defval=200, minval=1, group=_groupMA, inline='MA3')
ma3Source           = input.source(title='', defval=close, group=_groupMA, inline='MA3')


__groupCandles = 'EMA Candles Settings'
////# Volume Candles
useVolume           = input.bool(defval=true, title='Use Volume Opacity?', group=__groupCandles, inline='00')
volumeDown1         = input.int(100, 'Bearish: ', minval=1, group=__groupCandles, inline='01')
volumeDown2         = input.int(50, '', minval=1, group=__groupCandles, inline='01')
volumeDown3         = input.int(100, '', minval=1, group=__groupCandles, inline='01')
///
volumeUp1           = input.int(1, 'Bullish', minval=1, group=__groupCandles, inline='02')
volumeUp2           = input.int(1, '', minval=1, group=__groupCandles, inline='02')
volumeUp3           = input.int(1, '', minval=1, group=__groupCandles, inline='02')
////# Candle Colors
// weak trends 
readCandleSticks    = input.bool(defval=true, title='Use EMA Candles', group=__groupCandles, inline='03')
_emaDOWN            = input.color(defval=color.new(#660000, 0), title='', inline='03', group=__groupCandles)
_StrongDown         = input.color(defval=color.new(#004d40, 0), title='', inline='03', group=__groupCandles)
// neutral 
_naCandle           = input.color(defval=color.new(#ffffff, 0), title='', inline='03', group=__groupCandles)
// strong trends
_emaUP              = input.color(defval=color.new(#009688, 0), title='', inline='03', group=__groupCandles)
_StrongUP           = input.color(defval=color.new(#ffeb3b, 0), title='', inline='03', group=__groupCandles)
//

////# Display each
showEMAdown         = input.bool(defval=false, title='Down ', inline='04', group=__groupCandles)
showStrongEMAdown   = input.bool(defval=false, title='Strong Down ', inline='04', group=__groupCandles)
showEMAneutral      = input.bool(defval=false, title='Neutral', inline='04', group=__groupCandles)
showEMAup           = input.bool(defval=false, title='Up ', inline='04', group=__groupCandles)
showStrongEMAup     = input.bool(defval=false, title='Strong Up ', inline='04', group=__groupCandles)
////# 
candle              = input.source(defval=close, title='Source', group=__groupCandles, inline='05')
fast                = input.int(defval=5, title='Fast EMA', group=__groupCandles, inline='05')  //Fast EMA Band
slow                = input.int(defval=26, title='Slow EMA', group=__groupCandles, inline='05')  //Slow EMA Band
length              = input.int(21, 'volume', minval=1, group=__groupCandles, inline='05')

// ////# Retracement forcasting
__groupRetracement = 'Retracement'
ZZprd           = input.int(defval=3, title='Retracement', minval=2, maxval=30, inline='00', group=__groupRetracement)  // if res1 exists, set it to 30
zzlinestyle_    = input.string(defval='Dashed', title='Style', options=['Solid', 'Dashed', 'Dotted'], group=__groupRetracement, inline='00')
showlevels      = input.bool(defval=true, title='Show', inline='00', group=__groupRetracement)



////////////////////////////////////////////////////////////////////}
////# Trend logic
////////////////////////////////////////////////////////////////////{
/////// LOGIC
C_DownTrend = true
C_UpTrend = true
var trendRule1 = 'SMA50'
var trendRule2 = 'SMA50, SMA200'
var trendRule = input.string(trendRule1, 'Detect Trend Based On', options=[trendRule1, trendRule2, 'No detection'], group=__groupCandles)

if trendRule == trendRule1
    priceAvg = ta.sma(close, 50)
    C_DownTrend := close < priceAvg
    C_UpTrend := close > priceAvg
    C_UpTrend

if trendRule == trendRule2
    sma200 = ta.sma(close, 200)
    sma50 = ta.sma(close, 50)
    C_DownTrend := close < sma50 and sma50 < sma200
    C_UpTrend := close > sma50 and sma50 > sma200
    C_UpTrend
C_Len = 14  // ema depth for bodyAvg
C_ShadowPercent = 5.0  // size of shadows
C_ShadowEqualsPercent = 100.0
C_DojiBodyPercent = 5.0
C_Factor = 2.0  // shows the number of times the shadow dominates the candlestick body

C_BodyHi = math.max(close, open)
C_BodyLo = math.min(close, open)
C_Body = C_BodyHi - C_BodyLo
C_BodyAvg = ta.ema(C_Body, C_Len)
C_SmallBody = C_Body < C_BodyAvg
C_LongBody = C_Body > C_BodyAvg
C_UpShadow = high - C_BodyHi
C_DnShadow = C_BodyLo - low
C_HasUpShadow = C_UpShadow > C_ShadowPercent / 100 * C_Body
C_HasDnShadow = C_DnShadow > C_ShadowPercent / 100 * C_Body
C_WhiteBody = open < close
C_BlackBody = open > close
C_Range = high - low
C_IsInsideBar = C_BodyHi[1] > C_BodyHi and C_BodyLo[1] < C_BodyLo
C_BodyMiddle = C_Body / 2 + C_BodyLo
C_ShadowEquals = C_UpShadow == C_DnShadow or math.abs(C_UpShadow - C_DnShadow) / C_DnShadow * 100 < C_ShadowEqualsPercent and math.abs(C_DnShadow - C_UpShadow) / C_UpShadow * 100 < C_ShadowEqualsPercent
C_IsDojiBody = C_Range > 0 and C_Body <= C_Range * C_DojiBodyPercent / 100
C_Doji = C_IsDojiBody and C_ShadowEquals

patternLabelPosLow = low - ta.atr(30) * 0.6
patternLabelPosHigh = high + ta.atr(30) * 0.6


////////////////////////////////////////////////////////////////////}
////# STANDARD Candlestick Pattern Recognition
////////////////////////////////////////////////////////////////////{

__groupCandlePatterns   = 'Candle Patterns'

useEngulfing            = input.bool(false, title="Engulfing",  group=__groupCandlePatterns, inline="patterns")
useDoji                 = input.bool(false, title="Doji",       group=__groupCandlePatterns, inline="patterns")
useHammer               = input.bool(false, title="Hammer",     group=__groupCandlePatterns, inline="patterns")
useHarami               = input.bool(false, title="Harami",     group=__groupCandlePatterns, inline="patterns")
useKicker               = input.bool(false, title="Kicker",     group=__groupCandlePatterns, inline="patterns")
useStars                = input.bool(false, title="Stars",      group=__groupCandlePatterns, inline="patterns")

EngulfingBullish    =   CandleStore._isEngulfingBullish()
EngulfingBearish    =   CandleStore._isEngulfingBearish()

dojiup              =   CandleStore.dojiup()
dojidown            =   CandleStore.dojidown()

Hammer              =   CandleStore.Hammer()
InvertedHammer      =   CandleStore.InvertedHammer()

BearishHarami       =   CandleStore.BearishHarami()
BullishHarami       =   CandleStore.BullishHarami()

BullishKicker       =   CandleStore.BullishKicker()
BearishKicker       =   CandleStore.BearishKicker()

EveningStar         =   CandleStore.EveningStar()
MorningStar         =   CandleStore.MorningStar()
ShootingStar        =   CandleStore.ShootingStar()

BullishBelt         =   CandleStore.BullishBelt()


HangingMan          =   CandleStore.HangingMan()
DarkCloudCover      =   CandleStore.DarkCloudCover()


plotshape(series = useEngulfing and EngulfingBullish  ? bar_index : na,  style=shape.triangleup, location=location.belowbar, text='Engulfing \n Bullish',textcolor=color.new(color.green, 0),        color=color.new(color.green, 0)) 
plotshape(series = useEngulfing and EngulfingBearish  ? bar_index : na,  style=shape.triangledown, location=location.abovebar, text='Engulfing \n Bearish',textcolor=color.new(color.red, 0),        color=color.new(color.red, 0)) 

plotshape(series = useDoji and dojiup                ? bar_index : na,   style=shape.triangledown, location=location.abovebar, text='Doji \n Up',textcolor=color.new(color.green, 0),        color=color.new(color.green, 0)) 
plotshape(series = useDoji and dojidown              ? bar_index : na,   style=shape.triangledown, location=location.belowbar, text='Doji \n Down',textcolor=color.new(color.red, 0),        color=color.new(color.red, 0)) 

plotshape(series = useHammer and Hammer              ? bar_index : na,   style=shape.triangledown, location=location.abovebar, text='Hammer',textcolor=color.new(color.green, 0),            color=color.new(color.green, 0)) 
plotshape(series = useHammer and InvertedHammer      ? bar_index : na,   style=shape.triangledown, location=location.belowbar, text='InvertedHammer',textcolor=color.new(color.red, 0) ,     color=color.new(color.red, 0)) 

plotshape(series = useKicker and BullishKicker       ? bar_index : na,   style=shape.triangleup, location=location.belowbar, text='BullishKicker',textcolor=color.new(color.green, 0),     color=color.new(color.green, 0)) 
plotshape(series = useKicker and BearishKicker       ? bar_index : na,   style=shape.triangledown, location=location.abovebar, text='BearishKicker',textcolor=color.new(color.red, 0),       color=color.new(color.red, 0)) 

plotshape(series = useStars and MorningStar          ? bar_index : na,   style=shape.diamond, location=location.belowbar, text='MorningStar',textcolor=color.new(color.green, 0),            color=color.new(color.yellow, 0)) 
plotshape(series = useStars and EveningStar          ? bar_index : na,   style=shape.diamond, location=location.abovebar, text='EveningStar',textcolor=color.new(color.red, 0),            color=color.new(color.yellow, 0)) 
plotshape(series = useStars and ShootingStar         ? bar_index : na,   style=shape.diamond, location=location.belowbar, text='ShootingStar',textcolor=color.new(color.red, 0),             color=color.new(color.yellow, 0)) 

plotshape(series = useHarami and BullishHarami       ? bar_index : na,   style=shape.triangleup, location=location.belowbar, text='BullishHarami',textcolor=color.new(color.green, 0),     color=color.new(color.green, 0)) 
plotshape(series = useHarami and BearishHarami       ? bar_index : na,   style=shape.triangledown, location=location.abovebar, text='BearishHarami',textcolor=color.new(color.red, 0),       color=color.new(color.red, 0)) 





////# CandleStick Inputs

__groupTheme = 'Theme Settings'
// CandleType = input(title = "Pattern Type", defval="Both", options=["Bullish", "Bearish", "Both"], group=__groupTheme)
label_color_StrongBullish = input.color(color.new(color.green, 1), 'Bull Band', inline='00', group=__groupTheme)
label_color_StrongBearish = input.color(color.new(#f20a05, 1), 'Bear Band', inline='00', group=__groupTheme)

label_color_bullish = input.color(color.new(color.green, 90), 'Bullish', group=__groupTheme, inline='01')
label_color_neutral = input.color(color.gray, 'Neutral', group=__groupTheme, inline='01')
label_color_bearish = input.color(color.new(color.red, 90), 'Bearish', group=__groupTheme, inline='01')



////# Types


_groupBullish = 'Bullish Legend'
showBullish         = input.bool(defval=false, title='Show \n Bullish', inline='00', group=_groupBullish)
showBearishSell     = input.bool(defval=false, title='Bearish \n Sell', inline='00', group=_groupBullish)
showYellow          = input.bool(defval=false, title='Show Yellow Variations', inline='00', group=_groupBullish)
showVolumeBuy       = input.bool(defval=false, title='Show \n Volume Buy', inline='00', group=_groupBullish)

_groupBearish = 'Bearish Legend'
showBearish         = input.bool(defval=false, title='Show \n Bearish', inline='00', group=_groupBearish)
showBearishBuy      = input.bool(defval=false, title='Bearish Buy ', inline='00', group=_groupBearish)
showGreen           = input.bool(defval=false, title='Show Green ', inline='00', group=_groupBearish)
showVolumeSell      = input.bool(defval=false, title='Show \n Volume Sell', inline='00', group=_groupBullish)

////#Hard Coded Values
_bearRowBG = color.new(color.red, 80)



////////////////////////////////////////////////////////////////////}
////# Wick Analysis
////////////////////////////////////////////////////////////////////{

// This Indicator measures the wick parts of candles and sum it up. 
// Wick part of candle is a sign of strength that's why it measures the 60 bars of candles wick. then sum it up and converted it in percentage. 
// The output is indicated in the last 10 candles. that's how simple this indicator is but very useful to analyze the strength of every candles.
// The upper numbers is the bear power.
// The lower numbers is the bull power.
wickDescription = 'This Indicator measures candle wick and sum it up. The UPPER numbers is the BEAR power and the LOWER numbers is the BULL power.'
useWick         = input.bool(false, title='Wick Analysis', group=__groupUI, inline='02', tooltip=wickDescription)


bear            = high - (open > close ? open : close)
bull            = (open < close ? open : close) - low
barlength       = close > open ? close - open : open - close


sumbarlenght = math.sum(barlength, 60)
sumbull = math.sum(bear, 60) / sumbarlenght * 100
sumbear = math.sum(bull, 60) / sumbarlenght * 100

bullPower_converted = str.tostring(math.floor(sumbull))
bearPower_converted = str.tostring(math.floor(sumbear))

////# wick
if useWick
    bull_label = label.new(x=bar_index, y=na, text=bullPower_converted, yloc=yloc.belowbar, textcolor=color.red, style=label.style_none, size=size.normal)
    bear_label = label.new(x=bar_index, y=na, text=bearPower_converted, yloc=yloc.abovebar, textcolor=color.green, style=label.style_none, size=size.normal)
    bear_label
////


// threeGreenCandles = close[2] > open[2] and close[1] > open[1] and close > open
// sixGreen = close[5] > open[5] and close[4] > open[4] and close[3] > open[3] and close[2] > open[2] and close[1] > open[1] and close > open
// threeRedCandles = close[2] < open[2] and close[1] < open[1] and close < open
// sixRed = close[5] < open[5] and close[4] < open[4] and close[3] < open[3] and close[2] < open[2] and close[1] < open[1] and close < open


////////////////////////////////////////////////////////////////////}
////# EMA Candle
////////////////////////////////////////////////////////////////////{
//EMA CANDLESTICKS
fe = ta.ema(candle, fast)
se = ta.ema(candle, slow)

// NA
isFastOverSlow = fe > se
isCrossUnderSlow = ta.crossunder(candle, se)  // NA UP?
isCrossOverSlow = ta.crossover(candle, se)  // NA Down?


// BEAR
isStrongUp = candle > se  // yellow
isDown = candle < fe  // black

// BULL
isStrongDown = candle < se  // dark green
isUp = candle > fe  // green

////# Labels
_emaUPTip = 'when isFastOverSlow=false or isCrossUnderSlow=false and isUp=false'
_blackTip = 'Black is signals a DOWN Trend and used to sniffout bull traps (green candles with downward trend).\nBlack with RED is RED candle with down trend...\n Black with GREEN outline is a GREEN candle with down trend...'
_whiteTip = 'White signals the MIDDLE of a trend in either direction. It is generated when there is a Cross Under SLOW EMA BAND using```crossunder(CANDLE, SE)```...\nFor Reference:\nCANDLE default value is \'close\'...\nFE=ema(candle,fast)\nSE=ema(candle,slow). Conditional Logic:\n1. when isFastOverSlow=True and isCrossUnderSlow=True'
_redTip = 'Red is bad...'
_greenTip = 'Green is bad...'
_darkTip = 'Dark Green may signify a \'floor\' may berming...'

////    Coloring Algorithm  ////
////# Volume
avrg = ta.sma(volume, length)

vold1 = volume > avrg * 1.5 and redCandle
vold2 = volume >= avrg * 0.5 and volume <= avrg * 1.5 and redCandle
vold3 = volume < avrg * 0.5 and redCandle

volu1 = volume > avrg * 1.5 and greenCandle
volu2 = volume >= avrg * 0.5 and volume <= avrg * 1.5 and greenCandle
volu3 = volume < avrg * 0.5 and greenCandle

//// Set the opacity based on the volume
// volume down?
cold1 = volumeDown1
cold2 = volumeDown2
cold3 = volumeDown3

// vol up?
hot1 = volumeUp1
hot2 = volumeUp2
hot3 = volumeUp3

////# Convert EMA colors to volume-based colors
createVolumeCandles(_color) =>
    color = vold1 ? color.new(_color, cold1) : vold2 ? color.new(_color, cold2) : vold3 ? color.new(_color, cold3) : volu1 ? color.new(_color, hot1) : volu2 ? color.new(_color, hot2) : volu3 ? color.new(_color, hot3) : na
    color
//// Pass in user selected color, than adjust opacity based on volume and return a new color
//// The returned color will than be passed into BC
___emaDOWN      = useVolume ? createVolumeCandles(_emaDOWN) : _emaDOWN
___StrongDown   = useVolume ? createVolumeCandles(_StrongDown) : _StrongDown
// neutral 
___naCandle     = useVolume ? createVolumeCandles(_naCandle) : _naCandle
// strong trends
___emaUP        = useVolume ? createVolumeCandles(_emaUP) : _emaUP
___StrongUP     = useVolume ? createVolumeCandles(_StrongUP) : _StrongUP

////    Coloring Algorithm  ////
// outlineColors=
bc              = isFastOverSlow ? isCrossUnderSlow ? ___naCandle : isUp ? ___emaUP : isStrongUp ? ___StrongUP : _naCandle : isCrossOverSlow ? ___naCandle : isDown ? ___emaDOWN : isStrongDown ? ___StrongDown : isUp ? isStrongUp ? ___StrongUP : na : na
// bc= isFastOverSlow ? isCrossUnderSlow ? _naCandle : isUp ? _emaUP : isStrongUp ? _StrongUP : _naCandle : isCrossOverSlow ? _naCandle : isDown ? _emaDOWN : isStrongDown ? _StrongDown : isUp ? isStrongUp ? _StrongUP :na :na
___blank        = isFastOverSlow ? isCrossUnderSlow ? na : isUp ? na : isStrongUp ? na : na : isCrossOverSlow ? na : isDown ? na : isStrongDown ? na : isUp ? isStrongUp ? na : na : na
// variations for each
__isNA          = isFastOverSlow ? isCrossUnderSlow ? true : isUp ? na : isStrongUp ? na : true : isCrossOverSlow ? true : isDown ? na : isStrongDown ? na : isUp ? isStrongUp ? na : na : na
__emaUP         = isFastOverSlow ? isCrossUnderSlow ? na : isUp ? true : na ? na : na : isCrossOverSlow ? na : isDown ? na : isStrongDown ? na : isUp ? isStrongUp ? na : na : na
__isStrongUP    = isFastOverSlow ? isCrossUnderSlow ? na : isUp ? na : isStrongUp ? true : na : isCrossOverSlow ? na : isDown ? na : isStrongDown ? na : isUp ? isStrongUp ? true : na : na
__emaDOWN       = isFastOverSlow ? isCrossUnderSlow ? na : isUp ? na : isStrongUp ? na : na : isCrossOverSlow ? na : isDown ? true : isStrongDown ? na : isUp ? isStrongUp ? na : na : na
__isStrongDown  = isFastOverSlow ? isCrossUnderSlow ? na : isUp ? na : isStrongUp ? na : na : isCrossOverSlow ? na : isDown ? na : isStrongDown ? true : isUp ? isStrongUp ? na : na : na

////# Label Candles
noCross         = not isFastOverSlow and not isCrossUnderSlow
__notEMA        = not __isNA and not __emaUP and not __isStrongUP and not __emaDOWN and not __isStrongDown

////////////////////////////////////////////////////////////////////
condition1                  = __isStrongUP and EngulfingBullish
condition2                  = __isStrongUP and greenCandle and EngulfingBullish
strongEngulfing             = __isStrongUP and greenCandle and not EngulfingBearish

__falseUp                   = greenCandle and not __isStrongUP and not __emaUP
__falseUP2                  = greenCandle and __isStrongDown
__DisplayYellowEngulfing    = __isStrongUP and EngulfingBearish
__DisplayRedEngulfing       = __isStrongDown and EngulfingBearish
__DisplayWhiteEngulfing     = __isNA and EngulfingBearish

////# Volume Based Conditions
_VolumeBuy                  = __isStrongDown and volu1 and greenCandle
_VolumeSell                 = __isStrongUP and vold2 and redCandle

////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////}
// Originally from ZZ Forecast Retracement © LonesomeTheBlue
////////////////////////////////////////////////////////////////////{


// check highesy/lowest levels and create zigzag
float _ph       = ta.highestbars(high, ZZprd) == 0 ? high : na
float _pl       = ta.lowestbars(low, ZZprd) == 0 ? low : na

var dir = 0
iff_1 = _pl and na(_ph) ? -1 : dir
dir := _ph and na(_pl) ? 1 : iff_1

var zigzag      = array.new_float(0)
oldzigzag       = array.new_float(2)  // keep last point

////# init zigzag lines
var zzlines = array.new_line(0)
var zzlinestyle = line.style_dashed

////# variables to check if any circle broken
var bool uptbroken      = false
var bool downtbroken    = false
uptexist                = false
downtexist              = false

////# labels
var label upt_label     = na
var label downt_label   = na

////# definitions
width               = (ta.highest(292) - ta.lowest(292)) / 107
var up_circle_lines = array.new_line(0)
var dn_circle_lines = array.new_line(0)



////# to get rid of consistency warning, keep close in a array
var cls = array.new_float(500, na)
array.unshift(cls, close)
array.pop(cls)


////# ZZ Utilities
add_to_zigzag(value, bindex) =>  // 
    array.unshift(zigzag, bindex)
    array.unshift(zigzag, value)
    if array.size(zigzag) > 8
        array.pop(zigzag)
        array.pop(zigzag)
update_zigzag(value, bindex) =>  // 
    if array.size(zigzag) == 0
        add_to_zigzag(value, bindex)
    else
        if dir == 1 and value > array.get(zigzag, 0) or dir == -1 and value < array.get(zigzag, 0)
            array.set(zigzag, 0, value)
            array.set(zigzag, 1, bindex)
        0.
///////////
// calculate location of y level in a point
calc_pos_circle_rad(center_y_lev, center_bindex, radius, cal_bindex) =>
    loc_diff = math.abs(center_bindex - cal_bindex)
    rad = math.sqrt(math.pow(radius, 2) - math.pow(loc_diff * width, 2))
    rad
// draw uptrend circle until last candle 
draw_up_circle(radius) =>
    ind = dir == 1 ? 0 : 2
    nxt = dir == 1 ? 2 : 4
    broken = false
    if showlevels and bar_index - 1 > array.get(zigzag, nxt + 1)
        last_x = math.round(array.get(zigzag, nxt + 1))
        last_y = array.get(zigzag, nxt)
        for x = array.get(zigzag, nxt + 1) + 1 to bar_index - 1 by 1
            yloc = array.get(zigzag, ind) - calc_pos_circle_rad(array.get(zigzag, ind), array.get(zigzag, ind + 1), radius, x)
            if na(yloc)
                break
            if not na(yloc) and array.get(cls, math.round(bar_index - x)) < yloc
                broken := true
                break
            array.push(up_circle_lines, line.new(x1=last_x, y1=last_y, x2=math.round(x), y2=yloc, color=color.lime, width=2))
            last_x += 1
            last_y := yloc
            last_y
    broken
//
// draw downtrend circle until last candle    
draw_down_circle(radius) =>  //
    ind = dir == 1 ? 2 : 0
    nxt = dir == 1 ? 4 : 2
    broken = false
    if showlevels and bar_index - 1 > array.get(zigzag, nxt + 1)
        last_x = math.round(array.get(zigzag, nxt + 1))
        last_y = array.get(zigzag, nxt)
        for x = array.get(zigzag, nxt + 1) + 1 to bar_index - 1 by 1
            yloc = array.get(zigzag, ind) + calc_pos_circle_rad(array.get(zigzag, ind), array.get(zigzag, ind + 1), radius, x)
            if na(yloc)
                break
            if not na(yloc) and array.get(cls, math.round(bar_index - x)) > yloc
                broken := true
                break
            array.push(dn_circle_lines, line.new(x1=last_x, y1=last_y, x2=math.round(x), y2=yloc, color=color.red, width=2))
            last_x += 1
            last_y := yloc
            last_y
    broken
/////
Round_it(value) => math.round(value / syminfo.mintick) * syminfo.mintick

if array.size(zigzag) > 1
    array.set(oldzigzag, 0, array.get(zigzag, 0))
    array.set(oldzigzag, 1, array.get(zigzag, 1))
//
dirchanged = dir != dir[1]
if showlevels and _ph or _pl
    if dirchanged
        add_to_zigzag(dir == 1 ? _ph : _pl, bar_index)
    else
        update_zigzag(dir == 1 ? _ph : _pl, bar_index)
//

if barstate.isfirst  //
    zzlinestyle := zzlinestyle_ == 'Solid' ? line.style_solid : zzlinestyle_ == 'Dashed' ? line.style_dashed : line.style_dotted
    array.push(zzlines, line.new(x1=bar_index, y1=close, x2=bar_index - 1, y2=close, style=zzlinestyle))
    array.push(zzlines, line.new(x1=bar_index, y1=close, x2=bar_index - 1, y2=close, style=zzlinestyle))
//

var zzTOPValue = 0.0
var zzBOTTOMValue = 0.0
__BOTTOMlabel = 'if the current candle closes BELOW this, open a short'
__TOPlabel = 'if the current candle closes ABOVE this, open a long'

////# Retracement Logic 
if array.size(zigzag) >= 6
    // radius of circles
    r1 = math.sqrt(math.pow(array.get(zigzag, 0) - array.get(zigzag, 2), 2) + math.pow((array.get(zigzag, 1) - array.get(zigzag, 3)) * width, 2))
    r2 = math.sqrt(math.pow(array.get(zigzag, 2) - array.get(zigzag, 4), 2) + math.pow((array.get(zigzag, 3) - array.get(zigzag, 5)) * width, 2))
    radius_up = dir == 1 ? r1 : r2
    radius_down = dir == 1 ? r2 : r1
    // draw uptrend circle if needed
    if dirchanged or width != width[1] or dir == 1 and (array.get(zigzag, 0) != array.get(oldzigzag, 0) or array.get(zigzag, 1) != array.get(oldzigzag, 1))
        uptbroken := false
        if array.size(up_circle_lines) > 0
            for x = 0 to array.size(up_circle_lines) - 1 by 1
                line.delete(array.pop(up_circle_lines))
        uptbroken := draw_up_circle(radius_up)
        uptbroken
    // draw downtrend circle if needed
    if dirchanged or width != width[1] or dir == -1 and (array.get(zigzag, 0) != array.get(oldzigzag, 0) or array.get(zigzag, 1) != array.get(oldzigzag, 1))
        downtbroken := false
        if array.size(dn_circle_lines) > 0
            for x = 0 to array.size(dn_circle_lines) - 1 by 1
                line.delete(array.pop(dn_circle_lines))
        downtbroken := draw_down_circle(radius_down)
        downtbroken
    // calculate/check and draw part of uptrend circle for last last
    if not uptbroken
        ind = dir == 1 ? 0 : 2
        yloc = array.get(zigzag, ind) - calc_pos_circle_rad(array.get(zigzag, ind), array.get(zigzag, ind + 1), radius_up, bar_index)
        if not na(yloc) and close >= yloc
            uptexist := true
            lasty = array.get(zigzag, ind) - calc_pos_circle_rad(array.get(zigzag, ind), array.get(zigzag, ind + 1), radius_up, bar_index - 1)
            array.push(up_circle_lines, line.new(x1=bar_index - 1, y1=lasty, x2=bar_index, y2=yloc, color=color.lime, width=2))
            if showlevels
                label.delete(upt_label)
                zzTOPValue := Round_it(yloc)
                //# TODO:   log time_close when close is > 
                upt_label := label.new(x=bar_index, y=yloc, text='Bottom Retracement: ' + str.tostring(zzTOPValue), color=color.lime, textcolor=color.black, style=label.style_label_up, tooltip=__BOTTOMlabel)
                upt_label

        if not na(yloc) and close < yloc
            uptbroken := true
            uptbroken
    // calculate/check and draw part of downtrend circle for last last
    if not downtbroken
        ind = dir == 1 ? 2 : 0
        yloc = array.get(zigzag, ind) + calc_pos_circle_rad(array.get(zigzag, ind), array.get(zigzag, ind + 1), radius_down, bar_index)
        if not na(yloc) and close <= yloc
            downtexist := true
            lasty = array.get(zigzag, ind) + calc_pos_circle_rad(array.get(zigzag, ind), array.get(zigzag, ind + 1), radius_down, bar_index - 1)
            array.push(dn_circle_lines, line.new(x1=bar_index - 1, y1=lasty, x2=bar_index, y2=yloc, color=color.red, width=2))
            if showlevels
                label.delete(downt_label)
                zzBOTTOMValue := Round_it(yloc)  //#
                downt_label := label.new(x=bar_index, y=yloc, text='Top Retracement: ' + str.tostring(zzBOTTOMValue), color=color.red, textcolor=color.white, style=label.style_label_down, tooltip=__TOPlabel)
                downt_label
        if not na(yloc) and close > yloc
            downtbroken := true
            downtbroken
////////}




////////////////////////////////////////////////////////////////////}
////# RSI Support & Resistance by DGT © dgtrd
////////////////////////////////////////////////////////////////////{

////# Support & Resistance by DGT UI
groupSupportResistance      = 'RSI Support & Resistance'
i_supportResistance         = input.bool(true,  "Support Resistance Lines",    inline='options', group=groupSupportResistance)
i_fill                      = input.bool(false, "Bull/Bear Zones",       inline='options', group=groupSupportResistance)
i_obos                      = input.bool(true,  "Overbought/Oversold",   inline='options 2', group=groupSupportResistance)

i_source                    = input.string('Price (close)', 'Source', options=['Price (close)', 'On Balance Volume (OBV)'], inline='RSI', group=groupSupportResistance)
i_length                    = input.int(14, '  Length', minval=1, inline='RSI', group=groupSupportResistance)

i_obThreshold               = input.int(70, 'Overboght', minval=50, maxval=100, inline='Thresh', group=groupSupportResistance)
i_osThreshold               = input.int(30, 'Oversold', minval=1, maxval=50, inline='Thresh', group=groupSupportResistance)

i_bullZone                  = input.int(60, 'Bull Zone', minval=50, maxval=65, inline='Zones', group=groupSupportResistance)
i_bearZone                  = input.int(40, 'Bear Zone', minval=35, maxval=50, inline='Zones', group=groupSupportResistance)


// Functions ════════════════════════════════════════════════════════════════════════════════════ //
f_getPrice(_osc, _thresh, _cross) =>
    avgHigh = math.avg(high, close)
    avgLow = math.avg(low, close)
    var return_1 = 0.
    if _cross == 'over' or _cross == 'both'
        if ta.crossover(_osc, _thresh)
            return_1 := avgHigh
            return_1
    if _cross == 'under' or _cross == 'both'
        if ta.crossunder(_osc, _thresh)
            return_1 := avgLow
            return_1
    return_1
// -Calculations ════════════════════════════════════════════════════════════════════════════════ //

oscillator                  = ta.rsi(i_source == 'Price (close)' ? close : ta.obv, i_length)
crossover_overbought        = f_getPrice(oscillator, i_obThreshold, 'over')
crossunder_overbought       = f_getPrice(oscillator, i_obThreshold, 'under')
bullZone                    = f_getPrice(oscillator, i_bullZone, 'both')
bearZone                    = f_getPrice(oscillator, i_bearZone, 'both')
crossover_oversold          = f_getPrice(oscillator, i_osThreshold, 'over')
crossunder_oversold         = f_getPrice(oscillator, i_osThreshold, 'under')
overBought                  = oscillator > i_obThreshold
RSIsell                     = i_obos and overBought
underBought                 = oscillator < i_osThreshold
RSIbuy                      = i_obos and underBought

// -Plotting ════════════════════════════════════════════════════════════════════════════════════ //

plot_crossover_overbought   = plot(i_supportResistance and crossover_overbought > 0 ? crossover_overbought : na, 'Crossover Overbought', crossover_overbought == crossover_overbought[1] ? color.green : na, 1)
plot_crossunder_overbought  = plot(i_supportResistance and crossunder_overbought > 0 ? crossunder_overbought : na, 'Crossunder Overbought', crossunder_overbought == crossunder_overbought[1] ? color.green : na, 1, plot.style_cross)
plot_bullZone               = plot(i_supportResistance and bullZone > 0 ? bullZone : na, 'Cross Bull Zone', bullZone == bullZone[1] ? color.green : na, 1)


plot_bearZone               = plot(i_supportResistance and bearZone > 0 ? bearZone : na, 'Cross Bear Zone', bearZone == bearZone[1] ? color.red : na, 1)
plot_crossover_oversold     = plot(i_supportResistance and crossover_oversold > 0 ? crossover_oversold : na, 'Crossover Oversold', crossover_oversold == crossover_oversold[1] ? color.red : na, 1, plot.style_cross)
plot_crossunder_oversold    = plot(i_supportResistance and crossunder_oversold > 0 ? crossunder_oversold : na, 'Crossunder Oversold', crossunder_oversold == crossunder_oversold[1] ? color.red : na, 2)

////#  Create RSI Background
// overBought = (oscillator > i_obThreshold)
fill(plot_crossover_overbought, plot_bullZone, i_fill ? color.new(color.green, 90) : na)
plotshape(i_obos and overBought, 'Price Bars in Overbought Zone', shape.triangledown, location.abovebar, color.new(color.red, 0), size=size.small)

// underBought = (oscillator < i_osThreshold)
fill(plot_crossunder_oversold, plot_bearZone, i_fill ? color.new(color.red, 90) : na)
plotshape(i_obos and underBought, 'Price Bars in Oversold Zone', shape.triangleup, location.belowbar, color.new(color.green, 0), size=size.small)


////////////////////////////////////////////////////////////////////}
////# Multi Moving Average Forecast  
////////////////////////////////////////////////////////////////////{


ma(_type, _src, _len) =>  //{
    if _type == 'DEMA'
        2 * ta.ema(_src, _len) - ta.ema(ta.ema(_src, _len), _len)
    else if _type == 'EMA'
        ta.ema(_src, _len)
    else if _type == 'HMA'
        ta.wma(2 * ta.wma(_src, _len / 2) - ta.wma(_src, _len), math.round(math.sqrt(_len)))
    else if _type == 'LSMA'
        3 * ta.wma(_src, _len) - 2 * ta.sma(_src, _len)
    else if _type == 'MA'
        ta.sma(_src, _len)
    else if _type == 'RMA'
        ta.rma(_src, _len)
    else if _type == 'SMA'
        smma = 0.0
        smma := na(smma[1]) ? ta.sma(_src, _len) : (smma[1] * (_len - 1) + _src) / _len
        smma
    else if _type == 'SWMA'
        ta.swma(_src)
    else if _type == 'TEMA'
        3 * ta.ema(_src, _len) - 3 * ta.ema(ta.ema(_src, _len), _len) + ta.ema(ta.ema(ta.ema(_src, _len), _len), _len)
    else if _type == 'TMA'
        ta.swma(ta.wma(_src, _len))
    else if _type == 'VWMA'
        ta.vwma(_src, _len)
    else if _type == 'WMA'
        ta.wma(_src, _len)
//}
ma_prediction(_type, _src, _period, _offset) =>  //{
    (ma(_type, _src, _period - _offset) * (_period - _offset) + _src * _offset) / _period
//}


ma1         = request.security(syminfo.tickerid, maResolution, ma(ma1Type, ma1Source, ma1Length))
ma2         = request.security(syminfo.tickerid, maResolution, ma(ma2Type, ma2Source, ma2Length))
ma3         = request.security(syminfo.tickerid, maResolution, ma(ma3Type, ma3Source, ma3Length))

_MA1        = request.security(syminfo.tickerid, maResolution, ma_prediction(ma1Type, ma1Source, ma1Length, 1))
_pMA1a      = request.security(syminfo.tickerid, maResolution, ma_prediction(ma1Type, ma1Source, ma1Length, 3))
_pMA1b      = request.security(syminfo.tickerid, maResolution, ma_prediction(ma1Type, ma1Source, ma1Length, 5))
_pMA1c      = request.security(syminfo.tickerid, maResolution, ma_prediction(ma1Type, ma1Source, ma1Length, useforcast))

_MA2        = request.security(syminfo.tickerid, maResolution, ma_prediction(ma2Type, ma2Source, ma2Length, 1))
_pMA2a      = request.security(syminfo.tickerid, maResolution, ma_prediction(ma2Type, ma2Source, ma2Length, 3))
_pMA2b      = request.security(syminfo.tickerid, maResolution, ma_prediction(ma2Type, ma2Source, ma2Length, useforcast))

_MA3        = request.security(syminfo.tickerid, maResolution, ma_prediction(ma3Type, ma3Source, ma3Length, 1))
_pMA3a      = request.security(syminfo.tickerid, maResolution, ma_prediction(ma3Type, ma3Source, ma3Length, 3))
_pMA3b      = request.security(syminfo.tickerid, maResolution, ma_prediction(ma3Type, ma3Source, ma3Length, useforcast))

plot(useMAline ? ma1 : na, title='MA 1', color=ma1Color, linewidth=1)
plot(useMAline ? ma2 : na, title='MA 2', color=ma2Color, linewidth=1)
plot(useMAline ? ma3 : na, title='MA 3', color=ma3Color, linewidth=1)


////////////////////////////////////////////////////////////////////}
////# PIVOT LINES Settings
////////////////////////////////////////////////////////////////////{
prevCloseHTF    = request.security(syminfo.tickerid, higherTF, close[1], lookahead=barmerge.lookahead_on)
prevOpenHTF     = request.security(syminfo.tickerid, higherTF, open[1], lookahead=barmerge.lookahead_on)
prevHighHTF     = request.security(syminfo.tickerid, higherTF, high[1], lookahead=barmerge.lookahead_on)
prevLowHTF      = request.security(syminfo.tickerid, higherTF, low[1], lookahead=barmerge.lookahead_on)

pLevel          = (prevHighHTF + prevLowHTF + prevCloseHTF) / 3
r1Level         = pLevel * 2 - prevLowHTF
s1Level         = pLevel * 2 - prevHighHTF
r2Level         = pLevel + prevHighHTF - prevLowHTF
s2Level         = pLevel - (prevHighHTF - prevLowHTF)
r3Level         = prevHighHTF + 2 * (pLevel - prevLowHTF)
s3Level         = prevLowHTF - 2 * (prevHighHTF - pLevel)

////#2 Render Pivot lines
// Plot the pivot line, support and resistence
pColor          = close > pLevel ? label_color_StrongBullish : label_color_StrongBearish
plot(pLevel, color=pColor, linewidth=3, style=plot.style_line, title='Pivot')


var line r1Line = na
var line pLine  = na
var line s1Line = na

// Pivot Prices Labels
if pLevel[1] != pLevel
    //add text attribute
    label.new(showPivots == true ? bar_index : na, r3Level, 'R3', textcolor=color.white, style=label.style_none)
    label.new(showPivots == true ? bar_index : na, r2Level, 'R2', textcolor=color.white, style=label.style_none)
    label.new(showPivots == true ? bar_index : na, r1Level, 'R1', textcolor=color.white, style=label.style_none)
    label.new(showPivots == true ? bar_index : na, pLevel, 'P', textcolor=color.white, style=label.style_none)
    label.new(showPivots == true ? bar_index : na, s1Level, 'S1', textcolor=color.white, style=label.style_none)
    label.new(showPivots == true ? bar_index : na, s2Level, 'S2', textcolor=color.white, style=label.style_none)
    label.new(showPivots == true ? bar_index : na, s3Level, 'S3', textcolor=color.white, style=label.style_none)


////////////////////////////////////////////////////////////////////}
////# CUSTOM ENTRY INPUTS
////////////////////////////////////////////////////////////////////{
// useEntryOptions = input.string('MA1', 'Entry↕', inline='02', group=groupCustom, options=['MA1', 'MA2', 'MA3', '_pMA1a', '_pMA1b', '_pMA2a', '_pMA2b', '_pMA3a', '_pMA3b', 'Overbought', 'Bull Retracement', 'Resistance 1', 'Resistance 2', 'Resistance 3', 'Bull Zone', 'Pivot', 'Bear Zone', 'Bear Retracement', 'Support 1', 'Support 2', 'Support 3', 'Oversold'])
// useExitOptions = input.string('_pMA1b', 'EXIT↕', inline='02', group=groupCustom, options=['MA1', 'MA2', 'MA3', '_pMA1a', '_pMA1b', '_pMA2a', '_pMA2b', '_pMA3a', '_pMA3b', 'Overbought', 'Bull Retracement', 'Resistance 1', 'Resistance 2', 'Resistance 3', 'Bull Zone', 'Pivot', 'Bear Zone', 'Bear Retracement', 'Support 1', 'Support 2', 'Support 3', 'Oversold'])
// useOptions = input.bool(false, title='Position Calculator', group=groupCustom, inline='02')


////# POSITION Settings
group_pos       = 'Table Position & Size & Colors'
rangetooltip    = '0-100. Use 0 to auto-size height and width.'

string useTextSize  = input.string('Large', 'Text Size', options=['Auto', 'Tiny', 'Small', 'Normal', 'Large', 'Huge'], group=groupCustom, inline='02')
string textSize     = useTextSize == 'Auto' ? size.auto : useTextSize == 'Tiny' ? size.tiny : useTextSize == 'Small' ? size.small : useTextSize == 'Normal' ? size.normal : useTextSize == 'Large' ? size.large : size.huge

useStopOptions = input.string('MA3', 'Stop↕', inline='02', group=groupCustom, options=['MA1', 'MA2', 'MA3', '_pMA1a', '_pMA1b', '_pMA2a', '_pMA2b', '_pMA3a', '_pMA3b', 'Overbought', 'Bull Retracement', 'Resistance 1', 'Resistance 2', 'Resistance 3', 'Bull Zone', 'Pivot', 'Bear Zone', 'Bear Retracement', 'Support 1', 'Support 2', 'Support 3', 'Oversold'])
// useProfitOptions   = input("MA2","Profit↕",  inline = "02", group =groupCustom, options = ["MA1","MA2","MA3","_pMA1a","_pMA1b","_pMA2a","_pMA2b","_pMA3a","_pMA3b", "Overbought", "Bull Retracement", "Resistance 1", "Resistance 2", "Resistance 3",  "Bull Zone", "Pivot", "Bear Zone", "Bear Retracement", "Support 1", "Support 2", "Support 3", "Oversold"])
////# Filter Logic
_useRound(_input) =>
    math.round(_input, useRound)
_useOptions(_input) =>
    _input == 'Bull Zone' ? _useRound(bullZone) : _input == 'Bear Zone' ? _useRound(bearZone) : _input == 'Overbought' ? _useRound(crossover_overbought) : _input == 'Oversold' ? _useRound(crossunder_oversold) : _input == 'Pivot' ? _useRound(pLevel) : _input == 'Support 1' ? _useRound(s1Level) : _input == 'Support 2' ? _useRound(s2Level) : _input == 'Support 3' ? _useRound(s3Level) : _input == 'Resistance 1' ? _useRound(r1Level) : _input == 'Resistance 2' ? _useRound(r2Level) : _input == 'Resistance 3' ? _useRound(r3Level) : _input == 'Bull Retracement' ? _useRound(zzBOTTOMValue) : _input == 'Bear Retracement' ? _useRound(zzTOPValue) : _input == 'MA1' ? _useRound(_MA1) : _input == 'MA2' ? _useRound(_MA2) : _input == 'MA3' ? math.round(_MA3, 2) : _input == '_pMA1a' ? _useRound(_pMA1a) : _input == '_pMA1b' ? _useRound(_pMA1b) : _input == '_pMA2a' ? _useRound(_pMA2a) : _input == '_pMA2b' ? _useRound(_pMA2b) : _input == '_pMA3a' ? _useRound(_pMA3a) : _input == '_pMA2b' ? _useRound(_pMA3a) : na


////# Tables
var table topTable          = table.new(position.top_center, 15, 15, border_width=3)
var table topRightTable     = table.new(position.top_right, 15, 15, border_width=3)
var table topLeftTable      = table.new(position.top_right, 15, 15, border_width=3)
var table bottomTable       = table.new(position.bottom_center, 15, 15, border_width=3)

var table middleTable       = table.new(position.middle_right, 15, 15, border_width=3)

var table bottomRightTable  = table.new(position.bottom_right, 15, 15, border_width=3)
var table bottomLeftTable   = table.new(position.bottom_right, 15, 15, border_width=3)
var table table1            = table.new(position.bottom_left, 15, 15, border_width=3)


////# UI State Logic
___useEntryOptions = _useOptions(useEntryOptions)
___useExitOptions = _useOptions(useExitOptions)
___useStopOptions = _useOptions(useStopOptions)
// ___useProfitOptions  = _useOptions(useProfitOptions)

printProfit(_buy, _sell) =>
    _fee = useFEE
    netBuy = _buy - _buy * _fee
    netSell = _sell - _sell * _fee
    netProfit = math.round(netSell - netBuy, useRound) * useQuantity
    netProfit

////////////////////////////////////////////////////////////////////}
////# Strategy
////////////////////////////////////////////////////////////////////{
// ////# Set Limit Orders when retracement prices are hit
// var long = false
// var exitlong = false
// if downtexist[1] and not downtexist and uptexist
//     long := true
//     long
// if long and downtexist
//     long := false
//     exitlong := true
//     exitlong
// var short = false
// // exitshort = false
// if uptexist[1] and not uptexist and downtexist
//     short := true
//     short
// if short and uptexist
//     short := false
//     exitshort := true
//     exitshort

bullishMarket = close > pLevel and not(close < pLevel)
bearishMarket = close < pLevel


////
__bearishBuy        = EngulfingBullish and __emaDOWN and showBearishBuy
__volumeBuy         = _VolumeBuy and showVolumeBuy
// RSIbuy
strongBuy           = isStrongDown and isUp
__long3x            = strongBuy and greenCandle and volu1
__lowestBuy         = __emaDOWN and greenCandle and showGreen and underBought
__volumeEngulfing   = EngulfingBullish and volu2
showBearVolume      = input.bool(defval=true, title = "Show \n Bearish Volume", inline = "Bearish", group=__groupCandlePatterns)
////
if showBullish
    ////# Identify GREEN types
    if __bearishBuy
        var _description = "Engulfing Bullish candle with low EMA..."
        label.new(bar_index, patternLabelPosLow, text="Bearish \n Buy", style=label.style_label_up, color = color.yellow, textcolor=color.black,tooltip = _description)
    if __volumeBuy
        label.new(bar_index, patternLabelPosLow, text=str.tostring("Volume \n Buy"), style=label.style_label_up, color = color.yellow, textcolor=color.black)
    if EngulfingBearish and __emaUP 
        var _description    = "EngulfingBearish and __emaUP ..."
        label.new(bar_index, patternLabelPosLow, text="Bearish \n Buy", style=label.style_label_up, color = color.yellow, textcolor=color.black,tooltip = _description)
    if RSIbuy
        var _description = "This candle should form when there is an RSI buy and volume buy"
        label.new( bar_index, patternLabelPosLow, text="RSI\nVolume", style=label.style_label_up, color = color.green, textcolor=color.black, tooltip=_description)
    if __lowestBuy
        var _description = "This candle should form when there is a green candle with ema down not BullTrap. (The false up signal is still being isolated). "
        label.new( bar_index, patternLabelPosLow, text="Buy\nLow", style=label.style_label_up, color = color.green, textcolor=color.black, tooltip=_description)
    if __long3x
        var _description = "This candle should form when there is a green candle with ema down"
        label.new( bar_index, patternLabelPosLow, text="Long \n 3X", style=label.style_label_up, color = color.green, textcolor=color.black, tooltip=_description)
    ////# RSI
    if RSIbuy // and greenCandle
        label.new(bar_index , patternLabelPosLow, text="RSI \n BUY", style=label.style_label_up, color = color.green, textcolor=color.black)    
    ////# Volume
    if showBearVolume
        if  volu1
            var _description = "volume"
            label.new( bar_index, patternLabelPosLow, text="V1", style=label.style_label_up, color = color.green, textcolor=color.black, tooltip=_description)
        if  volu2
            var _description = "volume"
            label.new( bar_index, patternLabelPosLow, text="V2", style=label.style_label_up, color = color.green, textcolor=color.black, tooltip=_description)
        if  volu3
            var _description = "volume"
            label.new( bar_index, patternLabelPosLow, text="V3", style=label.style_label_up, color = color.green, textcolor=color.black, tooltip=_description)
    if EngulfingBullish and volu2
        var _description = "bullish volume engulfing"
        label.new( bar_index, patternLabelPosLow, text="Volume \n  Engulfing", style=label.style_label_down, color = color.green, textcolor=color.black, tooltip=_description)





////////////////////////////////////////////////////////////////////}
////# Bearish Strategy
////////////////////////////////////////////////////////////////////{

// //////////////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////


if showBearish
    ////# Identify YELLOW types
    if  __DisplayYellowEngulfing 
        var _description    = "Bearish Close \n This occurs __isStrongUP and EngulfingBearish. If a daily candle begins to form this, it is often a STRONG BEARish signal." 
        label.new(bar_index , patternLabelPosHigh, text="Bearish \n Close Longs", style=label.style_label_down, color = color.yellow, textcolor=color.black,tooltip = _description)    
    if strongEngulfing and not EngulfingBearish
        var _description    = "StrongEngulfing and not Bearish Engulfing" 
        label.new(bar_index , patternLabelPosHigh, text="Bullish \n Close Longs", style=label.style_label_down, color = color.yellow, textcolor=color.black,tooltip = _description)    
    // if useEngulfing
        // if  strongEngulfing
        //     var _description    = "Engulfing Bullish candle..."
        //     label.new(bar_index, patternLabelPosLow, text="YE", style=label.style_label_up, color = color.yellow, textcolor=color.black,tooltip = _description)
    ////# Volume
    if _VolumeSell and showVolumeSell
        label.new(bar_index, patternLabelPosLow, text=str.tostring("Close \n Short"), style=label.style_label_up, color = color.red, textcolor=color.black, tooltip="Close \n Short")
    // var __volume = true
    if showVolumeSell
        if  vold1
            var _description = "volume"
            label.new( bar_index, patternLabelPosLow, text="VD\n 1", style=label.style_label_up, color = color.red, textcolor=color.black, tooltip=_description)
        if  vold2
            var _description = "volume"
            label.new( bar_index, patternLabelPosLow, text="VD\n 2", style=label.style_label_up, color = color.red, textcolor=color.black, tooltip=_description)
        if  vold3
            var _description = "volume"
            label.new( bar_index, patternLabelPosLow, text="VD\n 3", style=label.style_label_up, color = color.red, textcolor=color.black, tooltip=_description)
    if EngulfingBearish and vold1
        var _description = "volume 1"
        label.new( bar_index, patternLabelPosLow, text="Close\n Short", style=label.style_label_up, color = color.red, textcolor=color.black, tooltip=_description)
    if EngulfingBearish and vold2
        var _description = "volume 2"
        label.new( bar_index, patternLabelPosLow, text="Close\n Short 2", style=label.style_label_up, color = color.red, textcolor=color.black, tooltip=_description)
    if EngulfingBearish and vold3
        var _description = "volume 3"
        label.new( bar_index, patternLabelPosLow, text="Volume\n Engulfing 3", style=label.style_label_up, color = color.red, textcolor=color.black, tooltip=_description)





////////////////////////////////////////////////////////////////////}
////# WEBHOOKS
////////////////////////////////////////////////////////////////////{


// -Discord Bot Settings   ════════════════════════════════════════════════════════════════════════════════════ //
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © ZenAndTheArtOfTrading / www.PineScriptMastery.com
// study("Discord Alerts")

// Get user input
botName         = input.string(title='Bot Name', defval='Laser-Eyes', tooltip='The display name for this webhook bot')
avatarURL       = input.string(title='Avatar URL', defval='', tooltip='Your preferred Avatar image URL')
iconURL         = input.string(title='Icon URL', defval='', tooltip='Your preferred message icon image URL')
titleURL        = input.string(title='Title URL', defval='https://www.tradingview.com/chart/dotusdt', tooltip='Where you want the title of the message to link to')
useMessage      = input.string(title='Message', defval='', tooltip='Optional message to add before the role tag & embed info')
role            = input.string(title='Role ID', defval='', tooltip='The role ID you want to ping when this message is sent to discord (optional)')
embedColor      = input.string(title='Embed Color', defval='', tooltip='Your embed color (decimal color only - not HEX or RGB!)')
volatility      = input.bool(title='Volatility Alerts?', defval=true, tooltip='Turns on/off intraday volatility alerts')

// // Declare constant variables
var ROLE_ID     = role == '' ? '' : ' (<@&' + role + '>)'
var ICON1_URL   = syminfo.type == 'forex' ? 'https://theartoftrading.com/files/discord/flags/' + syminfo.basecurrency + '.png' : iconURL
var ICON2_URL   = syminfo.type == 'forex' ? 'https://theartoftrading.com/files/discord/flags/' + syminfo.currency + '.png' : ''
var MARKET      = syminfo.type == 'forex' or syminfo.type == 'crypto' ? syminfo.basecurrency : syminfo.ticker

// // Get market data to send to discord
mktChange       = ta.change(close) / close[1] * 100
mktRSI          = ta.rsi(close, 14)

// // Custom function to truncate (cut) excess decimal places
truncate(_number, _decimalPlaces) =>
    _factor = math.pow(10, _decimalPlaces)
    int(_number * _factor) / _factor

// // Custom function to convert pips into whole numbers
atr = ta.atr(14)
toWhole(_number) =>
    _return = atr < 1.0 ? _number / syminfo.mintick / (10 / syminfo.pointvalue) : _number
    _return := atr >= 1.0 and atr < 100.0 and syminfo.currency == 'JPY' ? _return * 100 : _return
    _return

// // Generate discord embed JSON
// // https://courses.theartoftrading.com/pages/pine-script-mastery-source-code#discord
getDiscordEmbedJSON(_color, _author, _title, _url, _icon_url, _icon2_url, _footer, _description) =>
    botTxt = '"username":"' + botName + '","avatar_url":"' + avatarURL + '",'
    tagTxt = useMessage == '' and role == '' ? '' : '"content":"' + (useMessage == '' ? '' : useMessage + ' ') + ROLE_ID + '",'
    returnString = '{' + botTxt + tagTxt + '"embeds":[{"title":"' + _title + '","url":"' + _url + '","color":' + _color + ',"description":"' + _description + '","author":{"name":"' + _author + '","url":"' + _url + '","icon_url":"' + _icon_url + '"},"footer":{"text":"' + _footer + '","icon_url":"' + _icon2_url + '"}}]}'
    returnString


// Determine if we have a new bar starting - if so, send our Discord webhook alert
// var content = ""
if barstate.isconfirmed
    timeframe = (timeframe.isintraday ? timeframe.period + ' minute' : timeframe.isdaily ? 'Daily' : timeframe.isweekly ? 'Weekly' : timeframe.ismonthly ? 'Monthly' : timeframe.period) + ' timeframe'
    update = syminfo.ticker + ' ended ' + (mktChange > 0 ? 'up +' : 'down ') + str.tostring(truncate(mktChange, 2)) + '% on ' + timeframe + ' (RSI = ' + str.tostring(truncate(mktRSI, 2)) + ')'
    gainLoss = toWhole(open - close)
    footer = 'Price: ' + str.tostring(close) + ' (' + (gainLoss > 0 ? '+' : '') + str.tostring(gainLoss) + ' pips)'
    gainColor = embedColor != '' ? embedColor : mktChange > 0 ? '65280' : '16711680'
    content = getDiscordEmbedJSON(gainColor, 'Market Update', syminfo.ticker, titleURL, ICON1_URL, ICON2_URL, footer, update)
    content
    // table.cell(middleTable, 0, 3, "Market is Bullish ... \n"+tostring(content), text_size = textSize, width= 0, height= 0,text_color = color.green)
    // alert(content, alert.freq_once_per_bar)


////# Real-Time?
if barstate.islast
////# Alerts 
// __timeframe  = (timeframe.isintraday ? timeframe.period + " minute" : timeframe.isdaily ? "Daily" : timeframe.isweekly ? "Weekly" : timeframe.ismonthly ? "Monthly" : timeframe.period) + " timeframe"
// __update     = syminfo.ticker + " is " + (mktChange > 0 ? "up +" : "down ") + tostring(truncate(mktChange,2)) + "% [" + tostring(close) + "] on " + __timeframe + " (RSI = " + tostring(truncate(mktRSI,2)) + ")"
// __gainLoss   = toWhole(open - close)
// __footer     = "Price: " + tostring(close) + " (" + (__gainLoss > 0 ? "+" : "") + tostring(__gainLoss) + " pips)"
// __gainColor  = (embedColor != "" ? embedColor : (mktChange > 0 ? "65280" : "16711680"))
// __content    = getDiscordEmbedJSON(__gainColor, "High Volatility Alert", syminfo.ticker, titleURL, ICON1_URL, ICON2_URL, __footer, __update)
    ////# NEUTRAL Trend 
    if __isNA and showEMAneutral
        var _description = 'ema is __isNA'
        label.new(bar_index, patternLabelPosLow, text='\n NA \n', style=label.style_label_up, color=color.white, textcolor=color.black, tooltip=_description)
    ////# BULLISH Trend Labels
    if bullishMarket == true
        // table.cell(middleTable, 0, 3, "Market is Bullish ... \n"+tostring(floor(sumbull-sumbear)), text_size = textSize, width= 0, height= 0,text_color = color.green)
        // if timeframe.period =="1"
        //     createEstimate(bottomTable,"Stop/Profit: ", 4, ___useStopOptions, ___useEntryOptions, ___useExitOptions, color.new(color.red, 80))
        ////# BULLISH labels  
        if isUp and showEMAup
            var _description = 'ema is isUp'
            label.new(bar_index, patternLabelPosLow, text='\n UP \n', style=label.style_label_up, color=color.green, textcolor=color.black, tooltip=_description)
    ////# BEARISH Trend 
    if bearishMarket == true
        // table.cell(middleTable, 0, 3, " Market is Bearish ... \n"+tostring(floor(sumbear -sumbull)), text_size = textSize, width= 0, height= 0,text_color = color.red)
        ////# BEARISH labels  
        if isDown and showEMAdown
            var _description = 'ema is isDown'
            label.new(bar_index, patternLabelPosHigh, text='DOWN', style=label.style_label_down, color=color.red, textcolor=color.black, tooltip=_description)


alertcondition(EngulfingBullish and volu2 ? bar_index : na, "Bullish Volume Engulfing")

// plotshape(__isNA and showEMAneutral ? bar_index:na, location=location.abovebar, text="NA", color=color.white)
alertcondition(__isNA ? bar_index : na, 'NA', '\n{{exchange}}:{{ticker}}->\nPrice = {{close}},\nTime = {{time}}')

// plotshape(isDown and showEMAdown ? bar_index:na, style=shape.arrowdown,location=location.belowbar, text="down", color=color.red)
alertcondition(isDown ? bar_index : na, 'DOWN', '{"content": "Trend is... DOWN!", "tts": true }')

// plotshape(__isStrongDown and showStrongEMAdown ? bar_index:na, style=shape.arrowdown,location=location.abovebar, text="strong \n down", color=color.red)
alertcondition(__isStrongDown ? bar_index : na, 'Strong DOWN', '\n{{exchange}}:{{ticker}}->\nPrice = {{close}},\nTime = {{time}}')

// plotshape(isUp and showEMAup ? bar_index:na, style=shape.arrowup,location=location.belowbar, text="up", color=color.green)
alertcondition(isUp ? bar_index : na, 'UP', '{"content": "Trend is... UP!", "tts": true }')

// plotshape(isStrongUp and showStrongEMAup ? bar_index:na, style=shape.arrowup,location=location.belowbar, text="strong \n up", color=color.yellow)
alertcondition(isStrongUp ? bar_index : na, 'isStrongUp', '{"content": "Trend is... STRONG UP, set stoploss to s1Level and if you get stoplossed, consider DYOR on opening a short... !", "tts": true }')

////# Alert Conditions
//// https://www.tradingview.com/script/FPq2xKyZ-DiscordWebhookFunction/
import wlhm/DiscordWebhookFunction/1 
// discordWebhookJSON(
//      _username, 
//      _avatarImgUrl, 
//      _contentText, 
//      _bodyTitle, 
//      _descText, 
//      _bodyUrl, 
//      _embedCol, 
//      _timestamp, 
//      _authorName, 
//      _authorUrl, 
//      _authorIconUrl, 
//      _footerText, 
//      _footerIconUrl, 
//      _thumbImgUrl, 
//      _imageUrl)




// -RSI Alerts   ════════════════════════════════════════════════════════════════════════════════════ //
// {"content": "HYDRA Trend is... UP...on the 1 Hour.", "tts": true }
alertcondition(ta.crossover(close, crossover_overbought), 'RSI Sell', 'Crossover Previous Overbought\n{{exchange}}:{{ticker}}->\nPrice = {{close}},\nTime = {{time}}')
alertcondition(ta.crossunder(close, crossunder_oversold), 'RSI Buy', 'Crossunder Previous Oversold\n{{exchange}}:{{ticker}}->\nPrice = {{close}},\nTime = {{time}}')


// -Volume Alerts   ════════════════════════════════════════════════════════════════════════════════════ //
alertcondition(vold1 or vold2 or vold3, 'Volume Buy', '{"content": "volume SELLING conditions may be forming! \n This means that there is an Engulfing Bullish and vol up 2", "tts": true }')
alertcondition(volu1 or volu2 or volu3, 'Volume SELL', '{"content": "volume BUYING conditions may be forming! \n In theory, this should be a SHORT position... meaning that there is an Engulfing Bearish and vol down 2", "tts": true }')

alertcondition(EngulfingBearish ? bar_index : na, 'EngulfingBearish', '{"content": "Bearish Engulfing may be forming!", "tts": true }')
alertcondition(EngulfingBullish ? bar_index : na, 'EngulfingBullish', '{"content": "EngulfingBullish Engulfing may be forming!", "tts": true }')
alertcondition(__volumeEngulfing ? bar_index : na, 'volume Engulfing', '{"content": "volume Engulfing Engulfing may be forming! \n This means that there is an Engulfing Bullish and vol up 2", "tts": true }')

////# posible Reversal
alertcondition((bullishMarket or RSIbuy) and __isStrongDown and isUp and (volu1 or volu2 or volu3)  ? bar_index : na, 'BULLISH Scalping Opportunity (1M)', '{"content": "On lower timefrrames such as the 1 minute ... the market looks Bullish because the current price is above the pivot line and on the RSI is oversold and there is possitive volume. Additionally the ema trend is moving between strong down and up which suggest a floor may have been reacheed... Always DYOR before opening a position because lower timeframes do not carry the same weight...", "tts": true }')
alertcondition((bearishMarket or RSIsell) and isStrongUp and isDown and (vold1 or vold2 or vold3)   ? bar_index : na, 'BEARISH Scalping Opportunity (1M)', '{"content": "On lower timefrrames such as the 1 minute ... the market looks BEARISH because the current price is BELOW the pivot line and on the RSI is OVERBOUGHT and there is negitive volume. Additionally the ema trend is moving between strong up and DOWN which suggest a floor may have been reacheed... Always DYOR before opening a position because lower timeframes do not carry the same weight...", "tts": true }')
// {"content": "ETH Trend is... STRONG UP...on the 1 Hour. This indicates it may be too late to open a LONG so  always DYOR", "tts": true }

// if (exitshort or (zzlong and not zzlong[1]) )
//     strategy.entry("Long", strategy.long)
// if (exitlong or (zzshort and not zzshort[1]) )
//     strategy.entry("Short", strategy.short)


////////////////////////////////////////////////////////////////////}
//# * HELLO STREAM...
// ⬆️ GREEN Triangle Pointed Up means, open long/er a long
// ✖️ Close the LONG, and consider a opening a short
// Retracements could become engulfing candles or reversals/breakouts, if the current price os below
////////////////////////////////////////////////////////////////////{

