Extreme Entry with Mean Reversion and Trend Filter
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

//spudow @ edri
//rodavlas12
//@version=5
indicator(title='Extreme Entry with Mean Reversion and Trend Filter', overlay=true, shorttitle='Extreme Entry with MR and TR')

// Input settings
ccimomCross = input.string('CCI', 'Entry Signal Source', options=['CCI', 'Momentum'], tooltip='CCI or Momentum will be the final source of the Entry signal if selected.')
ccimomLength = input.int(10, minval=1, title='CCI/Momentum Length')
useDivergence = input.bool(false, title='Find Regular Bullish/Bearish Divergence', tooltip='If checked, it will only consider an overbought or oversold condition that has a regular bullish or bearish divergence formed inside that level.')
rsiOverbought = input.int(65, minval=1, title='RSI Overbought Level', tooltip='Adjusting the level to extremely high may filter out some signals especially when the option to find divergence is checked.')
rsiOversold = input.int(35, minval=1, title='RSI Oversold Level', tooltip='Adjusting this level extremely low may filter out some signals especially when the option to find divergence is checked.')
rsiLength = input.int(14, minval=1, title='RSI Length')
plotMeanReversion = input.bool(true, 'Plot Mean Reversion on the chart', tooltip='If checked, will use upper and lower bands to filter entry signals that are within or outside the range')
meanReversionFilter = input.string('All Entries', 'Mean Reversion Signal Filter', options=['Range Entries', 'Extreme Entries', 'All Entries'], tooltip='Entry signals filter will function only when Plot Mean Reversal is enabled')
emaPeriod = input(200, title='MR Lookback Period (EMA)')
bandMultiplier = input.float(1.8, title='MR Bands Multiplier', tooltip='Multiplier for both upper and lower bands to adjust the range.')

// Trend Filter Input
enableTrendFilter = input.bool(false, "Enable Trend Filter", tooltip="When enabled, entry signals will be filtered based on the long-term trend.")
emaPeriodFilter = input(200, title="EMA Period (Trend Filter)", tooltip="The period used for the EMA trend filter.")

// CCI and Momentum calculation
momLength = ccimomCross == 'Momentum' ? ccimomLength : 10
mom = close - close[momLength]
cci = ta.cci(close, ccimomLength)
ccimomCrossUp = ccimomCross == 'Momentum' ? ta.cross(mom, 0) : ta.cross(cci, 0)
ccimomCrossDown = ccimomCross == 'Momentum' ? ta.cross(0, mom) : ta.cross(0, cci)

// RSI calculation
src = close
up = ta.rma(math.max(ta.change(src), 0), rsiLength)
down = ta.rma(-math.min(ta.change(src), 0), rsiLength)
rsi = down == 0 ? 100 : up == 0 ? 0 : 100 - 100 / (1 + up / down)
oversoldAgo = rsi[0] <= rsiOversold or rsi[1] <= rsiOversold or rsi[2] <= rsiOversold or rsi[3] <= rsiOversold
overboughtAgo = rsi[0] >= rsiOverbought or rsi[1] >= rsiOverbought or rsi[2] >= rsiOverbought or rsi[3] >= rsiOverbought

// Regular Divergence Conditions
bullishDivergenceCondition = rsi[0] > rsi[1] and rsi[1] < rsi[2]
bearishDivergenceCondition = rsi[0] < rsi[1] and rsi[1] > rsi[2]

// Entry Conditions
longEntryCondition = ccimomCrossUp and oversoldAgo and (not useDivergence or bullishDivergenceCondition)
shortEntryCondition = ccimomCrossDown and overboughtAgo and (not useDivergence or bearishDivergenceCondition)

// Mean Reversion Indicator
meanReversion = plotMeanReversion ? ta.ema(close, emaPeriod) : na
stdDev = plotMeanReversion ? ta.stdev(close, emaPeriod) : na
upperBand = plotMeanReversion ? meanReversion + stdDev * bandMultiplier : na
lowerBand = plotMeanReversion ? meanReversion - stdDev * bandMultiplier : na

// Apply signal filtering based on mean reversion bands
if plotMeanReversion
    if meanReversionFilter == 'Range Entries'
        longEntryCondition := na(longEntryCondition) ? na : longEntryCondition and (close > lowerBand and close < upperBand)
        shortEntryCondition := na(shortEntryCondition) ? na : shortEntryCondition and (close > lowerBand and close < upperBand)
    else if meanReversionFilter == 'Extreme Entries'
        longEntryCondition := na(longEntryCondition) ? na : longEntryCondition and (close < lowerBand or close > upperBand)
        shortEntryCondition := na(shortEntryCondition) ? na : shortEntryCondition and (close < lowerBand or close > upperBand)

// Trend Filter
emaPeriodFiltered = enableTrendFilter ? ta.ema(close, emaPeriodFilter) : na
 
// Apply trend filter to entry conditions
if enableTrendFilter
    longEntryCondition := longEntryCondition and (close > emaPeriodFiltered)
    shortEntryCondition := shortEntryCondition and (close < emaPeriodFiltered)

// Plotting
plotshape(longEntryCondition, title='BUY', style=shape.triangleup, text='B', location=location.belowbar, color=color.new(color.lime, 0), textcolor=color.new(color.white, 0), size=size.tiny)
plotshape(shortEntryCondition, title='SELL', style=shape.triangledown, text='S', location=location.abovebar, color=color.new(color.red, 0), textcolor=color.new(color.white, 0), size=size.tiny)

plot(plotMeanReversion ? upperBand : na, title='Upper Band', color=color.new(color.fuchsia, 0), linewidth=1)
plot(plotMeanReversion ? meanReversion : na, title='Mean', color=color.new(color.gray, 0), linewidth=1)
plot(plotMeanReversion ? lowerBand : na, title='Lower Band', color=color.new(color.blue, 0), linewidth=1)

// Plot EMA when Trend Filter is enabled
plot(enableTrendFilter ? emaPeriodFiltered : na, color=color.new(color.orange, 0), title="EMA (Trend Filter)")

// Entry signal alerts
alertcondition(longEntryCondition, title='BUY Signal', message='Buy Entry Signal')
alertcondition(shortEntryCondition, title='SELL Signal', message='Sell Entry Signal')
alertcondition(longEntryCondition or shortEntryCondition, title='BUY or SELL Signal', message='Entry Signal')
 