MACD Plus
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © OskarGallard

//@version=5
indicator(title='MACD Plus', shorttitle='MACD Plus')
// Function to select the type of source
get_src(Type) =>
    if Type == 'VWAP'
        ta.vwap
    else if Type == 'Close'
        close
    else if Type == 'Open'
        open
    else if Type == 'HL2'
        hl2
    else if Type == 'HLC3'
        hlc3
    else if Type == 'OHLC4'
        ohlc4
    else if Type == 'HLCC4'
        hlcc4
    else if Type == 'High'
        high
    else if Type == 'Low'
        low
    else if Type == 'vwap(Close)'
        ta.vwap(close)
    else if Type == 'vwap(Open)'
        ta.vwap(open)
    else if Type == 'vwap(High)'
        ta.vwap(high)
    else if Type == 'vwap(Low)'
        ta.vwap(low)
    else if Type == 'AVG(vwap(H,L))'
        math.avg(ta.vwap(high), ta.vwap(low))
    else if Type == 'AVG(vwap(O,C))'
        math.avg(ta.vwap(open), ta.vwap(close))
    else if Type == 'OBV' // On Balance Volume
        ta.obv
    else if Type == 'AccDist' // Accumulation Distribution
        ta.accdist
    else if Type == 'PVT' // Price Volume Trend
        ta.pvt

// Inputs - MACD
res           = input.timeframe('', 'Indicator Time Frame')
fast_length   = input.int(12, 'Fast Length', inline='Length')
slow_length   = input.int(26, 'Slow Length', inline='Length')
sma_source    = input.string('EMA', 'Oscillator MA Type', inline='Oscillator', options=['SMA', 'EMA', 'WMA', 'Median', 'DWMA', 'New-WMA', 'VWMA', 'DVWMA', 'VAMA', 'HMA', 'ALMA', 'LSMA', 'Wild', 'JMA', 'COVWMA', 'FRAMA', 'Zero Lag', 'Tillson T3', 'VIDYA', 'KAMA', 'CTI', 'RMA', 'DEMA', 'TEMA', 'SWMA', 'RSI EMA', 'ADX MA'])
src           = input.string('Close', 'Source', inline='Oscillator', options=['VWAP', 'Close', 'Open', 'HL2', 'HLCC4', 'HLC3', 'OHLC4', 'High', 'Low', 'vwap(Close)', 'vwap(Open)', 'vwap(High)', 'vwap(Low)', 'AVG(vwap(H,L))', 'AVG(vwap(O,C))', 'OBV', 'AccDist', 'PVT'])
signal_length = input.int(9, 'Signal Smoothing', minval=1, maxval=50, inline='Signal')
ma_signal     = input.string('EMA', 'Line MA Type', inline='Signal', options=['SMA', 'EMA', 'WMA', 'Median', 'DWMA', 'New-WMA', 'VWMA', 'DVWMA', 'VAMA', 'HMA', 'ALMA', 'LSMA', 'Wild', 'JMA', 'COVWMA', 'FRAMA', 'Zero Lag', 'Tillson T3', 'VIDYA', 'KAMA', 'CTI', 'RMA', 'DEMA', 'TEMA', 'SWMA',  'RSI EMA', 'ADX MA'])
// Show Plots T/F
show_macd      = input.bool(true, 'Show MACD Lines', inline='SP10')
show_macd_LW   = input.int(2, 'MACD Width', minval=0, maxval=5, inline='SP11')
show_signal_LW = input.int(1, 'Signal Width', minval=0, maxval=5, inline='SP11')
show_Hist      = input.bool(true, 'Show Histogram', inline='SP20')
show_hist_LW   = input.int(1, '-- Width', minval=0, maxval=5, inline='SP20')
show_trend     = input.bool(true, 'Show MACD Lines w/ Trend Color', inline='SP30')
show_HB        = input.bool(false, 'Show Highlight Price Bars', inline='SP50')
show_cross     = input.bool(false, 'Show BackGround on Cross', inline='SP50')
show_dots      = input.bool(false, 'Show Circle on Cross', inline='SP60')
show_dots_LW   = input.int(7, '-- Width', minval=0, maxval=7, inline='SP60')
show_macd_bg   = input.bool(true, "MACD Background")
show_macd_bar  = input.bool(true, "MACD Bar Colors") 
// MACD Lines colors
col_macd    = input.color(#FFAB62, 'MACD Line  ',    inline='CS1')
col_signal  = input.color(#00CED1, 'Signal Line  ',  inline='CS1')
col_trnd_Up = input.color(#80FF00, 'Trend Up      ', inline='CS2')
col_trnd_Dn = input.color(#FF0000, 'Trend Down    ', inline='CS2')
// Histogram Colors
col_grow_above = input.color(#8080FF, 'Above   Grow', inline='Hist10')
col_fall_above = input.color(#353568, 'Fall',         inline='Hist10')
col_grow_below = input.color(#FF8080, 'Below Grow',   inline='Hist20')
col_fall_below = input.color(#683535, 'Fall',         inline='Hist20')
// Alerts T/F Inputs
alert_Long    = input.bool(false, 'MACD Cross Up', group='Alerts', inline='Alert10')
alert_Short   = input.bool(false, 'MACD Cross Dn', group='Alerts', inline='Alert10')
alert_Long_A  = input.bool(false, 'MACD Cross Up & > 0', group='Alerts', inline='Alert20')
alert_Short_B = input.bool(false, 'MACD Cross Dn & < 0', group='Alerts', inline='Alert20')

// Divergences
divergence     = input.string('Histogram', "Divergence on Histogram or MACD Line?", options = ['Histogram', 'MACD'], group="Divergences")
plotBull       = input.bool(true,  "Plot Bullish",        inline="bull", group="Divergences")
plotHiddenBull = input.bool(false, "Plot Hidden Bullish", inline="bull", group="Divergences")
bullColor      = input.color(color.new(#77DD77, 0), "   Color", inline="bull", group="Divergences")
plotBear       = input.bool(true,  "Plot Bearish",        inline="bear", group="Divergences")
plotHiddenBear = input.bool(false, "Plot Hidden Bearish", inline="bear", group="Divergences")
bearColor      = input.color(color.new(#FF6347, 0), "   Color", inline="bear", group="Divergences")
lbR            = input.int(5,      "Pivot Lookback Right",  group="Divergences")
lbL            = input.int(5,      "Pivot Lookback Left",   group="Divergences")
rangeUpper     = input.int(60,     "Max of Lookback Range", group="Divergences")
rangeLower     = input.int(5,      "Min of Lookback Range", group="Divergences")

// Input - The Expert Trend Locator - XTL 
candles_XTL = input.bool(false, title='Use XTL Bars Color', group='[XTL] Expert Trend Locator')
period_xtl  = input.int(35, title='Length', minval=2, inline='xtl', group='[XTL] Expert Trend Locator')
MA_Type2    = input.string('ALMA', title='Type', inline='xtl', group='[XTL] Expert Trend Locator', options=['SMA', 'EMA', 'WMA', 'DWMA', 'Median', 'VWMA', 'DVWMA', 'New-WMA', 'VAMA', 'HMA', 'ALMA', 'LSMA', 'Wild', 'JMA', 'Zero Lag', 'Tillson T3', 'VIDYA', 'KAMA', 'CTI', 'RMA', 'DEMA', 'TEMA', 'SWMA', 'COVWMA', 'FRAMA', 'RSI EMA', 'ADX MA'])
src_xtl     = input.string('HLC3', title='Source', inline='xtl', group='[XTL] Expert Trend Locator', options=['VWAP', 'Close', 'Open', 'HL2', 'HLCC4', 'HLC3', 'OHLC4', 'High', 'Low', 'vwap(Close)', 'vwap(Open)', 'vwap(High)', 'vwap(Low)', 'AVG(vwap(H,L))', 'AVG(vwap(O,C))', 'OBV', 'AccDist', 'PVT'])
fixed_Value = input.int(37, title='Threshold Level', minval=10, group='[XTL] Expert Trend Locator', inline='xtl2')
uTrad       = input.bool(false, title='Use the traditional CCI formula', group='[XTL] Expert Trend Locator', inline='xtl2')
color_xtlUP = input.color(#00BFFF, 'Trend Up',   group='[XTL] Expert Trend Locator', inline='ColXTL')
color_xtlNe = input.color(#FFFFFF, 'Neutral',    group='[XTL] Expert Trend Locator', inline='ColXTL')
color_xtlDN = input.color(#FF4000, 'Trend Down', group='[XTL] Expert Trend Locator', inline='ColXTL')
detect_bull = input.bool(false,    "◁ Alert: Bullish Trend", inline="alert_xtl", group="[XTL] Expert Trend Locator")
detect_bear = input.bool(false,    "◁ Alert: Bearish Trend", inline="alert_xtl", group="[XTL] Expert Trend Locator")

// Input - Squeeze Pro
length_sqz = input.int(20, title='Length', minval=1, step=1, inline='S', group='Squeeze Pro')
src_sqz    = input.string('OHLC4', title='Source', inline='S', group='Squeeze Pro', options=['VWAP', 'Close', 'Open', 'HL2', 'HLCC4', 'HLC3', 'OHLC4', 'High', 'Low', 'vwap(Close)', 'vwap(Open)', 'vwap(High)', 'vwap(Low)', 'AVG(vwap(H,L))', 'AVG(vwap(O,C))', 'OBV', 'AccDist', 'PVT'])
bbmatype   = input.string('SMA', title='Bollinger Bands Calculation Type', group='Squeeze Pro', options=['SMA', 'EMA', 'WMA', 'LSMA', 'ALMA', 'New-WMA', 'VAMA', 'JMA', 'HMA', 'KAMA', 'RMA', 'DEMA', 'TEMA', 'VWMA', 'SWMA', 'Wild', 'Median', 'COVWMA', 'FRAMA'])
kcmatype   = input.string('EMA', title='Keltner Channel Calculation Type', group='Squeeze Pro', options=['SMA', 'EMA', 'WMA', 'LSMA', 'ALMA', 'New-WMA', 'VAMA', 'JMA', 'HMA', 'KAMA', 'RMA', 'DEMA', 'TEMA', 'VWMA', 'SWMA', 'Wild', 'Median', 'COVWMA', 'FRAMA'])
color_H    = input.color(#FFE500, 'High Squeeze',   group='Squeeze Pro', inline='ColSQZ')
color_O    = input.color(#FF4000, 'Medium Squeeze', group='Squeeze Pro', inline='ColSQZ')
color_L    = input.color(#727272, 'Low Squeeze',    group='Squeeze Pro', inline='ColSQZ')

// Input - Directional Movement Index
lenSig    = input.int(14, 'ADX Smoothing', minval=1, maxval=50, inline='len1', group='Directional Movement Index')
lenDi     = input.int(14, 'DI Length', minval=1, inline='len1', group='Directional Movement Index')
keyLevel  = input.int(23, 'Strong Trend Theshold', group='Directional Movement Index')
weakTrend = input.int(15, 'Weak Trend Theshold', group='Directional Movement Index')
histLabel = input.int(0,  'Historical Label Readings', minval=0, inline='dmi', group='Directional Movement Index')
hideLabel = input.bool(false, 'Hide DMI Label', inline='dmi', group='Directional Movement Index')
detect_bull_dmi = input.bool(false, '◁ Alert: Bullish Trend', inline='alert_dmi', group='Directional Movement Index')
detect_bear_dmi = input.bool(false, '◁ Alert: Bearish Trend', inline='alert_dmi', group='Directional Movement Index')

// Input - Williams Vix Fix
sbcFilt  = input.bool(true, 'Show Signal For Filtered Entry [▲ FE ]', group='Williams Vix Fix') // Use FILTERED Criteria
sbcAggr  = input.bool(true, 'Show Signal For AGGRESSIVE Filtered Entry [▲ AE ]', group='Williams Vix Fix') // Use FILTERED Criteria
sbc      = input.bool(true, 'Show Signal if WVF WAS True and IS Now False [▼]', group='Williams Vix Fix') // Use Original Criteria
sbcc     = input.bool(true, 'Show Signal if WVF IS True [▼]', group='Williams Vix Fix') // Use Original Criteria
alert_AE = input.bool(false, '◁ Alert: [AGGRESSIVE Entry]', inline='AlertVF', group='Williams Vix Fix')
alert_FE = input.bool(false, '◁ Alert: [Filtered Entry]', inline='AlertVF', group='Williams Vix Fix')
pd       = input.int(22, 'LookBack Period Standard Deviation High', group='Williams Vix Fix')
bbl      = input.int(20, 'Bolinger Band Length', group='Williams Vix Fix')
mult     = input.float(2.0, 'Bollinger Band Standard Devaition Up', minval=1, maxval=5, group='Williams Vix Fix')
lb       = input.int(50, 'Look Back Period Percentile High', group='Williams Vix Fix')
ph       = input.float(.85, 'Highest Percentile - 0.90=90%, 0.95=95%, 0.99=99%', group='Williams Vix Fix')
ltLB     = input.int(40, minval=25, maxval=99, title='Long-Term Look Back Current Bar Has To Close Below This Value OR Medium Term--Default=40', group='Williams Vix Fix')
mtLB     = input.int(14, minval=10, maxval=20, title='Medium-Term Look Back Current Bar Has To Close Below This Value OR Long Term--Default=14', group='Williams Vix Fix')
str      = input.int(3,  minval=1,  maxval=9,  title='Entry Price Action Strength--Close > X Bars Back---Default=3', group='Williams Vix Fix')

// Kaufman's Adaptive Moving Average
fast = 0.666  // KAMA Fast End
slow = 0.0645  // KAMA Slow End
kama(x, t) =>
    dist = math.abs(x[0] - x[1])
    signal = math.abs(x - x[t])
    noise = math.sum(dist, t)
    effr = noise != 0 ? signal / noise : 1
    sc = math.pow(effr * (fast - slow) + slow, 2)
    KAma = x
    KAma := nz(KAma[1]) + sc * (x - nz(KAma[1]))
    KAma

// Jurik Moving Average of @everget
jma(src, length, power, phase) =>
    phaseRatio = phase < -100 ? 0.5 : phase > 100 ? 2.5 : phase / 100 + 1.5
    beta = 0.45 * (length - 1) / (0.45 * (length - 1) + 2)
    alpha = math.pow(beta, power)
    Jma = 0.0
    e0 = 0.0
    e0 := (1 - alpha) * src + alpha * nz(e0[1])
    e1 = 0.0
    e1 := (src - e0) * (1 - beta) + beta * nz(e1[1])
    e2 = 0.0
    e2 := (e0 + phaseRatio * e1 - nz(Jma[1])) * math.pow(1 - alpha, 2) + math.pow(alpha, 2) * nz(e2[1])
    Jma := e2 + nz(Jma[1])
    Jma

cti(sm, src, cd) =>
    di = (sm - 1.0) / 2.0 + 1.0
    c1 = 2 / (di + 1.0)
    c2 = 1 - c1
    c3 = 3.0 * (cd * cd + cd * cd * cd)
    c4 = -3.0 * (2.0 * cd * cd + cd + cd * cd * cd)
    c5 = 3.0 * cd + 1.0 + cd * cd * cd + 3.0 * cd * cd
    i1 = 0.0
    i2 = 0.0
    i3 = 0.0
    i4 = 0.0
    i5 = 0.0
    i6 = 0.0
    i1 := c1 * src + c2 * nz(i1[1])
    i2 := c1 * i1 + c2 * nz(i2[1])
    i3 := c1 * i2 + c2 * nz(i3[1])
    i4 := c1 * i3 + c2 * nz(i4[1])
    i5 := c1 * i4 + c2 * nz(i5[1])
    i6 := c1 * i5 + c2 * nz(i6[1])
    bfr = -cd * cd * cd * i6 + c3 * i5 + c4 * i4 + c5 * i3
    bfr

a = 0.618
T3ma(src, Len) =>
    e1 = ta.ema(src, Len)
    e2 = ta.ema(e1, Len)
    e3 = ta.ema(e2, Len)
    e4 = ta.ema(e3, Len)
    e5 = ta.ema(e4, Len)
    e6 = ta.ema(e5, Len)
    C1 = -a * a * a
    C2 = 3 * a * a + 3 * a * a * a
    C3 = -6 * a * a - 3 * a - 3 * a * a * a
    C4 = 1 + 3 * a + a * a * a + 3 * a * a
    C1 * e6 + C2 * e5 + C3 * e4 + C4 * e3

VIDYA(src, Len) =>
    mom = ta.change(src)
    upSum = math.sum(math.max(mom, 0), Len)
    downSum = math.sum(-math.min(mom, 0), Len)
    out = (upSum - downSum) / (upSum + downSum)
    cmo = math.abs(out)
    alpha = 2 / (Len + 1)
    vidya = 0.0
    vidya := src * alpha * cmo + nz(vidya[1]) * (1 - alpha * cmo)
    vidya

// ZLEMA: Zero Lag
zema(_src, _len) =>
    alpha = (_len - 1) / 2
    zlema0 = _src + _src - _src[alpha]
    zlemaF = ta.ema(zlema0, _len)
    zlemaF

// ADX Weighted Moving Average of @Duyck 
adx_weighted_ma(_src, _period) =>
    [_diplus, _diminus, _adx] = ta.dmi(17, 14)
    _vol_sum  = 0.0
    _adx_sum  = 0.0
    for i = 0 to _period
        _vol_sum  := _src[i] * _adx[i] + _vol_sum
        _adx_sum  := _adx[i] + _adx_sum 
    _volwma   = _vol_sum / _adx_sum

// COVWMA - Coefficient of Variation Weighted Moving Average of @DonovanWall
covwma(a, b) =>
    cov    = ta.stdev(a, b) / ta.sma(a, b)
    cw     = a*cov
    covwma = math.sum(cw, b) / math.sum(cov, b)

// FRAMA - Fractal Adaptive Moving Average of @DonovanWall
w = -4.6 // "Coefficient (if FRAMA)"
frama(a, b) =>
    frama = 0.0
    n3    = (ta.highest(high, b) - ta.lowest(low, b))/b
    hd2   = ta.highest(high, b/2)
    ld2   = ta.lowest(low, b/2)
    n2    = (hd2 - ld2)/(b/2)
    n1    = (hd2[b/2] - ld2[b/2])/(b/2)
    dim   = (n1 > 0) and (n2 > 0) and (n3 > 0) ? (math.log(n1 + n2) - math.log(n3))/math.log(2) : 0
    alpha = math.exp(w*(dim - 1))
    sc    = (alpha < 0.01 ? 0.01 : (alpha > 1 ? 1 : alpha))
    frama := ta.cum(1)<=2*b ? a : (a*sc) + nz(frama[1])*(1 - sc)
    frama

// EMA RSI Adaptive of @glaz
rsi_ema(src, period) =>
    RsiPeriod = 14
    ema = 0.0
    RSvoltl = math.abs(ta.rsi(close, RsiPeriod)-50)+1.0
    multi   = (5.0+100.0/RsiPeriod) / (0.06+0.92*RSvoltl+0.02*math.pow(RSvoltl,2))
    pdsx    = multi*period
    alpha   = 2.0 /(1.0+pdsx)
    ema     := nz(ema[1])+alpha*(ta.sma(close, period)-nz(ema[1]))
    ema

// VAMA - Volume Adjusted Moving Average of @allanster
vama(_src,_len,_fct,_rul,_nvb) =>                             // vama(source,length,factor,rule,sample)
    tvb = 0, tvb := _nvb == 0 ? nz(tvb[1]) + 1 : _nvb         // total volume bars used in sample            
    tvs = _nvb == 0 ? ta.cum(volume) : math.sum(volume, _nvb) // total volume in sample
    v2i = volume / ((tvs / tvb) * _fct)                       // ratio of volume to increments of volume                                                  
    wtd = _src*v2i                                            // weighted prices 
    nmb = 1                                                   // initialize number of bars summed back               
    wtdSumB = 0.0                                             // initialize weighted prices summed back
    v2iSumB = 0.0                                             // initialize ratio of volume to increments of volume summed back
    for i = 1 to _len * 10                                    // set artificial cap for strict to VAMA length * 10 to help reduce edge case timeout errors
        strict = _rul ? false : i == _len                     // strict rule N bars' v2i ratios >= vama length, else <= vama length
        wtdSumB := wtdSumB + nz(wtd[i-1])                     // increment number of bars' weighted prices summed back
        v2iSumB := v2iSumB + nz(v2i[i-1])                     // increment number of bars' v2i's summed back
        if v2iSumB >= _len or strict                          // if chosen rule met
            break                                             // break (exit loop)
        nmb := nmb + 1                                        // increment number of bars summed back counter
    nmb                                                       // number of bars summed back to fulfill volume requirements or vama length
    wtdSumB                                                   // number of bars' weighted prices summed back
    v2iSumB                                                   // number of bars' v2i's summed back
    vama = (wtdSumB - (v2iSumB - _len) * _src[nmb]) / _len    // volume adjusted moving average

// New WMA
NWMA(_src, _n1) =>
    fast_n   = int(_n1 / 2)
    lambda = _n1 / fast_n
    alpha  = lambda * (_n1 - 1) / (_n1 - lambda)
    ma1    = ta.wma(_src, _n1)
    ma2    = ta.wma(ma1, fast_n)
    nwma   = (1 + alpha) * ma1 - alpha * ma2

ma(MAType, MASource, MAPeriod) =>
    if MAPeriod > 0
        if MAType == 'SMA'
            ta.sma(MASource, MAPeriod)
        else if MAType == 'EMA'
            ta.ema(MASource, MAPeriod)
        else if MAType == 'WMA'
            ta.wma(MASource, MAPeriod)
        else if MAType == 'RMA'
            ta.rma(MASource, MAPeriod)
        else if MAType == 'HMA'
            ta.hma(MASource, MAPeriod)
        else if MAType == 'DEMA'
            e = ta.ema(MASource, MAPeriod)
            2 * e - ta.ema(e, MAPeriod)
        else if MAType == 'TEMA'
            e = ta.ema(MASource, MAPeriod)
            3 * (e - ta.ema(e, MAPeriod)) + ta.ema(ta.ema(e, MAPeriod), MAPeriod)
        else if MAType == 'VWMA'
            ta.vwma(MASource, MAPeriod)
        else if MAType == 'ALMA'
            ta.alma(MASource, MAPeriod, .85, 6)
        else if MAType == 'CTI'
            cti(MAPeriod, MASource, 0)
        else if MAType == 'KAMA'
            kama(MASource, MAPeriod)
        else if MAType == 'SWMA'
            ta.swma(MASource)
        else if MAType == 'JMA'
            jma(MASource, MAPeriod, 2, 50)
        else if MAType == 'LSMA'  // Least Squares
            ta.linreg(MASource, MAPeriod, 0)
        else if MAType == 'Wild'
            wild = MASource
            wild := nz(wild[1]) + (MASource - nz(wild[1])) / MAPeriod
            wild
        else if MAType == 'Tillson T3'
            T3ma(MASource, MAPeriod)
        else if MAType == 'VIDYA'
            VIDYA(MASource, MAPeriod)
        else if MAType == 'DWMA'
            ta.wma(ta.wma(MASource, MAPeriod), MAPeriod) // Double Weighted Moving Average
        else if MAType == 'DVWMA'
            ta.vwma(ta.vwma(MASource, MAPeriod), MAPeriod) // Double Volume-Weighted Moving Average
        else if MAType == 'Zero Lag'
            zema(MASource, MAPeriod)
        else if MAType == "Median"
            ta.median(MASource, MAPeriod)
        else if MAType == "RSI EMA"
            rsi_ema(MASource, MAPeriod)
        else if MAType == "ADX MA"
            adx_weighted_ma(MASource, MAPeriod)
        else if MAType == "COVWMA"
            covwma(MASource, MAPeriod)
        else if MAType == "FRAMA"
            frama(MASource, MAPeriod)
        else if MAType == "VAMA"
            factor = 0.67
            vama(MASource, MAPeriod, factor, true, 0)
        else if MAType == "New-WMA"
            NWMA(MASource, MAPeriod)

//_____________________________________________________________________________________________
// Based on "CM MACD Custom Indicator - Multiple Time Frame - V2" - Author: @ChrisMoody
// https://www.tradingview.com/script/XFr7xHqZ-CM-MACD-Custom-Indicator-Multiple-Time-Frame-V2/
//_____________________________________________________________________________________________
// Calculating
src_ma = get_src(src)
fast_media = ma(sma_source, src_ma, fast_length)
slow_media = ma(sma_source, src_ma, slow_length)
fast_ma = request.security(syminfo.tickerid, res, fast_media)
slow_ma = request.security(syminfo.tickerid, res, slow_media)
macd = fast_ma - slow_ma
signal = request.security(syminfo.tickerid, res, ma(ma_signal, macd, signal_length))
hist = (macd - signal)*2
// MACD Trend and Cross Up/Down conditions
trend_up = macd > signal
trend_dn = macd < signal
cross_UP = signal[1] >= macd[1] and signal < macd
cross_DN = signal[1] <= macd[1] and signal > macd
cross_UP_A = signal[1] >= macd[1] and signal < macd and macd > 0
cross_DN_B = signal[1] <= macd[1] and signal > macd and macd < 0
// Condition that changes Color of MACD Line if Show Trend is turned on..
trend_col = show_trend and trend_up ? col_trnd_Up : trend_up ? col_macd : show_trend and trend_dn ? col_trnd_Dn : trend_dn ? col_macd : na

// Var Statements for Histogram Color Change
var bool histA_IsUp   = false
var bool histA_IsDown = false
var bool histB_IsDown = false
var bool histB_IsUp   = false
histA_IsUp   := hist == hist[1] ? histA_IsUp[1]   : hist > hist[1] and hist > 0
histA_IsDown := hist == hist[1] ? histA_IsDown[1] : hist < hist[1] and hist > 0
histB_IsDown := hist == hist[1] ? histB_IsDown[1] : hist < hist[1] and hist <= 0
histB_IsUp   := hist == hist[1] ? histB_IsUp[1]   : hist > hist[1] and hist <= 0

hist_col = histA_IsUp ? col_grow_above : histA_IsDown ? col_fall_above : histB_IsDown ? col_grow_below : histB_IsUp ? col_fall_below : color.silver
color_macd = (macd < signal) and (macd >= 0) ? col_fall_above : (macd > signal) and (macd >= 0) ? col_grow_above : (macd > signal) and (macd < 0) ? col_fall_below : (macd < signal) and (macd < 0) ? col_grow_below : color.silver

// Plot Statements
// Background Color
bgcolor(show_cross and cross_UP ? color.new(col_trnd_Up, 70) : na, editable=false)
bgcolor(show_cross and cross_DN ? color.new(col_trnd_Dn, 70) : na, editable=false)
//Highlight Price Bars
barcolor(show_HB and trend_up ? col_trnd_Up : na, title='Trend Up', offset=0, editable=false)
barcolor(show_HB and trend_dn ? col_trnd_Dn : na, title='Trend Dn', offset=0, editable=false)
// Regular Plots
plot(show_Hist and hist   ? hist   : na, 'Histogram', color.new(hist_col, 0),   style=plot.style_columns, linewidth=show_hist_LW)
plot(show_macd and signal ? signal : na, 'Signal',    color.new(col_signal, 0), style=plot.style_line,    linewidth=show_signal_LW)
plot(show_macd and macd   ? macd   : na, 'MACD',      color.new(trend_col, 0),  style=plot.style_line,    linewidth=show_macd_LW)
hline(0, '0 Line', color.new(color.gray, 0), linestyle=hline.style_dotted, linewidth=1, editable=false)
plot(show_dots and cross_UP ? signal : na, 'Up Dots',   color.new(trend_col, 80), style=plot.style_circles, linewidth=show_dots_LW, editable=false)
plot(show_dots and cross_DN ? signal : na, 'Down Dots', color.new(trend_col, 80), style=plot.style_circles, linewidth=show_dots_LW, editable=false)
bgcolor(show_macd_bg   ? color.new(color_macd, 90) : na, title = "MACD Background")
barcolor(show_macd_bar ? color.new(color_macd, 0)  : na, title = "MACD Bar Colors")

// Alerts
if alert_Long and cross_UP
    alert('Symbol = (' + syminfo.tickerid + ') \n TimeFrame = (' + timeframe.period + ') \n Current Price (' + str.tostring(close) + ') \n MACD Crosses Up.', alert.freq_once_per_bar_close)

if alert_Short and cross_DN
    alert('Symbol = (' + syminfo.tickerid + ') \n TimeFrame = (' + timeframe.period + ') \n Current Price (' + str.tostring(close) + ') \n MACD Crosses Down.', alert.freq_once_per_bar_close)
//Alerts - Stricter Condition - Only Alerts When MACD Crosses UP & MACD > 0 -- Crosses Down & MACD < 0
if alert_Long_A and cross_UP_A
    alert('Symbol = (' + syminfo.tickerid + ') \n TimeFrame = (' + timeframe.period + ') \n Current Price (' + str.tostring(close) + ') \n MACD > 0 And Crosses Up.', alert.freq_once_per_bar_close)

if alert_Short_B and cross_DN_B
    alert('Symbol = (' + syminfo.tickerid + ') \n TimeFrame = (' + timeframe.period + ') \n Current Price (' + str.tostring(close) + ') \n MACD < 0 And Crosses Down.', alert.freq_once_per_bar_close)

// Divergences
hiddenBullColor = color.new(bullColor, 70)
hiddenBearColor = color.new(bearColor, 70)
textColor = color.white
noneColor = color.new(color.white, 100)
osc = show_Hist and divergence == 'Histogram' ? hist : (show_macd ? macd : na)

plFound = na(ta.pivotlow(osc, lbL, lbR))  ? false : true
phFound = na(ta.pivothigh(osc, lbL, lbR)) ? false : true
_inRange(cond) =>
	bars = ta.barssince(cond == true)
	rangeLower <= bars and bars <= rangeUpper

//------------------------------------------------------------------------------
// Regular Bullish
// Osc: Higher Low

oscHL = osc[lbR] > ta.valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1])

// Price: Lower Low

priceLL = low[lbR] < ta.valuewhen(plFound, low[lbR], 1)
bullCond = plotBull and priceLL and oscHL and plFound

plot(
     plFound ? osc[lbR] : na,
     offset=-lbR,
     title="Regular Bullish",
     linewidth=2,
     color=(bullCond ? bullColor : noneColor)
     )

plotshape(
	 bullCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Regular Bullish Label",
	 text=" R ",
	 style=shape.labelup,
	 location=location.absolute,
	 color=bullColor,
	 textcolor=#000000
	 )
	 
//------------------------------------------------------------------------------
// Hidden Bullish
// Osc: Lower Low

oscLL = osc[lbR] < ta.valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1])

// Price: Higher Low

priceHL = low[lbR] > ta.valuewhen(plFound, low[lbR], 1)
hiddenBullCond = plotHiddenBull and priceHL and oscLL and plFound

plot(
	 plFound ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bullish",
	 linewidth=2,
	 color=(hiddenBullCond ? hiddenBullColor : noneColor)
	 )

plotshape(
	 hiddenBullCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bullish Label",
	 text=" H ",
	 style=shape.labelup,
	 location=location.absolute,
	 color=bullColor,
	 textcolor=color.black
	 )

//------------------------------------------------------------------------------
// Regular Bearish
// Osc: Lower High

oscLH = osc[lbR] < ta.valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1])

// Price: Higher High

priceHH = high[lbR] > ta.valuewhen(phFound, high[lbR], 1)

bearCond = plotBear and priceHH and oscLH and phFound

plot(
	 phFound ? osc[lbR] : na,
	 offset=-lbR,
	 title="Regular Bearish",
	 linewidth=2,
	 color=(bearCond ? bearColor : noneColor)
	 )

plotshape(
	 bearCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Regular Bearish Label",
	 text=" R ",
	 style=shape.labeldown,
	 location=location.absolute,
	 color=bearColor,
	 textcolor=textColor
	 )

//------------------------------------------------------------------------------
// Hidden Bearish
// Osc: Higher High

oscHH = osc[lbR] > ta.valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1])

// Price: Lower High

priceLH = high[lbR] < ta.valuewhen(phFound, high[lbR], 1)

hiddenBearCond = plotHiddenBear and priceLH and oscHH and phFound

plot(
	 phFound ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bearish",
	 linewidth=2,
	 color=(hiddenBearCond ? hiddenBearColor : noneColor)
	 )

plotshape(
	 hiddenBearCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bearish Label",
	 text=" H ",
	 style=shape.labeldown,
	 location=location.absolute,
	 color=bearColor,
	 textcolor=textColor
	 )

//______________________________________________________________________________
// The Expert Trend Locator - XTL 
// https://www.tradingview.com/script/UcBJKm4O/
//______________________________________________________________________________
media  = ma(MA_Type2, get_src(src_xtl), period_xtl)
cciNT  = (get_src(src_xtl) - media) / (0.015 * ta.dev(get_src(src_xtl), period_xtl))
cciT   = (get_src(src_xtl) - media) / (0.015 * ta.dev(math.abs(get_src(src_xtl) - media), period_xtl))
values = uTrad ? cciT : cciNT

var color color_XTL = na
if values < -fixed_Value
    color_XTL := color_xtlDN  // Bear
    color_XTL
if -fixed_Value <= values and values <= fixed_Value
    color_XTL := color_xtlNe  // Neutral
    color_XTL
if values > fixed_Value
    color_XTL := color_xtlUP  // Bull
    color_XTL

cond_bull_xtl = detect_bull and ta.crossover(values, fixed_Value)
cond_bear_xtl = detect_bear and ta.crossunder(values, -fixed_Value)

if cond_bull_xtl
    alert('Symbol = (' + syminfo.tickerid + ') \n TimeFrame = (' + timeframe.period + ') \n Current Price (' + str.tostring(close) + ') \n Bullish Trend [XTL].', alert.freq_once_per_bar_close)
if cond_bear_xtl
    alert('Symbol = (' + syminfo.tickerid + ') \n TimeFrame = (' + timeframe.period + ') \n Current Price (' + str.tostring(close) + ') \n Bearish Trend [XTL].', alert.freq_once_per_bar_close)

barcolor(candles_XTL ? color_XTL : na, title='XTL [Expert Trend Locator]')

//______________________________________________________________________________
// Squeeze Momentum [Plus]
// https://www.tradingview.com/script/3mQBizyn/
//______________________________________________________________________________
// Bollinger Bands Basis Line
basis = ma(bbmatype, get_src(src_sqz), length_sqz)
// Keltner Channel Basis Line
basiskc = ma(kcmatype, get_src(src_sqz), length_sqz)
// Keltner Channel Range
range_1 = ma(kcmatype, ta.tr, length_sqz)

// Bollinger Bands Multiplier
multBB = 2.0
// Keltner Channel Low Multiplier
multlowKC = 2.0
// Keltner Channel Mid Multiplier
multmidKC = 1.5
// Keltner Channel High Multiplier
multhighKC = 1.0

// Bollinger Bands 
dev = multBB * ta.stdev(get_src(src_sqz), length_sqz)
upperBB = basis + dev
lowerBB = basis - dev
// Keltner Channel Bands Low 
upperKCl = basiskc + range_1 * multlowKC
lowerKCl = basiskc - range_1 * multlowKC
// Keltner Channel Bands Mid
upperKCm = basiskc + range_1 * multmidKC
lowerKCm = basiskc - range_1 * multmidKC
// Keltner Channel Bands High
upperKCh = basiskc + range_1 * multhighKC
lowerKCh = basiskc - range_1 * multhighKC

//Squeeze On
lowsqz = lowerBB > lowerKCl and upperBB < upperKCl
lsf = lowsqz == false
midsqz = lowerBB > lowerKCm and upperBB < upperKCm
msf = midsqz == false
highsqz = lowerBB > lowerKCh and upperBB < upperKCh
hsf = highsqz == false

//Squeeze Dot Colors
sqz_color = highsqz ? color_H : midsqz ? color_O : lowsqz ? color_L : na

//Squeeze Dot Plot Above 
sqzpro = highsqz ? highsqz : midsqz ? midsqz : lowsqz ? lowsqz : na
plotshape(sqzpro, 'Squeeze Pro', shape.circle, location.top, sqz_color)

//_____________________________________________________________________________________
// Based on "Williams_Vix_Fix_V3_Upper_Text_Plots" - Author: @ChrisMoody
// https://www.tradingview.com/script/1ffumXy5-CM-Williams-Vix-Fix-V3-Upper-Text-Plots/
// https://www.ireallytrade.com/newsletters/VIXFix.pdf
//_____________________________________________________________________________________
// Williams Vix Fix Formula
wvf       = (ta.highest(close, pd) - low) / ta.highest(close, pd) * 100
sDev      = mult * ta.stdev(wvf, bbl)
midLine   = ta.sma(wvf, bbl)
lowerBand = midLine - sDev
upperBand = midLine + sDev
rangeHigh = ta.highest(wvf, lb) * ph

// Filtered Criteria
upRange      = low > low[1] and close > high[1]
upRange_Aggr = close > close[1] and close > open[1]
// Filtered Criteria
filtered      = (wvf[1] >= upperBand[1] or wvf[1] >= rangeHigh[1]) and wvf < upperBand and wvf < rangeHigh
filtered_Aggr = (wvf[1] >= upperBand[1] or wvf[1] >= rangeHigh[1]) and not(wvf < upperBand and wvf < rangeHigh)

// Alerts Criteria
alert1  = wvf >= upperBand or wvf >= rangeHigh ? 1 : 0
alert2  = (wvf[1] >= upperBand[1] or wvf[1] >= rangeHigh[1]) and wvf < upperBand and wvf < rangeHigh ? 1 : 0
cond_FE = upRange and close > close[str] and (close < close[ltLB] or close < close[mtLB]) and filtered 
alert3  = cond_FE ? 1 : 0
cond_AE = upRange_Aggr and close > close[str] and (close < close[ltLB] or close < close[mtLB]) and filtered_Aggr
alert4  = cond_AE ? 1 : 0

plotshape(sbcc and alert1 ? alert1 : na, 'WVF Is True',              shape.triangledown, location.bottom, color.new(#80FF00, 60),    size=size.tiny)
plotshape(sbc and alert2  ? alert2 : na, 'WVF Was True - Now False', shape.triangledown, location.bottom, color.new(color.teal, 60), size=size.tiny)
plotshape(sbcAggr and alert4 ? alert4 : na, 'Aggressive Entry', shape.triangleup, location.bottom, color.new(#80FF00, 20), textcolor=color.new(#80FF00, 20), text='AE', size=size.tiny)
plotshape(sbcFilt and alert3 ? alert3 : na, 'Filtered Entry',   shape.triangleup, location.bottom, color.new(#80FF00, 20), textcolor=color.new(#80FF00, 20), text='FE', size=size.tiny)

if alert_AE and cond_AE
    alert('Symbol = (' + syminfo.tickerid + ') \n TimeFrame = (' + timeframe.period + ') \n Current Price (' + str.tostring(close) + ') \n Aggressive Entry [VixFix].', alert.freq_once_per_bar_close)

if alert_FE and cond_FE
    alert('Symbol = (' + syminfo.tickerid + ') \n TimeFrame = (' + timeframe.period + ') \n Current Price (' + str.tostring(close) + ') \n Filtered Entry [VixFix].', alert.freq_once_per_bar_close)
    
//___________________________________________________________________________________ 
// Colored Directional Movement Index (CDMI) by @dgtrd and @OskarGallard
//___________________________________________________________________________________ 
[diplus, diminus, adxValue] = ta.dmi(lenDi, lenSig)

// J. Welles Wilder, developer of DMI, believed that a DMI reading above 25 indicated a strong trend, 
// while a reading below 20 indicated a weak or non-existent trend.
dmiBull = diplus   >= diminus  and adxValue >= keyLevel
dmiBear = diplus   <  diminus  and adxValue >= keyLevel
dmiWeak = adxValue <  keyLevel and adxValue >  weakTrend

slope_positive = adxValue > adxValue[1]
diCross = bar_index - ta.valuewhen(ta.cross(diplus, diminus), bar_index, 0)
strong = slope_positive ? "Strong" : " "
weak_up_dn = dmiWeak ? (diplus   >= diminus ? "[uptrend]" : "[downtrend]") : ""

// Label
lbStat  = histLabel > 0 ? "\n\n Timeframe: " + timeframe.period + ", " + str.tostring(histLabel) + " bar(s) earlier historical value.-": 
          "\n\n Timeframe: " + timeframe.period + ", last di cross " + str.tostring(diCross) + " bar(s) before.-"

adxMom  = slope_positive ? " ▲ Growing | Previous ADX: " + str.tostring(adxValue[1], "#.##") + ")\n» " : " ▼ Falling | Previous ADX(" + str.tostring(adxValue[1], "#.##") + ")\n» "

diStat  = diplus >= diminus ? "diPlus(" + str.tostring(diplus, "#.##") + ") >= diMinus(" + str.tostring(diminus, "#.##") + ")" :
          "diPlus(" + str.tostring(diplus, "#.##") + ") < diMinus(" + str.tostring(diminus, "#.##") + ")"

dmiText = dmiBull ? strong + " Bullish\n» ADX(" + str.tostring(adxValue, "#.##") + ")" + adxMom + diStat: 
          dmiBear ? strong + " Bearish\n» ADX(" + str.tostring(adxValue, "#.##") + ")" + adxMom + diStat:
          dmiWeak ? "Weak " + weak_up_dn + "\n» ADX(" + str.tostring(adxValue, "#.##") + ")" + adxMom + diStat:
          "No Trend\n» ADX(" + str.tostring(adxValue, "#.##") + ")" + adxMom + diStat

oneDay = 24 * 60 * 60 * 1000
barsAhead = 3
onward = if timeframe.ismonthly
    barsAhead * oneDay * 30
else if timeframe.isweekly
    barsAhead * oneDay * 7
else if timeframe.isdaily
    barsAhead * oneDay
else if timeframe.isminutes
    barsAhead * oneDay * timeframe.multiplier / 1440
else if timeframe.isseconds
    barsAhead * oneDay * timeframe.multiplier / 86400
else
    0

dmiColor = dmiBull ? (slope_positive ? #006400     : color.green) : 
           dmiBear ? (slope_positive ? #910000     : color.red) : 
           dmiWeak ? (slope_positive ? color.black : color.gray) : 
           (slope_positive ? #DAA80A : #FFC40C)  

// Colored DMI
plotshape(diplus >= diminus, '+DI > -DI', shape.triangleup,   location.bottom, dmiColor)
plotshape(diplus < diminus,  '+DI < -DI', shape.triangledown, location.bottom, dmiColor)

alert_dmiBull = detect_bull_dmi and diplus >= diminus and ta.crossover(adxValue, keyLevel)
alert_dmiBear = detect_bear_dmi and diplus <  diminus and ta.crossover(adxValue, keyLevel)

if alert_dmiBull
    alert('Symbol = (' + syminfo.tickerid + ') \n TimeFrame = (' + timeframe.period + ') \n Current Price (' + str.tostring(close) + ') \n Bullish Trend [DMI].', alert.freq_once_per_bar_close)

if alert_dmiBear
    alert('Symbol = (' + syminfo.tickerid + ') \n TimeFrame = (' + timeframe.period + ') \n Current Price (' + str.tostring(close) + ') \n Bearish Trend [DMI].', alert.freq_once_per_bar_close)

// Label
if not hideLabel
    label dmiLabel = label.new(time, 0, text="DMI reading: " + dmiText[histLabel] + lbStat
         ,tooltip="                 ◁ how to read colored dmi ▷\n* triangle shapes:\n  ▲- bullish : diplus >= diminus\n  ▼- bearish : diplus < diminus\n* colors:\n  green - bullish trend : adx >= keyLevel and di+ > di-\n  red - bearish trend : adx >= keyLevel and di+ < di- \n  gray - weak trend : weekTrend < adx < keyLevel\n  yellow - no trend : adx < weekTrend\n* color density:\n  darker : adx growing\n  lighter : adx falling "
         ,color=dmiColor[histLabel], xloc=xloc.bar_time, style=label.style_label_left, textcolor=adxValue[histLabel] < weakTrend ? color.black : color.white, textalign=text.align_left)
    label.set_x(dmiLabel, label.get_x(dmiLabel) + onward)
    label.delete(dmiLabel[1])

 