RF+ Divergence Scalping System
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ 
// © tvenn

//@version=5
indicator(title="RF+ Divergence Scalping System", shorttitle="RF+", overlay = true, max_bars_back = 1000, max_lines_count = 400, max_labels_count = 400)
// strategy(title="RF+ strategies", max_bars_back = 1000, max_labels_count = 400, max_lines_count = 400, initial_capital = 10000, default_qty_value = 10, slippage = 5 )

//=Constants
green = #95BD5F
red = #EA1889
mocha = #C0A392

//=Range Filters
//==================================================================================================================================
showDashboard       = input(false, title="Show Dashboard", inline='1')
dashboardPosition   = input.string(title='', defval='Top Right', options=['Top Right', 'Bottom Right', 'Top Left', 'Bottom Left'], inline='1')
dashboardSize       = input.string(title='', defval='Mobile', options=['Mobile', 'Desktop'], inline='1')
showRangeFilters    = input(true, title="Show Range Filters", tooltip="The 2x Range Filters can be used to help indicate short term trend direction. When both Range Filters change colour can help to determine when price is ready to reverse, especially helpful in timing entries for regular divergences and avoiding entering too early, where price can often take some time before it actually begins to reverse. A common mistake in trading divergences is to enter too early.")
showMTFSignals      = input(true, title="Show MTF Signals")
showRealPriceLine   = input(false, title="Show Real Price Line", tooltip="This will show a real price line for use with Heikin Ashi candles.\n\nNOTE: this feature may lag slightly due to the large number of features. Consider using a standalone indicator such as 'Real Price Line + Dots (for Heikin Ashi), linked in my Tradingview profile.")
showRealCloseDots   = input(false, title="Show Real Price Close Dots", tooltip="This will show real price close dots on each candle, for use with Heikin Ashi candles.\n\nNOTE: this feature may lag slightly due to the large number of features. Consider using a standalone indicator such as 'Real Price Line + Dots (for Heikin Ashi), linked in my Tradingview profile")
enableMA            = input(true, title="Show Moving Averages")
enableMTFMA         = input(true, title="Show MTF Moving Averages", tooltip="Enabling this will show the various levels of the selected moving average for each of the selected timeframes below on a single chart, shown as a horizontal line on the right of the chart.\n\nThis can help identify levels at which price may react to the moving average (which may occur on multiple timeframes) without having to monitor those additional chart timeframes directly.")
showVWAP            = input(false, title="Show VWAP", inline="vwap")
showpivot           = input(false, title="Show Pivot Points")
showWatermark       = input(true, title="Show Watermark")


//=Divergence settings
//==================================================================================================================================
grp_div     = "Divergence settings"
showlines   = input(defval = true, title = "Show Divergence Lines", group=grp_div)
showlast    = input(defval = true, title = "Show Only Last Divergence", group=grp_div)
shownum     = input(defval = false, title = "Show Divergence Number", group=grp_div)
dontconfirm = input(defval = false, title = "Don't Wait for Confirmation", group=grp_div)

showConfirmlines= input(defval = false, title = "Show Regular Divergence Confirm Lines", group=grp_div, tooltip="This will place a horizontal line extending right from the startpoint of regular divergences, these lines can be used as a confirmation entry level into some regular divergence reversal trades, if and when price reverses, and pushes past this level.\n\nThey will not be shown for hidden divergences.")
confirmLineLen = input.int(20, title="Extend Regular Divergence Confirm Line", group=grp_div)

showindis = input.string(defval = "Don't Show", title = "Show Indicator Names", options = ["Full", "First Letter", "Don't Show"], group=grp_div)
searchdiv = input.string(defval = "Regular/Hidden", title = "Show Divergence Type", options = ["Regular", "Hidden", "Regular/Hidden"], group=grp_div)
showlimit = input.int(1, title="Minimum Number of Divergence", minval = 1, maxval = 11, group=grp_div)


//=Custom confluence signals
//==================================================================================================================================
grp_SIGNALS                 = "Custom signals"
MTFOBOSDivSignal            = input(true, title="Show MTF CCI/Stoch RSI OB/OS + Div", group=grp_SIGNALS, tooltip="Places label to indicate where MTF Stoch RSI / MTF CCI oversold AND recent bullish divergence, and where MTF Stoch RSI / MTF CCI overbought AND recent bearish divergence.\n\nYou can alert these using the alert called 'MTF OB/OS + Div on RF+'")
showpullbackdivergence      = input(false, title="Show RF Pullbacks with Divergences", group=grp_SIGNALS, tooltip="Icons will show signals for long entries:\n\n1) Price closes beneath 2x uptrending Range Filters and\n2) That candle also forms a bullish divergence that supports the direction of the Range Filters\n\nAnd for short entries:\n\n1) Price closes above 2x downtrending Range Filters and\n2) That candle also forms a bearish divergence that supports the direction of the Range Filters.\n\nThese signals represent a possible entry into a trend continuation trade in the direction indicated by the 2xRFs and the suppporting divergence.\n\nDesigned primarily for the 2-3m timeframes, but also work on higher timeframes.")
showFilteredDivEntryCriteria= input(false, title="Show Divs Filtered by 21sma + RSI MA (for 15m)", group=grp_SIGNALS, tooltip="Show divergence signals that are filtered by\n\nFor buy signals\n1) Price above the 21sma and\n2) Has a recent bullish divergence and\n3) RSI above the RSI moving average\n\n Or\n\nFor sell signals\n1)Price is below 21sma and\n2) Has recent bearish divergence and\n3) RSI is below the RSI moving average.\n\nThe RSI moving average trend filter settings are found under the section in this settings menu called RSI trend filter. This signal is designed for the 15 minute timeframe.\n\nSignals print gold triangle")


//=Select divergence indicators
//==================================================================================================================================

grp_DIVINDI = "Use divergences from indicators"
calcuo      = input(defval = true, title = "UO", group=grp_DIVINDI)
calctsi     = input(defval = true, title = "TSI", group=grp_DIVINDI)
calcufo     = input(defval = true, title = "UFO", group=grp_DIVINDI, tooltip="This is a hybrid of the UO x MFI, the oscillator is calculated by taking an average of the two values.\n\UFO = (UO_Value + MFI_Value) / 2")
calcrsi     = input(defval = true, title = "RSI", group=grp_DIVINDI)
calcmfi     = input(defval = true, title = "MFI", group=grp_DIVINDI)
calccci     = input(defval = false, title = "CCI", group=grp_DIVINDI)
calccdv     = input(defval = false, title = "CDV", group=grp_DIVINDI)
calcstoc    = input(defval = false, title = "Stochastic", group=grp_DIVINDI)



//=Real price line & real price close dots
//==================================================================================================================================

//Real price line and dot settings
grp_HA                  = "Real price for Heikin Ashi candles"
realclosedotscolor      = input(color.new(color.aqua, 50), title="Real Price Close Dot Color", group=grp_HA)
showRealPriceLinelinecolor = input(color.new(color.aqua, 0), title="Real Price Line Color", group=grp_HA)
realpricewidth          = input.int(1, options=[1, 2], title="Real Price Line Width", group=grp_HA)

real_price = ticker.new(prefix=syminfo.prefix, ticker=syminfo.ticker)
real_close = request.security(symbol=real_price, timeframe='', expression=close, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_off)

if(showRealPriceLine)
    real_price_line = line.new(bar_index[1], real_close, bar_index, real_close, xloc.bar_index, extend.both, showRealPriceLinelinecolor, line.style_dotted, realpricewidth)
    line.delete(real_price_line[1])


//Show real price close dots
plotshape(series=real_close, title="Real price close dots", location=location.absolute, color=realclosedotscolor, editable=false, style=shape.circle, size=size.auto, display=(showRealCloseDots ? display.all : display.none))


// =MTF Stoch
//==================================================================================================================================
grp_MTFSRSI = "MTF Stoch RSI"
smoothK     = input.int(3, "K", minval=1, group=grp_MTFSRSI)
smoothD     = input.int(3, "D", minval=1, group=grp_MTFSRSI)
lengthRSI   = input.int(14, "RSI Length", minval=1, group=grp_MTFSRSI)
lengthStoch = input.int(14, "Stochastic Length", minval=1, group=grp_MTFSRSI)
rsi1        = ta.rsi(close, lengthRSI)
k           = ta.sma(ta.stoch(rsi1, rsi1, rsi1, lengthStoch), smoothK)
d           = ta.sma(k, smoothD)


grp_CTFSRSI1         = "Show Current Timeframe OB/OS in Ribbon"
includeCurrentTFOBOS = input(true, title="Show Current Timeframe OB/OS Ribbon", group=grp_CTFSRSI1, tooltip="this will include in the ribbon indications where the Stoch RSI is overbought or oversold on the current timeframe")
CTF_1                 = input.string("Chart", title="CTF", options=["Chart"], group=grp_CTFSRSI1, inline="tf1")
CTF_OSTHRESH_1        = input(20, title="", group=grp_CTFSRSI1, inline="tf1")
CTF_OBTHRESH_1        = input(80, title="", group=grp_CTFSRSI1, inline="tf1")


//Primary MTF Stoch RSI confluences
grp_MTFSRSI1             = "MTF Stoch RSI"
stochRSIRibbonPosition   = input.string('Bottom', title="Stoch RSI Ribbon Position", options=['Top', 'Bottom'], group=grp_MTFSRSI1)
overboughtColor_1        = input.color(red, title="Stoch Overbought Color", group=grp_MTFSRSI1)
oversoldColor_1          = input.color(green, title="Stoch Oversold Color", group=grp_MTFSRSI1)
enableOBOS_1             = input(true, title="Show MTF Stoch RSI OB/OS in ribbon", group=grp_MTFSRSI1, tooltip="This will show a ribbon to indicate the MTF Stoch RSI overbought and oversold confuences")
useBgColorMTFStochOBOS_1 = input(false, title="Color Background where MTF Stoch RSI OB/OS", group=grp_MTFSRSI1, tooltip="his will color the background of the chart to indicate the MTF Stoch RSI overbought and oversold confuences")
useBarColorMTFStochOBOS_1= input(false, title="Color Candles where MTF Stoch RSI OB/OS", group=grp_MTFSRSI1, tooltip="his will color the candles on the chart to indicate the MTF Stoch RSI overbought and oversold confuences")


grp_MTFSRSI1_ = "Stoch RSI MTF [Timeframe] [OS level] [OB level]"
TF_1 = input.string("1", title="TF1", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group=grp_MTFSRSI1_, inline="mtf1")
TF_2 = input.string("5", title="TF2", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group=grp_MTFSRSI1_, inline="mtf2")
TF_3 = input.string("15", title="TF3", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group=grp_MTFSRSI1_, inline="mtf3")

MTF_OSTHRESH_1 = input(20, title="", group=grp_MTFSRSI1_, inline="mtf1")
MTF_OSTHRESH_2 = input(20, title="", group=grp_MTFSRSI1_, inline="mtf2")
MTF_OSTHRESH_3 = input(20, title="", group=grp_MTFSRSI1_, inline="mtf3")

MTF_OBTHRESH_1 = input(80, title="", group=grp_MTFSRSI1_, inline="mtf1")
MTF_OBTHRESH_2 = input(80, title="", group=grp_MTFSRSI1_, inline="mtf2")
MTF_OBTHRESH_3 = input(80, title="", group=grp_MTFSRSI1_, inline="mtf3")


MTF1 = request.security(syminfo.tickerid, TF_1 == "Chart" ? "" : TF_1, k, barmerge.gaps_off)
MTF2 = request.security(syminfo.tickerid, TF_2 == "Chart" ? "" : TF_2, k, barmerge.gaps_off)
MTF3 = request.security(syminfo.tickerid, TF_3 == "Chart" ? "" : TF_3, k, barmerge.gaps_off)

allMTFStochOB_1 = (MTF1 > MTF_OBTHRESH_1 and MTF2 > MTF_OBTHRESH_2 and MTF3 > MTF_OBTHRESH_3)
allMTFStochOS_1 = (MTF1 < MTF_OSTHRESH_1 and MTF2 < MTF_OSTHRESH_2 and MTF3 < MTF_OSTHRESH_3)

obColor_1 = (k > CTF_OBTHRESH_1+10 ? color.new(overboughtColor_1, 50) : enableOBOS_1 and k > CTF_OBTHRESH_1+10 ? color.new(overboughtColor_1, 70) : na)
osColor_1 = (k < CTF_OSTHRESH_1-10 ? color.new(oversoldColor_1, 50) : enableOBOS_1 and k < CTF_OSTHRESH_1 ? color.new(oversoldColor_1, 70) : na)

allOBColor_1 = (allMTFStochOB_1 ? overboughtColor_1 : na)
allOSColor_1 = (allMTFStochOS_1 ? oversoldColor_1 : na)

_stochRSIRibbonPosition = switch stochRSIRibbonPosition
    "Top" => location.top
    "Bottom" => location.bottom

plotchar(k, title="Current TF SRSI overbought", color=(includeCurrentTFOBOS ? obColor_1 : na), char="■", location=_stochRSIRibbonPosition)
plotchar(k, title="Current TF SRSI oversold", color=(includeCurrentTFOBOS ? osColor_1 : na), char="■", location=_stochRSIRibbonPosition)
plotchar(k, title="All overbought/oversold", color=(enableOBOS_1 and showMTFSignals and allMTFStochOB_1 ? allOBColor_1 : (enableOBOS_1 and showMTFSignals and allMTFStochOS_1 ? allOSColor_1 : na)), char="■", location=_stochRSIRibbonPosition)
// plotchar(k, title="3x TF all oversold", color=(enableOBOS_1 ? allOSColor_1 : na), char="■", location=_stochRSIRibbonPosition)

//bgcolor
bgcolor((useBgColorMTFStochOBOS_1 and allMTFStochOB_1 and showMTFSignals ? color.new(allOBColor_1, 90) : (useBgColorMTFStochOBOS_1 and allMTFStochOS_1 and showMTFSignals ? color.new(allOSColor_1, 90) : na)), title='Stoch RSI OB/OS background colour')
barcolor(useBarColorMTFStochOBOS_1 and allMTFStochOB_1 and showMTFSignals ? allOBColor_1 : (useBarColorMTFStochOBOS_1 and allMTFStochOS_1 and showMTFSignals ? allOSColor_1 : na))

// =MTF CCI
//==================================================================================================================================

grp_CCI = "MTF CCI settings"
ccisrc = input(hlc3, title="CCI Source", group=grp_CCI)
ccilen = input(20, title="CCI Length", group=grp_CCI)
cci_val = ta.cci(ccisrc, ccilen) // CCI

cciRibbonPosition       = input.string('Top', title="CCI Ribbon Position", options=['Top', 'Bottom'], group=grp_CCI)
overboughtColorCCI      = input(color.rgb(175, 49, 49), title="CCI Overbought Color", group=grp_CCI)
oversoldColorCCI        = input(color.rgb(49, 117, 51), title="CCI Oversold Color", group=grp_CCI)
enableOBOSCCI           = input(true, title="Enable MTF CCI OB/OS Ribbon", group=grp_CCI)
useBgColorMTFCCIOBOS    = input(false, title="Color Background where MTF CCI OB/OS", group=grp_CCI, tooltip="his will color the background of the chart to indicate the MTF CCI overbought and oversold confuences")
useBarColorMTFCCIOBOS   = input(false, title="Color Candles where MTF CCI OB/OS", group=grp_CCI, tooltip="his will color the candles on the chart to indicate the MTF CCI overbought and oversold confuences")


includeCurrentTFOBOSCCI = input(true, title="Show Current Timeframe OB/OS in Ribbon", group="Current timeframe [Timeframe] [OS level] [OB level]", tooltip="this will include in the ribbon indications where the CCI is overbought or oversold on the current timeframe")
CCICTF_1 = input.string("Chart", title="CTF", options=["Chart"], group="Current timeframe [Timeframe] [OS level] [OB level]", inline="tf1")
CCICTF_OSTHRESH_1 = input(-150, title="", group="Current timeframe [Timeframe] [OS level] [OB level]", inline="tf1")
CCICTF_OBTHRESH_1 = input(150, title="", group="Current timeframe [Timeframe] [OS level] [OB level]", inline="tf1")

//MTF CCI confluences
CCITF_1 = input.string("1", title="TF1", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf1")
CCITF_2 = input.string("5", title="TF2", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf2")
CCITF_3 = input.string("15", title="TF3", options=["Chart", "1", "2", "3", "4", "5", "8", "10", "15", "20", "30", "45", "60", "120", "240"], group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf3")

CCIMTF_OSTHRESH_1 = input(-150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf1")
CCIMTF_OSTHRESH_2 = input(-150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf2")
CCIMTF_OSTHRESH_3 = input(-150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf3")

CCIMTF_OBTHRESH_1 = input(150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf1")
CCIMTF_OBTHRESH_2 = input(150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf2")
CCIMTF_OBTHRESH_3 = input(150, title="", group="CCI MTF confluences [Timeframe] [OS level] [OB level]", inline="mtf3")


CCIMTF1 = request.security(syminfo.tickerid, CCITF_1 == "Chart" ? "" : CCITF_1, cci_val, barmerge.gaps_off)
CCIMTF2 = request.security(syminfo.tickerid, CCITF_2 == "Chart" ? "" : CCITF_2, cci_val, barmerge.gaps_off)
CCIMTF3 = request.security(syminfo.tickerid, CCITF_3 == "Chart" ? "" : CCITF_3, cci_val, barmerge.gaps_off)

allMTFCCIOB = (CCIMTF1 > CCIMTF_OBTHRESH_1 and CCIMTF2 > CCIMTF_OBTHRESH_2 and CCIMTF3 > CCIMTF_OBTHRESH_3)
allMTFCCIOS = (CCIMTF1 < CCIMTF_OSTHRESH_1 and CCIMTF2 < CCIMTF_OSTHRESH_2 and CCIMTF3 < CCIMTF_OSTHRESH_3)

obColorCCI = (cci_val > CCICTF_OBTHRESH_1+20 ? color.new(overboughtColorCCI, 50) : cci_val > CCICTF_OBTHRESH_1 ? color.new(overboughtColorCCI, 70) : na)
osColorCCI = (cci_val < CCICTF_OSTHRESH_1-20 ? color.new(oversoldColorCCI, 50) : cci_val < CCICTF_OSTHRESH_1 ? color.new(oversoldColorCCI, 70) : na)

allOBColorCCI = (allMTFCCIOB ? overboughtColorCCI : na)
allOSColorCCI = (allMTFCCIOS ? oversoldColorCCI : na)

_cciRibbonPosition = switch cciRibbonPosition
    "Top" => location.top
    "Bottom" => location.bottom

plotchar(cci_val, title="Current TF overbought", color=(enableOBOSCCI and includeCurrentTFOBOSCCI ? obColorCCI : na), char="■", location=_cciRibbonPosition, size=size.auto)
plotchar(cci_val, title="Current TF oversold", color=(enableOBOSCCI and includeCurrentTFOBOSCCI ? osColorCCI : na), char="■", location=_cciRibbonPosition, size=size.auto)
plotchar(cci_val, title="All overbought/oversold", color=(enableOBOSCCI and showMTFSignals and allMTFCCIOB ? allOBColorCCI : (enableOBOSCCI and showMTFSignals and allMTFCCIOS ? allOSColorCCI : na)), char="■", location=_cciRibbonPosition, size=size.auto)
// plotchar(cci_val, title="All oversold", color=(enableOBOSCCI ? allOSColorCCI : na), char="■", location=_cciRibbonPosition, size=size.auto)

bgcolor((useBgColorMTFCCIOBOS and allMTFCCIOB and showMTFSignals ? color.new(allOBColorCCI, 80) : (useBgColorMTFCCIOBOS and allMTFCCIOS and showMTFSignals ? color.new(allOSColorCCI, 80) : na)), title='CCI OB/OS background colour')
barcolor(useBarColorMTFCCIOBOS and allMTFCCIOB and showMTFSignals ? allOBColorCCI : (useBarColorMTFCCIOBOS and allMTFCCIOS and showMTFSignals ? allOSColorCCI : na))

grp_CombiMTF        = "Combi MTF signals"
showCombiMTF        = input.bool(true, title="Show combi MTF CCI and Stoch RSI signals", group=grp_CombiMTF, tooltip="This will show where both the MTF CCI and MTF Stoch RSI overbought and oversold occur together")
showCombiMTFOBColor = input.color(color.new(red, 75), title="Combi MTF Overbought Color", group=grp_CombiMTF)
showCombiMTFOSColor = input.color(color.new(green, 75), title="Combi MTF Oversold Color", group=grp_CombiMTF)

//MTF CCI AND StochRSI BOTH overbought / oversold
bgcolor(showCombiMTF and allMTFCCIOB and allMTFStochOB_1 and showMTFSignals ? showCombiMTFOBColor : (showCombiMTF and allMTFCCIOS and allMTFStochOS_1 and showMTFSignals ? showCombiMTFOSColor : na), title="MTF CCI AND MTF StochRSI Both OB/OS")


//=Moving averages
//==================================================================================================================================

ma(length, type) =>
    switch type
        "SMA" => ta.sma(close, length)
        "EMA" => ta.ema(close, length)
        "SMMA (RMA)" => ta.rma(close, length)
        "WMA" => ta.wma(close, length)
        "VWMA" => ta.vwma(close, length)
        "HULLMA" => ta.wma(2*ta.wma(close, length/2)-ta.wma(close, length), math.floor(math.sqrt(length)))

grp_MA      = "Moving averages"

ma1color    = input(color.new(color.orange, 40), title="", group=grp_MA, inline="1")
lenMA1      = input(144, title="", group=grp_MA, inline="1")
typeMA1     = input.string(title = "", defval = "EMA", options=["EMA", "SMA", "SMMA (RMA)", "WMA", "VWMA", "HULLMA"], group=grp_MA, inline="1")
showma1     = input(true, title="Enable", group=grp_MA, inline="1")

ma2color    = input(color.new(color.white, 40), title="", group=grp_MA, inline="2")
lenMA2      = input(50, title="", group=grp_MA, inline="2")
typeMA2     = input.string(title = "", defval = "EMA", options=["EMA", "SMA", "SMMA (RMA)", "WMA", "VWMA", "HULLMA"], group=grp_MA, inline="2")
showma2     = input(false, title="Enable", group=grp_MA, inline="2")

ma3color    = input(color.new(red, 40), title="", group=grp_MA, inline="3")
lenMA3      = input(21, title="", group=grp_MA, inline="3")
typeMA3     = input.string(title = "", defval = "EMA", options=["EMA", "SMA", "SMMA (RMA)", "WMA", "VWMA", "HULLMA"], group=grp_MA, inline="3")
showma3     = input(false, title="Enable", group=grp_MA, inline="3")

plot(showma1 and enableMA ? ma(lenMA1, typeMA1) : na, title="MA 1", color = ma1color, linewidth=1, display = display.pane)
plot(showma2 and enableMA ? ma(lenMA2, typeMA2) : na, title="MA 2", color = ma2color, linewidth=1, display = display.pane)
plot(showma3 and enableMA ? ma(lenMA3, typeMA3) : na, title="MA 3", color = ma3color, linewidth=1, display = display.pane)


//=VWAP Settings
//==================================================================================================================================
grp_VWAP	= "Anchored VWAP Settings"
vwapColor   = input.color(color.new(color.aqua, 0), title="", group=grp_VWAP, inline="vwap")
anchor      = input.string("2 Day", title="", options=["1 Day", "2 Day", "Week", "Month"], group=grp_VWAP, inline="vwap")
src         = input(hlc3, title="", group=grp_VWAP, inline="vwap")
stdevMult   = input(1.0, title="", group=grp_VWAP, inline="vwapdev")
showVWAPBand= input(true, title="Show Deviation Band Multiplier", group=grp_VWAP, inline="vwapdev")


if barstate.islast and ta.cum(volume) == 0
    runtime.error("No volume is provided by the data vendor.")

isNewPeriod = switch anchor
	"1 Day"   	=> timeframe.change("D")
	"2 Day"		=> timeframe.change("2D")
	"Week"      => timeframe.change("W")
	"Month"     => timeframe.change("M")
	=> false

if na(src[1])
	isNewPeriod := true

float vwapValue = na
float upperBandValue1 = na
float lowerBandValue1 = na

if not (timeframe.isdwm) //Hide VWAP on charts 1D or Above
    [_vwap, _stdevUpper, _] = ta.vwap(src, isNewPeriod, 1)
	vwapValue := _vwap
    stdevAbs = _stdevUpper - _vwap
	upperBandValue1 := showVWAP ? (_vwap + stdevAbs * stdevMult) : na
	lowerBandValue1 := showVWAP ? (_vwap - stdevAbs * stdevMult) : na

plot((showVWAP ? vwapValue : na), title="VWAP", color=vwapColor)
fill(plot(upperBandValue1, title="Upper Band #1", color=color.new(vwapColor, 70), display = showVWAPBand ? display.all : display.none), plot(lowerBandValue1, title="Lower Band #1", color=color.new(vwapColor, 70), display = showVWAPBand ? display.all : display.none), title="Bands Fill #1", color= color.new(vwapColor, 97), display = showVWAPBand ? display.all : display.none)



//=MTF MA settings
//==================================================================================================================================
grp_MTFMA   = "MTF MA Settings"
MTFMALen    = input.int(144, title="", minval=2, maxval=200, step=1, group=grp_MTFMA, inline="0")
MTFMAType   = input.string("EMA", title="", options=["SMA", "EMA", "SMMA (RMA)", "WMA", "VWMA", "HULLMA"], group=grp_MTFMA, inline="0")

realPriceTicker = ticker.new(prefix=syminfo.prefix, ticker=syminfo.ticker)

getTimeframe(timeframe) =>
    switch timeframe
        "1m" => "1"
        "2m" => "2"
        "3m" => "3"
        "5m" => "5"
        "10m" => "10"
        "15m" => "15"

// MTF MA #1
tf1LineColor 	= input.color(color.new(color.orange, 40), title="", group=grp_MTFMA, inline='1')
tf1 			= input.string("3m", title="", options=["1m", "2m", "3m", "5m", "10m", "15m"], group=grp_MTFMA, inline='1')
enableTF1 		= input.bool(true, title='Show Level', group=grp_MTFMA, inline='1', tooltip="")
// MTF MA #2 
tf2LineColor 	= input.color(color.new(color.orange, 40), title="", group=grp_MTFMA, inline='2')
tf2 			= input.string("5m", title="", options=["1m", "2m", "3m", "5m", "10m", "15m"], group=grp_MTFMA, inline='2')
enableTF2 		= input.bool(true, title='Show Level', group=grp_MTFMA, inline='2')
// MTF MA #3 
tf3LineColor 	= input.color(color.new(color.orange, 40), title='', group=grp_MTFMA, inline='3')
tf3 		 	= input.string("15m", title='', options=["1m", "2m", "3m", "5m", "10m", "15m"], group=grp_MTFMA, inline='3')
enableTF3		= input.bool(true, title='Show Level', group=grp_MTFMA, inline='3')

mtf1MA          = request.security(symbol=realPriceTicker, timeframe=getTimeframe(tf1), expression=ma(MTFMALen, MTFMAType), lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_off)
mtf2MA          = request.security(symbol=realPriceTicker, timeframe=getTimeframe(tf2), expression=ma(MTFMALen, MTFMAType), lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_off)
mtf3MA          = request.security(symbol=realPriceTicker, timeframe=getTimeframe(tf3), expression=ma(MTFMALen, MTFMAType), lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_off)

mtfMATextColor 	= input.color(color.new(color.orange, 70), title="", group=grp_MTFMA, inline="4")
showTFLabel     = input.bool(true, title='Show Timeframe Labels', group=grp_MTFMA, inline="4")

if (enableMTFMA and enableTF1)
	mtf1MALine = line.new(x1=bar_index, x2=bar_index + 10, y1=mtf1MA, y2=mtf1MA, extend=extend.right, style=line.style_dotted, color=tf1LineColor)
	line.delete(mtf1MALine[1])
	if(showTFLabel)
		mtf1MALabel = label.new(x=(bar_index + 20), y=mtf1MA, style=label.style_label_down, text=tf1, color=na, textcolor=mtfMATextColor)
		label.delete(mtf1MALabel[1])

if(enableMTFMA and enableTF2)
	mtf2MALine = line.new(x1=bar_index, x2=bar_index + 10, y1=mtf2MA, y2=mtf2MA, extend=extend.right, style=line.style_dotted, color=tf2LineColor)
	line.delete(mtf2MALine[1])
	if(showTFLabel)
		mtf2MALabel = label.new(x=(bar_index + 20), y=mtf2MA, style=label.style_label_down, text=tf2, color=na, textcolor=mtfMATextColor)
		label.delete(mtf2MALabel[1])

if(enableMTFMA and enableTF3)
	mtf3MALine = line.new(x1=bar_index, x2=bar_index + 10, y1=mtf3MA, y2=mtf3MA, extend=extend.right, style=line.style_dotted, color=tf3LineColor)
	line.delete(mtf3MALine[1])
	if(showTFLabel)
		mtf3MALabel = label.new(x=(bar_index + 20), y=mtf3MA, style=label.style_label_down, text=tf3, color=na, textcolor=mtfMATextColor)
		label.delete(mtf3MALabel[1])



//=Range Filter settings
//==================================================================================================================================

grp_RF = "Range Filters"


//Range Filter #1 Settings
grp_RF1 = "Range Filter #1 settings"
rf1UpColor   = input.color(color.new(#CCCCCC, 50), title="Range Filter 1 Bullish Color", group=grp_RF1)
rf1DownColor = input.color(color.new(color.blue, 50), title="Range Filter 1 Bearish Color", group=grp_RF1)
rf1LineWidth = input.int(1, minval=1, maxval=3, title="Range Filter 1 Line Width", group=grp_RF1)
src1    = input(defval=hl2, title="Source", group=grp_RF1)
per1    = input(defval=30, title="Sampling Period", group=grp_RF1)
mult1   = input(defval=2.6, title="Range Multiplier", group=grp_RF1)

//Range Filter #2 Settings
grp_RF2 = "Range Filter #2 settings"
rf2UpColor   = input.color(color.new(#CCCCCC, 0), title="Range Filter 2 Bullish Color", group=grp_RF2)
rf2DownColor = input.color(color.new(color.blue, 0), title="Range Filter 2 Bearish Color", group=grp_RF2)
rf2LineWidth = input.int(2, minval=1, maxval=3, title="Range Filter 2 Line Width", group=grp_RF2)
src2    = input(defval=ohlc4, title="Source", group=grp_RF2)
per2    = input(defval=48, title="Sampling Period", group=grp_RF2)
mult2   = input(defval=3.4, title="Range Multiplier", group=grp_RF2)

// Smooth average
smoothrng(x, t, m) =>
    wper = t * 2 - 1
    avrng = ta.ema(math.abs(x - x[1]), t)
    smoothrng = ta.ema(avrng, wper) * m
    smoothrng
smrng1 = smoothrng(src1, per1, mult1)
smrng2 = smoothrng(src2, per2, mult2)

// Range Filter calculation
rngfilt(x, r) =>
    rngfilt = x
    rngfilt := x > nz(rngfilt[1]) ? x - r < nz(rngfilt[1]) ? nz(rngfilt[1]) : x - r : 
       x + r > nz(rngfilt[1]) ? nz(rngfilt[1]) : x + r
    rngfilt
filt1 = rngfilt(src1, smrng1)
filt2 = rngfilt(src2, smrng2)

//RF Filter direction
upward1     = 0.0
downward1   = 0.0
upward2     = 0.0
downward2   = 0.0
upward1     := filt1 > filt1[1] ? nz(upward1[1]) + 1 : filt1 < filt1[1] ? 0 : nz(upward1[1])
downward1   := filt1 < filt1[1] ? nz(downward1[1]) + 1 : filt1 > filt1[1] ? 0 : nz(downward1[1])
upward2     := filt2 > filt2[1] ? nz(upward2[1]) + 1 : filt2 < filt2[1] ? 0 : nz(upward2[1])
downward2   := filt2 < filt2[1] ? nz(downward2[1]) + 1 : filt2 > filt2[1] ? 0 : nz(downward2[1])

//RF Target bands
hband1 = filt1 + smrng1
lband1 = filt1 - smrng1
hband2 = filt2 + smrng2
lband2 = filt2 - smrng2

//RF Colors
filtcolor1  = upward1 > 0 ? rf1UpColor : rf1DownColor
filtcolor2  = upward2 > 0 ? rf2UpColor : rf2DownColor
filtplot1   = plot((showRangeFilters ? filt1 : na), color=filtcolor1, linewidth=rf1LineWidth, title="Range Filter #1", display=display.pane)
filtplot2   = plot((showRangeFilters ? filt2 : na), color=filtcolor2, linewidth=rf2LineWidth, title="Range Filter #2", display=display.pane)

// Break Outs
longCond = bool(na)
shortCond = bool(na)
longCond := src1 > filt1 and src1 > src1[1] and upward1 > 0 or 
   src1 > filt1 and src1 < src1[1] and upward1 > 0
shortCond := src1 < filt1 and src1 < src1[1] and downward1 > 0 or 
   src1 < filt1 and src1 > src1[1] and downward1 > 0

CondIni = 0
CondIni := longCond ? 1 : shortCond ? -1 : CondIni[1]
longCondition = longCond and CondIni[1] == -1
shortCondition = shortCond and CondIni[1] == 1

alertcondition(longCondition, title="Range Filter 1 Buy in RF+", message="Range Filter 1 Buy in RF+")
alertcondition(shortCondition, title="Range Filter 1 Sell in RF+", message="Range Filter 1 Sell in RF+")

//=Imported indicator code for divergence detection
//==================================================================================================================================

//UO code
grp_UO  = "UO Settings"
length1 = input.int(7, minval=1, title = "Fast Length", group=grp_UO)
length2 = input.int(14, minval=1, title = "Middle Length", group=grp_UO)
length3 = input.int(28, minval=1, title = "Slow Length", group=grp_UO)
average(bp, tr_, length) => math.sum(bp, length) / math.sum(tr_, length)
high_   = math.max(high, close[1])
low_    = math.min(low, close[1])
bp      = close - low_
tr_     = high_ - low_
avg7    = average(bp, tr_, length1)
avg14   = average(bp, tr_, length2)
avg28   = average(bp, tr_, length3)
ultimate_value = 100 * (4*avg7 + 2*avg14 + avg28)/7
//UO code end

//TSI
grp_TSI     = "TSI settings"
long        = input(title="Long Length", defval=6, group=grp_TSI)
short       = input(title="Short Length", defval=13, group=grp_TSI)
tsisignal   = input(title="Signal Length",  defval=4, group=grp_TSI)
price       = close[0]

double_smooth(src, long, short) =>
	fist_smooth = ta.ema(src, long)
	ta.ema(fist_smooth, short)

pc                  = ta.change(price)
double_smoothed_pc  = double_smooth(pc, long, short)
double_smoothed_abs_pc=double_smooth(math.abs(pc), long, short)
tsi_val             = (double_smoothed_pc / double_smoothed_abs_pc)
tsi_value           = (double_smoothed_pc / double_smoothed_abs_pc)
lagline             = int(ta.ema(tsi_value, tsisignal))

tsi_lagline_value   = (ta.ema(tsi_value, tsisignal))
tsi_bands_crossed_up= (tsi_value > tsi_lagline_value) ? 1 : 0
//TSI code end

// Cumulative delta code
tw      = high - math.max(open, close) 
bw      = math.min(open, close) - low 
body    = math.abs(close - open) 

_rate(cond) =>
    ret = 0.5 * (tw + bw + (cond ? 2 * body : 0)) / (tw + bw + body) 
    ret := nz(ret) == 0 ? 0.5 : ret
    ret
    
deltaup     = volume * _rate(open <= close) 
deltadown   = volume * _rate(open > close)
delta       = close >= open ? deltaup : -deltadown
cdv         = ta.cum(delta)
// End of Cumulative delta code

//=MFI length setting
mfilen = input(14, title="MFI Length", group="MFI settings")

//end of Imported indicator code


//=Trend filter
//==================================================================================================================================
rsiLengthInput  = input.int(150, minval=1, title="RSI Length", group="RSI Trend Filter")
rsiSourceInput  = input.source(close, "Source", group="RSI Trend Filter")
maLengthInput   = input.int(35, title="MA Length", group="RSI Trend Filter")


//=Watermark
//==================================================================================================================================

textVPosition = input.string("top", "", options = ["top", "middle", "bottom"], group = "Watermark text", inline="w0")
showText      = input(true, title="Show Text", group = "Watermark text", inline="w0")
s_title       = input.string("small", "", options = ["small", "normal", "large", "huge", "auto"], group = "Watermark text", inline="w1")
c_title       = input.color(color.new(color.gray, 0), "", group = "Watermark text", inline="w1")
title         = input("RF+", "", group = "Watermark text", inline="w1")
s_subtitle    = input.string("normal", "", options = ["small", "normal", "large", "huge", "auto"], group = "Watermark text", inline="w2")
c_subtitle    = input(color.new(color.gray, 0), "", group = "Watermark text", inline="w2")
subtitle      = input("Divergence Scalping System", "", group = "Watermark text", inline="w2")

symVPosition  = input.string("bottom", "", options = ["top", "middle", "bottom"], group = "Watermark symbol", inline="w3")
showSymText   = input(true, title="Show Symbol", group = "Watermark symbol", inline="w3")
symInfo       = syminfo.ticker  + " | " + timeframe.period + (timeframe.isminutes ? "M" : na)
date          = str.tostring(dayofmonth(time_close)) + "/" + str.tostring(month(time_close)) + "/" + str.tostring(year(time_close))
s_symInfo     = input.string("normal", "", options = ["small", "normal", "large", "huge", "auto"], group = "Watermark symbol", inline="w4")
c_symInfo     = input(color.new(color.gray, 30), "", group = "Watermark symbol", inline="w4")
c_bg          = color.new(color.blue, 100)


//text watermark creation
textWatermark = table.new(textVPosition + "_" + "center", 1, 3)
if showText == true and showWatermark
    table.cell(textWatermark, 0, 0, title, 0, 0, c_title, "center", text_size = s_title, bgcolor = c_bg)
    table.cell(textWatermark, 0, 1, subtitle, 0, 0, c_subtitle, "center", text_size = s_subtitle, bgcolor = c_bg)
//symbol info watermark creation
symWatermark = table.new(symVPosition + "_" + "center", 5, 5)
if showSymText == true and showWatermark
    table.cell(symWatermark, 0, 1, symInfo, 0, 0, c_symInfo, "center", text_size = s_symInfo, bgcolor = c_bg)



//=Styles
//==================================================================================================================================

grp_STYLES          = "Styles"

MTFTableColor       = input.color(color.new(color.white, 100), title="Dashboard Color", group=grp_STYLES)
confirmLineColor    = input.color(color.orange, title="Confirm Line Color", group=grp_STYLES)

reg_div_l_style_    = input.string(defval = "Solid", title = "Regular Divergence Line Style", options = ["Solid", "Dashed", "Dotted"], group=grp_STYLES)
hid_div_l_style_    = input.string(defval = "Dotted", title = "Hdden Divergence Line Style", options = ["Solid", "Dashed", "Dotted"], group=grp_STYLES)
reg_div_l_width     = input.int(defval = 2, title = "Regular Divergence Line Width", minval = 1, maxval = 5, group=grp_STYLES)
hid_div_l_width     = input.int(defval = 2, title = "Hidden Divergence Line Width", minval = 1, maxval = 5, group=grp_STYLES)

pos_reg_div_col     = input(defval = color.new(green, 40), title = "Bullish Regular Divergence", group=grp_STYLES)
neg_reg_div_col     = input(defval = color.new(red, 40), title = "Bearish Regular Divergence", group=grp_STYLES)
pos_hid_div_col     = input(defval = color.new(green, 40), title = "Bullish Hidden Divergence", group=grp_STYLES)
neg_hid_div_col     = input(defval = color.new(red, 40), title = "Bearish Hidden Divergence", group=grp_STYLES)
pos_div_text_col    = input(defval = color.new(color.white, 10), title = "Bullish Divergence Text Color", group=grp_STYLES)
neg_div_text_col    = input(defval = color.new(color.white, 10), title = "Bearish Divergence Text Color", group=grp_STYLES)


//=Pivot point settings
//==================================================================================================================================

grp_PP  = "Pivot point settings"
pp      = input.int(defval = 12, title = "Pivot period", minval = 1, maxval = 50, group=grp_PP)
maxpp   = input.int(defval = 5, title = "Maximum Pivot periods to check for divs", minval = 1, maxval = 100, group=grp_PP)
maxbars = input.int(defval = 100, title = "Maximum Bars to Check", minval = 1, maxval = 200, group=grp_PP)
source  = input.string(defval = "Close", title = "Source for Pivot points", options = ["Close", "High/Low"], group=grp_PP)


prd = pp

//=Divergence logic
//==================================================================================================================================

// set line styles
var reg_div_l_style = reg_div_l_style_ == "Solid" ? line.style_solid : 
                       reg_div_l_style_ == "Dashed" ? line.style_dashed :
                       line.style_dotted
var hid_div_l_style = hid_div_l_style_ == "Solid" ? line.style_solid : 
                       hid_div_l_style_ == "Dashed" ? line.style_dashed :
                       line.style_dotted

// get indicators
uo      = ultimate_value
tsi     = tsi_value
rsi     = ta.rsi(close, 14) // RSI
Mfi     = ta.mfi(hlc3, mfilen) // Money Flow Index
ufo     = (ultimate_value + Mfi) / 2 // UFO
cci     = ta.cci(ccisrc, ccilen) // CCI
stk     = ta.sma(ta.stoch(close, high, low, lengthStoch), smoothD) // Stoch

// keep indicators names and colors in arrays
var indicators_name = array.new_string(14)
var div_colors = array.new_color(4)
if barstate.isfirst
    // names
    array.set(indicators_name, 0, showindis == "Full" ? "UO" : "U")
    array.set(indicators_name, 1, showindis == "Full" ? "TSI" : "T")
    array.set(indicators_name, 2, showindis == "Full" ? "UFO" : "U")
    array.set(indicators_name, 3, showindis == "Full" ? "RSI" : "R")
    array.set(indicators_name, 4, showindis == "Full" ? "MFI" : "M")
    array.set(indicators_name, 5, showindis == "Full" ? "CCI" : "C")
    array.set(indicators_name, 6, showindis == "Full" ? "CDV" : "C")
    array.set(indicators_name, 7, showindis == "Full" ? "Stoch" : "S")
    //colors
    array.set(div_colors, 0, pos_reg_div_col)
    array.set(div_colors, 1, neg_reg_div_col)
    array.set(div_colors, 2, pos_hid_div_col)
    array.set(div_colors, 3, neg_hid_div_col)

// Check if we get new Pivot High Or Pivot Low
float ph = ta.pivothigh((source == "Close" ? close : high), prd, prd)
float pl = ta.pivotlow((source == "Close" ? close : low), prd, prd)
plotshape(ph and showpivot, text = "",  style = shape.circle, color = color.new(color.orange, 70), textcolor = color.new(#FFFFFF, 80), location = location.abovebar, offset = -prd, size=size.tiny)
plotshape(pl and showpivot, text = "",  style = shape.circle, color = color.new(color.orange, 70), textcolor = color.new(#FFFFFF, 80), location = location.belowbar, offset = -prd, size=size.tiny)

// keep values and positions of Pivot Highs/Lows in the arrays
var int maxarraysize = 22
var ph_positions = array.new_int(maxarraysize, 0)
var pl_positions = array.new_int(maxarraysize, 0)
var ph_vals = array.new_float(maxarraysize, 0.)
var pl_vals = array.new_float(maxarraysize, 0.)

// add PHs to the array
if ph
    array.unshift(ph_positions, bar_index)
    array.unshift(ph_vals, ph)
    if array.size(ph_positions) > maxarraysize
        array.pop(ph_positions)
        array.pop(ph_vals)

// add PLs to the array
if pl
    array.unshift(pl_positions, bar_index)
    array.unshift(pl_vals, pl)
    if array.size(pl_positions) > maxarraysize
        array.pop(pl_positions)
        array.pop(pl_vals)

// functions to check Regular Divergences and Hidden Divergences

// function to check positive regular or negative hidden divergence
// cond == 1 => positive_regular, cond == 2=> negative_hidden
positive_regular_positive_hidden_divergence(src, cond)=>
    divlen = 0
    prsc = source == "Close" ? close : low
    // if indicators higher than last value and close price is higher than las close 
    if dontconfirm or src > src[1] or close > close[1]
        startpoint = dontconfirm ? 0 : 1 // don't check last candle
        // we search last 15 PPs
        for x = 0 to maxpp - 1
            len = bar_index - array.get(pl_positions, x) + prd
            // if we reach non valued array element or arrived 101. or previous bars then we don't search more
            if array.get(pl_positions, x) == 0 or len > maxbars
                break
            if len > 5 and 
               ((cond == 1 and src[startpoint] > src[len] and prsc[startpoint] < nz(array.get(pl_vals, x))) or
               (cond == 2 and src[startpoint] < src[len] and prsc[startpoint] > nz(array.get(pl_vals, x))))
                slope1 = (src[startpoint] - src[len]) / (len - startpoint)
                virtual_line1 = src[startpoint] - slope1
                slope2 = (close[startpoint] - close[len]) / (len - startpoint)
                virtual_line2 = close[startpoint] - slope2
                arrived = true
                for y = 1 + startpoint to len - 1
                    if src[y] < virtual_line1 or nz(close[y]) < virtual_line2
                        arrived := false
                        break
                    virtual_line1 := virtual_line1 - slope1
                    virtual_line2 := virtual_line2 - slope2
                
                if arrived
                    divlen := len
                    break
    divlen

// function to check negative regular or positive hidden divergence
// cond == 1 => negative_regular, cond == 2=> positive_hidden
negative_regular_negative_hidden_divergence(src, cond)=>
    divlen = 0
    prsc = source == "Close" ? close : high
    // if indicators higher than last value and close price is higher than las close 
    if dontconfirm or src < src[1] or close < close[1]
        startpoint = dontconfirm ? 0 : 1 // don't check last candle
        // we search last 15 PPs
        for x = 0 to maxpp - 1
            len = bar_index - array.get(ph_positions, x) + prd
            // if we reach non valued array element or arrived 101. or previous bars then we don't search more
            if array.get(ph_positions, x) == 0 or len > maxbars
                break
            if len > 5 and 
               ((cond == 1 and src[startpoint] < src[len] and prsc[startpoint] > nz(array.get(ph_vals, x))) or 
               (cond == 2 and src[startpoint] > src[len] and prsc[startpoint] < nz(array.get(ph_vals, x))))
                slope1 = (src[startpoint] - src[len]) / (len - startpoint)
                virtual_line1 = src[startpoint] - slope1
                slope2 = (close[startpoint] - nz(close[len])) / (len - startpoint)
                virtual_line2 = close[startpoint] - slope2
                arrived = true
                for y = 1 + startpoint to len - 1
                    if src[y] > virtual_line1 or nz(close[y]) > virtual_line2
                        arrived := false
                        break
                    virtual_line1 := virtual_line1 - slope1
                    virtual_line2 := virtual_line2 - slope2
                
                if arrived
                    divlen := len
                    break
    divlen

// calculate 4 types of divergence if enabled in the options and return divergences in an array
calculate_divs(cond, indicator)=>
    divs = array.new_int(4, 0)
    array.set(divs, 0, cond and (searchdiv == "Regular" or searchdiv == "Regular/Hidden") ? positive_regular_positive_hidden_divergence(indicator, 1) : 0)
    array.set(divs, 1, cond and (searchdiv == "Regular" or searchdiv == "Regular/Hidden") ? negative_regular_negative_hidden_divergence(indicator, 1) : 0)
    array.set(divs, 2, cond and (searchdiv == "Hidden" or searchdiv == "Regular/Hidden")  ? positive_regular_positive_hidden_divergence(indicator, 2) : 0)
    array.set(divs, 3, cond and (searchdiv == "Hidden" or searchdiv == "Regular/Hidden")  ? negative_regular_negative_hidden_divergence(indicator, 2) : 0)
    divs

// array to keep all divergences
var all_divergences = array.new_int(44) // 11 indicators * 4 divergence = 44 elements
// set related array elements
array_set_divs(div_pointer, index)=>
    for x = 0 to 3
        array.set(all_divergences, index * 4 + x, array.get(div_pointer, x))

// set divergences array
array_set_divs(calculate_divs(calcuo, uo), 0)
array_set_divs(calculate_divs(calctsi, tsi), 1)
array_set_divs(calculate_divs(calcufo, ufo), 2)
array_set_divs(calculate_divs(calcrsi, rsi), 3)
array_set_divs(calculate_divs(calcmfi, Mfi), 4)
array_set_divs(calculate_divs(calccci, cci), 5)
array_set_divs(calculate_divs(calccdv, cdv), 6)
array_set_divs(calculate_divs(calcstoc, stk), 7)

// check minimum number of divergence, if less than showlimit then delete all divergence
total_div = 0
for x = 0 to array.size(all_divergences) - 1
    total_div := total_div + math.round(math.sign(array.get(all_divergences, x)))

if total_div < showlimit
    array.fill(all_divergences, 0)

// keep line in an array
var pos_div_lines = array.new_line(0)
var pos_div_confirm_lines = array.new_line(0)
var neg_div_lines = array.new_line(0)
var neg_div_confirm_lines = array.new_line(0)
var pos_div_labels = array.new_label(0)
var neg_div_labels = array.new_label(0) 

// remove old lines and labels if showlast option is enabled
delete_old_pos_div_lines()=>
    if array.size(pos_div_lines) > 0    
        for j = 0 to array.size(pos_div_lines) - 1 
            line.delete(array.get(pos_div_lines, j))
        array.clear(pos_div_lines)

delete_old_pos_div_confirm_lines()=>
    if array.size(pos_div_confirm_lines) > 0    
        for j = 0 to array.size(pos_div_confirm_lines) - 1 
            line.delete(array.get(pos_div_confirm_lines, j))
        array.clear(pos_div_confirm_lines)

delete_old_neg_div_lines()=>
    if array.size(neg_div_lines) > 0    
        for j = 0 to array.size(neg_div_lines) - 1 
            line.delete(array.get(neg_div_lines, j))
        array.clear(neg_div_lines)

delete_old_neg_div_confirm_lines()=>
    if array.size(neg_div_confirm_lines) > 0    
        for j = 0 to array.size(neg_div_confirm_lines) - 1 
            line.delete(array.get(neg_div_confirm_lines, j))
        array.clear(neg_div_confirm_lines)

delete_old_pos_div_labels()=>
    if array.size(pos_div_labels) > 0 
        for j = 0 to array.size(pos_div_labels) - 1 
            label.delete(array.get(pos_div_labels, j))
        array.clear(pos_div_labels)

delete_old_neg_div_labels()=>
    if array.size(neg_div_labels) > 0    
        for j = 0 to array.size(neg_div_labels) - 1 
            label.delete(array.get(neg_div_labels, j))
        array.clear(neg_div_labels)

// delete last created lines and labels until we met new PH/PV 
delete_last_pos_div_lines_label(n)=>
    if n > 0 and array.size(pos_div_lines) >= n    
        asz = array.size(pos_div_lines)
        for j = 1 to n
            line.delete(array.get(pos_div_lines, asz - j))
            array.pop(pos_div_lines)
        if array.size(pos_div_labels) > 0  
            label.delete(array.get(pos_div_labels, array.size(pos_div_labels) - 1))
            array.pop(pos_div_labels)

delete_last_neg_div_lines_label(n)=>
    if n > 0 and array.size(neg_div_lines) >= n    
        asz = array.size(neg_div_lines)
        for j = 1 to n
            line.delete(array.get(neg_div_lines, asz - j))
            array.pop(neg_div_lines)
        if array.size(neg_div_labels) > 0  
            label.delete(array.get(neg_div_labels, array.size(neg_div_labels) - 1))
            array.pop(neg_div_labels)
            
// variables for Alerts
pos_reg_div_detected = false
neg_reg_div_detected = false
pos_hid_div_detected = false
neg_hid_div_detected = false

// to remove lines/labels until we met new // PH/PL
var last_pos_div_lines = 0
var last_neg_div_lines = 0
var remove_last_pos_divs = false 
var remove_last_neg_divs = false
if pl
    remove_last_pos_divs := false
    last_pos_div_lines := 0
if ph
    remove_last_neg_divs := false
    last_neg_div_lines := 0

// draw divergences lines and labels
divergence_text_top = ""
divergence_text_bottom = ""
distances = array.new_int(0)
dnumdiv_top = 0
dnumdiv_bottom = 0
top_label_col = color.white
bottom_label_col = color.white
old_pos_divs_can_be_removed = true
old_neg_divs_can_be_removed = true
startpoint = dontconfirm ? 0 : 1 // used for don't confirm option


for x = 0 to 10
    div_type = -1
    for y = 0 to 3
        if array.get(all_divergences, x * 4 + y) > 0 // any divergence?
            div_type := y
            if (y % 2) == 1
                dnumdiv_top := dnumdiv_top + 1
                top_label_col := array.get(div_colors, y)
            if (y % 2) == 0
                dnumdiv_bottom := dnumdiv_bottom + 1
                bottom_label_col := array.get(div_colors, y)
            if not array.includes(distances, array.get(all_divergences, x * 4 + y))  // line not exist ?
                array.push(distances, array.get(all_divergences, x * 4 + y))
                new_line = showlines ? line.new(x1 = bar_index - array.get(all_divergences, x * 4 + y),
                          y1 = (source == "Close" ? close[array.get(all_divergences, x * 4 + y)] : 
                                           (y % 2) == 0 ? low[array.get(all_divergences, x * 4 + y)] : 
                                                          high[array.get(all_divergences, x * 4 + y)]),
                          x2 = bar_index - startpoint,
                          y2 = (source == "Close" ? close[startpoint] : 
                                           (y % 2) == 0 ? low[startpoint] : 
                                                          high[startpoint]),
                          color = array.get(div_colors, y),
                          style = y < 2 ? reg_div_l_style : hid_div_l_style,
                          width = y < 2 ? reg_div_l_width : hid_div_l_width
                          )
                          : na
                new_confirm_line = showlines ? line.new(x1 = bar_index - array.get(all_divergences, x * 4 + y),
                          y1 = (source == "Close" ? close[array.get(all_divergences, x * 4 + y)] : 
                                           (y % 2) == 0 ? low[array.get(all_divergences, x * 4 + y)] : 
                                                          high[array.get(all_divergences, x * 4 + y)]),
                          x2 = bar_index - startpoint + confirmLineLen,
                          y2 =  (source == "Close" ? close[array.get(all_divergences, x * 4 + y)] : 
                                           (y % 2) == 0 ? low[array.get(all_divergences, x * 4 + y)] : 
                                                          high[array.get(all_divergences, x * 4 + y)]),
                          color = y < 2 and showConfirmlines ? confirmLineColor : na,
                          style = line.style_solid,
                          width = 1
                          )
                          : na
                if (y % 2) == 0 
                    if old_pos_divs_can_be_removed
                        old_pos_divs_can_be_removed := false
                        if not showlast and remove_last_pos_divs
                            delete_last_pos_div_lines_label(last_pos_div_lines)
                            last_pos_div_lines := 0
                        if showlast
                            delete_old_pos_div_lines()
                            delete_old_pos_div_confirm_lines()
                    array.push(pos_div_lines, new_line)
                    array.push(pos_div_confirm_lines, new_confirm_line)
                    last_pos_div_lines := last_pos_div_lines + 1
                    remove_last_pos_divs := true
                    
                if (y % 2) == 1 
                    if old_neg_divs_can_be_removed
                        old_neg_divs_can_be_removed := false
                        if not showlast and remove_last_neg_divs
                            delete_last_neg_div_lines_label(last_neg_div_lines)
                            last_neg_div_lines := 0
                        if showlast
                            delete_old_neg_div_lines()
                            delete_old_neg_div_confirm_lines()
                    array.push(neg_div_lines, new_line)
                    array.push(neg_div_confirm_lines, new_confirm_line)
                    last_neg_div_lines := last_neg_div_lines + 1
                    remove_last_neg_divs := true
                    
            // set variables for alerts
            if y == 0 
                pos_reg_div_detected := true
            if y == 1 
                neg_reg_div_detected := true
            if y == 2 
                pos_hid_div_detected := true
            if y == 3 
                neg_hid_div_detected := true
    // get text for labels
    if div_type >= 0 
        divergence_text_top    := divergence_text_top    + ((div_type % 2) == 1 ? (showindis != "Don't Show" ? array.get(indicators_name, x) + "\n" : "") : "")
    if div_type >= 0 
        divergence_text_bottom := divergence_text_bottom + ((div_type % 2) == 0 ? (showindis != "Don't Show" ? array.get(indicators_name, x) + "\n" : "") : "")

// draw labels
if showindis != "Don't Show" or shownum
    if shownum and dnumdiv_top > 0 
        divergence_text_top := divergence_text_top + str.tostring(dnumdiv_top)
    if shownum and dnumdiv_bottom > 0 
        divergence_text_bottom := divergence_text_bottom + str.tostring(dnumdiv_bottom)
    if divergence_text_top != ""
        if showlast
            delete_old_neg_div_labels()
        array.push(neg_div_labels,
                      label.new( x = bar_index, 
                                 y = math.max(high, high[1]), 
                                 text = divergence_text_top,
                                 color = top_label_col,
                                 textcolor = neg_div_text_col,
                                 style = label.style_label_down,
                                 size=size.tiny
                                 ))
                                
                                 
    if divergence_text_bottom != ""
        if showlast
            delete_old_pos_div_labels()
        array.push(pos_div_labels, 
                      label.new( x = bar_index, 
                                 y = math.min(low, low[1]), 
                                 text = divergence_text_bottom,
                                 color = bottom_label_col, 
                                 textcolor = pos_div_text_col,
                                 style = label.style_label_up,
                                 size=size.tiny
                                 ))


alertcondition((pos_reg_div_detected and not pos_reg_div_detected[1]) or (pos_hid_div_detected and not pos_hid_div_detected[1]) or (neg_reg_div_detected and not neg_reg_div_detected[1]) or (neg_hid_div_detected and not neg_hid_div_detected[1]), title='Divergence Detected in RF+', message='Divergence Detected in RF+')


// //MTF Stoch RSI / MTF CCI alert when all overbought or oversold
alertcondition((allMTFStochOB_1 and not allMTFStochOB_1[1]) or (allMTFStochOS_1 and not allMTFStochOS_1[1]) or (allMTFCCIOB and not allMTFCCIOB[1]) or (allMTFCCIOS and not allMTFCCIOS[1]), title="MTF OB/OS on RF+", message="MTF OB/OS on RF+")


//=Confluences are met signals // see allconfluencesmet setting at top of file for details in tooltip
//==================================================================================================================================
var recentBarsWithPosDivConfluences = false
var recentBarsWithNegDivConfluences = false

recentBarsWithMTFOB = 0
for obi = 0 to 4
    if allMTFStochOB_1[obi] or allMTFCCIOB[obi]
        recentBarsWithMTFOB := recentBarsWithMTFOB + 1
        break

recentBarsWithMTFOS = 0
for osi = 0 to 4
    if allMTFStochOS_1[osi] or allMTFCCIOS[osi]
        recentBarsWithMTFOS := recentBarsWithMTFOS + 1
        break

noWickBull =  (open == low)
noWickBear =  (open == high)

pullbackWithBullishDivCondition = showpullbackdivergence and (upward1 and upward2) and (pos_hid_div_detected or pos_reg_div_detected) and (close < filt1 and close < filt2) ? 1.0 : 0.0
pullbackWithBearishDivCondition = showpullbackdivergence and (downward1 and downward2) and (neg_hid_div_detected or neg_reg_div_detected) and (close > filt1 and close > filt2) ? 1.0 : 0.0

//Pullbacks - trend continuation confleunce signal
plotchar(pullbackWithBullishDivCondition, char="◡", color=green, title="Pullback with Bullish div", location=location.belowbar, size=size.tiny, offset=0)
plotchar(pullbackWithBearishDivCondition, char="◠", color=red, title="Pullback with Bearish div", location=location.abovebar, size=size.tiny, offset=0)

alertcondition(pullbackWithBullishDivCondition or pullbackWithBearishDivCondition, title="Pullback with divergence in RF+", message="Pullback with divergence in  RF+")


// =Dashboard table
//==================================================================================================================================

//Trend filter
up      = ta.rma(math.max(ta.change(rsiSourceInput), 0), rsiLengthInput)
down    = ta.rma(-math.min(ta.change(rsiSourceInput), 0), rsiLengthInput)
trsi    = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
trsiMA  = ta.sma(rsi, maLengthInput)

//Stats
rangeFilterTrendingUp   = upward1 and upward2 ? true : false
rangeFilterTrendingDown = downward1 and downward2 ? true : false
ema144TrendingUp        = close > ta.ema(close, 144) ? true : false
priceAbove21SMA         = close > ta.sma(close, 21) ? true : false
tsiBandsCrossingUp      = tsi_bands_crossed_up ? true : false
mfiAbove50              = Mfi > 50 ? true : false
uoAbove50               = ultimate_value > 50 ? true : false
tsiAbove0               = tsi_value > 0 ? true : false


//Entry criteria
shortPullbackEntryCriteriaMet() =>
    showpullbackdivergence and (downward1 and downward2) and (neg_hid_div_detected or neg_reg_div_detected) and (close > filt1 and close > filt2) ? true : false

longPullbackEntryCriteriaMet() =>
    showpullbackdivergence and (upward1 and upward2) and (pos_hid_div_detected or pos_reg_div_detected) and (close < filt1 and close < filt2) ? true : false

shortDivEntryCriteriaMet() =>
    showFilteredDivEntryCriteria and (neg_hid_div_detected or neg_reg_div_detected) and (close < filt1 and close < filt2) and not priceAbove21SMA and trsi < trsiMA ? true : false

longDivEntryCriteriaMet() =>
    showFilteredDivEntryCriteria and (pos_hid_div_detected or pos_reg_div_detected) and (close > filt1 and close > filt2) and priceAbove21SMA and trsi > trsiMA ? true : false


recentBarsWithPosDiv = 0
for pdi = 0 to 4
    if pos_hid_div_detected[pdi] or pos_reg_div_detected[pdi]
        recentBarsWithPosDiv := recentBarsWithPosDiv + 1
        break

recentBarsWithNegDiv = 0
for ndi = 0 to 4
    if neg_hid_div_detected[ndi] or neg_reg_div_detected[ndi]
        recentBarsWithNegDiv := recentBarsWithNegDiv + 1
        break


plotchar(shortDivEntryCriteriaMet(), char="🢓", color=color.orange, title="short entry", location=location.abovebar, size=size.small, offset=0)
plotchar(longDivEntryCriteriaMet(), char="🢑", color=color.orange, title="long entry", location=location.belowbar, size=size.small, offset=0)
alertcondition(shortDivEntryCriteriaMet() or longDivEntryCriteriaMet(), title="Div filtered by 21sma & RSI MA in RF+", message="Div filtered by 21sma & RSI MA in RF+")

plotshape(MTFOBOSDivSignal and recentBarsWithMTFOB and recentBarsWithNegDiv and not (recentBarsWithMTFOB[1] and recentBarsWithNegDiv[1]), text = "",  style = shape.labeldown, color = color.new(red, 70), textcolor = color.new(#FFFFFF, 50), location = location.abovebar, size=size.small)
plotshape(MTFOBOSDivSignal and recentBarsWithMTFOS and recentBarsWithPosDiv and not (recentBarsWithMTFOS[1] and recentBarsWithPosDiv[1]), text = "",  style = shape.labelup, color = color.new(green, 70), textcolor = color.new(#FFFFFF, 50), location = location.belowbar, size=size.small)
alertcondition(MTFOBOSDivSignal and ((recentBarsWithMTFOB and recentBarsWithNegDiv and not (recentBarsWithMTFOB[1] and recentBarsWithNegDiv[1])) or (recentBarsWithMTFOS and recentBarsWithPosDiv) and not (recentBarsWithMTFOS[1] and recentBarsWithPosDiv[1])), title="MTF OB/OS + Div on RF+", message="MTF OB/OS + Div on RF+")


_position = switch dashboardPosition
    "Top Left" => position.top_left
    "Top Right" => position.top_right
    "Bottom Left" => position.bottom_left
    => position.bottom_right

_size = switch dashboardSize
    "Mobile" => size.small
    "Desktop" => size.normal

// We use `var` to only initialize the table on the first bar.
var table dashboard = table.new(_position, 4, 4, bgcolor = MTFTableColor, frame_width = 0, frame_color = na)

LabelColor = color.new(color.white, 70)
ValueColor = color.new(color.white, 20)

_CCIlabelColor(val, ob, os) =>
    val > ob ? overboughtColorCCI : (val < os ? oversoldColorCCI : ValueColor)

_SRSIlabelColor(val, ob, os) =>
    val > ob ? overboughtColor_1 : (val < os ? oversoldColor_1 : ValueColor)

// We call functions like `ta.atr()` outside the `if` block so it executes on each bar.
if barstate.islast and showDashboard
    // We only populate the table on the last bar.
    
    table.cell(dashboard, 0, 0, text="CCI", text_color=LabelColor, text_halign=text.align_left, text_size=size.small, width=2)
    table.cell(dashboard, 0, 1, text=CCITF_1+"m", text_color=LabelColor, text_halign=text.align_left, text_size=size.tiny)
    table.cell(dashboard, 0, 2, text=CCITF_2+"m", text_color=LabelColor, text_halign=text.align_left, text_size=size.tiny)
    table.cell(dashboard, 0, 3, text=CCITF_3+"m", text_color=LabelColor, text_halign=text.align_left, text_size=size.tiny)
    table.cell(dashboard, 1, 0, text="", width=3, text_color=LabelColor, text_halign=text.align_left, text_size=size.small)
    table.cell(dashboard, 1, 1, text=str.tostring(math.round(CCIMTF1, 0)) , text_color=_CCIlabelColor(CCIMTF1, CCIMTF_OBTHRESH_1, CCIMTF_OSTHRESH_1), text_halign=text.align_right, text_size=_size)
    table.cell(dashboard, 1, 2, text=str.tostring(math.round(CCIMTF2, 0)) , text_color=_CCIlabelColor(CCIMTF2, CCIMTF_OBTHRESH_2, CCIMTF_OSTHRESH_2), text_halign=text.align_right, text_size=_size)
    table.cell(dashboard, 1, 3, text=str.tostring(math.round(CCIMTF3, 0)), text_color=_CCIlabelColor(CCIMTF3, CCIMTF_OBTHRESH_3, CCIMTF_OSTHRESH_3), text_halign=text.align_right, text_size=_size)

    table.cell(dashboard, 2, 0, text="STOCH", text_color=LabelColor, text_halign=text.align_left, text_size=size.small, width=2)
    table.cell(dashboard, 2, 1, text=TF_1+"m", text_color=LabelColor, text_halign=text.align_left, text_size=size.tiny)
    table.cell(dashboard, 2, 2, text=TF_2+"m", text_color=LabelColor, text_halign=text.align_left, text_size=size.tiny)
    table.cell(dashboard, 2, 3, text=TF_3+"m", text_color=LabelColor, text_halign=text.align_left, text_size=size.tiny)
    table.cell(dashboard, 3, 0, text="", width=3, text_color=LabelColor, text_halign=text.align_left, text_size=size.small)
    table.cell(dashboard, 3, 1, text=str.tostring(math.round(MTF1, 0)) , text_color=_SRSIlabelColor(MTF1, MTF_OBTHRESH_1, MTF_OSTHRESH_1), text_halign=text.align_right, text_size=_size)
    table.cell(dashboard, 3, 2, text=str.tostring(math.round(MTF2, 0)) , text_color=_SRSIlabelColor(MTF2, MTF_OBTHRESH_2, MTF_OSTHRESH_2), text_halign=text.align_right, text_size=_size)
    table.cell(dashboard, 3, 3, text=str.tostring(math.round(MTF3, 0)) , text_color=_SRSIlabelColor(MTF3, MTF_OBTHRESH_3, MTF_OSTHRESH_3), text_halign=text.align_right, text_size=_size)


plot(bar_index, title="bar index", display=display.data_window)


// grp_STRAT   = "Strategy settings"
// timeInput   = input.time(timestamp("1 Nov 2022 00:00 +0000"), title="Start date", group=grp_STRAT)
// tpInPips    = input.int(220, title="TP (in pips)", group=grp_STRAT)
// slInPips    = input.int(20, title="SL (in pips)", group=grp_STRAT)

// timePeriod  = time >= timeInput

// longSignal = MTFOBOSDivSignal and (recentBarsWithMTFOS and recentBarsWithPosDiv) and tsi_bands_crossed_up and longCondition
// shortSignal = MTFOBOSDivSignal and (recentBarsWithMTFOB and recentBarsWithNegDiv) and not tsi_bands_crossed_up and shortCondition

// // longSignal = ta.crossunder(vwapValue, close)
// // shortSignal = ta.crossover(vwapValue, close)

// if(longSignal and timePeriod)
//     strategy.entry("Long", strategy.long)
//     strategy.exit("Exit long", "Long", loss=slInPips, profit=tpInPips)
// if(shortSignal and timePeriod)
//     strategy.entry("Short", strategy.short)
//     strategy.exit("Exit short", "Short", loss=slInPips, profit=tpInPips)