Bayesian BBSMA + nQQE Oscillator + Bank funds (whales detector)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//
// Three trend indicators in one. Fork of Gunslinger2005 indicator, with a fix to display the nQQE oscillator correctly and clearly, and converted to pinescript v5 (allowing to set a different timeframe and gaps).
// How to use: Essentially, nQQE is a long term trend indicator which is more adequate in daily or weekly timeframe to indicate the current market cycle. Banker Fund seems better suited to indicate current local trend, although it is sensitive to relief rallies. Bayesian BBSMA is an awesome tool to visualize the buildup in bullish/bearish sentiment, and when it is more likely to get released, however it is unreliable, so it needs to be combined with other indicators.
//
// Original indicators list:
// Bayesian BBSMA: https://www.tradingview.com/v/8lXcviYm/
// nQQE: https://www.tradingview.com/v/CfCuUCeE/
// L3 Banker Fund Flow Trend: https://www.tradingview.com/v/791WkWcm/
// Originally mixed together by Gunslinger2005: https://www.tradingview.com/script/Gan1g6EY-The-Bayesian-Q-Oscillator/
// Fixed nQQE plotting by Tartigradia

//@version=5
indicator('Bayesian BBSMA + nQQE Oscillator + Bank funds (whales detector)', shorttitle='Bayesian/nQQE/BankFunds', precision=4, timeframe="", timeframe_gaps=true)

rescale(_src, _oldMin, _oldMax, _newMin, _newMax) =>
    // Rescales series with known min/max.
    // _src            : series to rescale.
    // _oldMin, _oldMax: min/max values of series to rescale.
    // _newMin, _newMin: min/max values of rescaled series.
    _newMin + (_newMax - _newMin) * (_src - _oldMin) / math.max(_oldMax - _oldMin, 10e-10)


//#################### Bayesian BBSMA

bbSmaPeriod = input.int(20, title='BB SMA Period', group='═════ Bayesian BBSMA settings ═════')
bbStdDevMult = input.float(2.5, title='BB Standard Deviation', maxval=50.0)

bbBasis = ta.sma(close, bbSmaPeriod)
bbStdDev = bbStdDevMult * ta.stdev(close, bbSmaPeriod)

bbUpper = bbBasis + bbStdDev
bbLower = bbBasis - bbStdDev

// AO
aoFast = input(5, 'AO Fast EMA Length')
aoSlow = input(34, 'AO Slow EMA Length')
ao = ta.sma(hl2, aoFast) - ta.sma(hl2, aoSlow)
colorAo = ta.change(ao) > 0 ? color.green : color.red

// AC
acFast = input(5, 'AC Fast SMA Length')
acSlow = input(34, 'AC Slow SMA Length')
xSMA1_hl2 = ta.sma(hl2, acFast)
xSMA2_hl2 = ta.sma(hl2, acSlow)
xSMA1_SMA2 = xSMA1_hl2 - xSMA2_hl2
xSMA_hl2 = ta.sma(xSMA1_SMA2, acFast)
ac = xSMA1_SMA2 - xSMA_hl2
cClr = ac > ac[1] ? color.blue : color.red

acAo = (ac + ao) / 2

maAcAoPeriod = input(13, 'AC AO MA Period')
showMaAcAo = input(false, 'Show AC AO MA?')
maAcAo = ta.vwma(acAo, maAcAoPeriod)

// Combine AC & AO
acIsBlue = ac > ac[1]
acIsRed = not(ac > ac[1])
aoIsGreen = ta.change(ao) > 0
aoIsRed = not(ta.change(ao) > 0)
acAoIsBullish = acIsBlue and aoIsGreen
acAoIsBearish = acIsRed and acIsRed
acAoColorIndex = acAoIsBullish ? 1 : acAoIsBearish ? -1 : 0

// Alligator
smma(src, length) =>
    smma = 0.0
    smma := na(smma[1]) ? ta.sma(src, length) : (smma[1] * (length - 1) + src) / length
    smma
lipsLength = input(title='🐲 Lips Length', defval=5)
teethLength = input(title='🐲 Teeth Length', defval=8)
jawLength = input(title='🐲 Jaw Length', defval=13)
lipsOffset = input(title='🐲 Lips Offset', defval=3)
teethOffset = input(title='🐲 Teeth Offset', defval=5)
jawOffset = input(title='🐲 Jaw Offset', defval=8)
lips = smma(hl2, lipsLength)
teeth = smma(hl2, teethLength)
jaw = smma(hl2, jawLength)

// SMA
smaPeriod = input(20, title='SMA Period')
smaValues = ta.sma(close, smaPeriod)


// Bayesian Theorem Starts
bayesPeriod = input(20, title='Bayesian Lookback Period')

// Next candles are breaking Down
probBbUpperUpSeq = close > bbUpper ? 1 : 0
probBbUpperUp = math.sum(probBbUpperUpSeq, bayesPeriod) / bayesPeriod
probBbUpperDownSeq = close < bbUpper ? 1 : 0
probBbUpperDown = math.sum(probBbUpperDownSeq, bayesPeriod) / bayesPeriod

probUpBbUpper = probBbUpperUp / (probBbUpperUp + probBbUpperDown)

probBbBasisUpSeq = close > bbBasis ? 1 : 0
probBbBasisUp = math.sum(probBbBasisUpSeq, bayesPeriod) / bayesPeriod
probBbBasisDownSeq = close < bbBasis ? 1 : 0
probBbBasisDown = math.sum(probBbBasisDownSeq, bayesPeriod) / bayesPeriod

probUpBbBasis = probBbBasisUp / (probBbBasisUp + probBbBasisDown)

probSmaUpSeq = close > smaValues ? 1 : 0
probSmaUp = math.sum(probSmaUpSeq, bayesPeriod) / bayesPeriod
probSmaDownSeq = close < smaValues ? 1 : 0
probSmaDown = math.sum(probSmaDownSeq, bayesPeriod) / bayesPeriod

probUpSma = probSmaUp / (probSmaUp + probSmaDown)

sigmaProbsDown = nz(probUpBbUpper * probUpBbBasis * probUpSma / probUpBbUpper * probUpBbBasis * probUpSma + (1 - probUpBbUpper) * (1 - probUpBbBasis) * (1 - probUpSma))

// Next candles are breaking Up
probDownBbUpper = probBbUpperDown / (probBbUpperDown + probBbUpperUp)
probDownBbBasis = probBbBasisDown / (probBbBasisDown + probBbBasisUp)
probDownSma = probSmaDown / (probSmaDown + probSmaUp)

sigmaProbsUp = nz(probDownBbUpper * probDownBbBasis * probDownSma / probDownBbUpper * probDownBbBasis * probDownSma + (1 - probDownBbUpper) * (1 - probDownBbBasis) * (1 - probDownSma))

showNextCandleDown = input(true, title='Plot Next Candles Breaking Down?')
plot(showNextCandleDown ? sigmaProbsDown * 100 : na, title='Next Candle Breaking Down Probs', style=plot.style_area, color=color.new(color.red, 60), linewidth=2)

showNextCandleUp = input(true, title='Plot Next Candles Breaking Up?')
plot(showNextCandleUp ? sigmaProbsUp * 100 : na, title='Next Candle Breaking Up Probs', style=plot.style_area, color=color.new(color.green, 60), linewidth=2)

probPrime = nz(sigmaProbsDown * sigmaProbsUp / sigmaProbsDown * sigmaProbsUp + (1 - sigmaProbsDown) * (1 - sigmaProbsUp))

showPrime = input(true, title='Plot Prime Probability?')
plot(showPrime ? probPrime * 100 : na, title='Prime Probability', style=plot.style_area, color=color.new(color.blue, 60), linewidth=2)

lowerThreshold = input(15.0, title='Lower Threshold')

sideways = probPrime < lowerThreshold / 100 and sigmaProbsUp < lowerThreshold / 100 and sigmaProbsDown < lowerThreshold / 100

longUsingProbPrime = probPrime > lowerThreshold / 100 and probPrime[1] == 0
longUsingSigmaProbsUp = sigmaProbsUp < 1 and sigmaProbsUp[1] == 1

shortUsingProbPrime = probPrime == 0 and probPrime[1] > lowerThreshold / 100
shortUsingSigmaProbsDown = sigmaProbsDown < 1 and sigmaProbsDown[1] == 1

milanIsRed = acAoColorIndex == -1
milanIsGreen = acAoColorIndex == 1
pricesAreMovingAwayUpFromAlligator = close > jaw and open > jaw
pricesAreMovingAwayDownFromAlligator = close < jaw and open < jaw

useBWConfirmation = input(false, title='Use Bill Williams indicators for confirmation?')

bwConfirmationUp = useBWConfirmation ? milanIsGreen and pricesAreMovingAwayUpFromAlligator : true
bwConfirmationDown = useBWConfirmation ? milanIsRed and pricesAreMovingAwayDownFromAlligator : true

longSignal = bwConfirmationUp and (longUsingProbPrime or longUsingSigmaProbsUp)
shortSignal = bwConfirmationDown and (shortUsingProbPrime or shortUsingSigmaProbsDown)

barcolor(longSignal ? color.lime : na, title='Long Bars')
barcolor(shortSignal ? color.maroon : na, title='Short Bars')

//hzl3 = hline(lowerThreshold, color=#333333, linestyle=hline.style_solid)
//hzl4 = hline(0, color=#333333, linestyle=hline.style_solid)
//fill(hzl3, hzl4, title="Lower Threshold", color=sideways ? color.gray : color.maroon, transp=70)

alertcondition(longSignal, title='Long!', message='Bayesian BBSMA - LONG - {{exchange}}:{{ticker}} at {{close}}')
alertcondition(shortSignal, title='Short!', message='Bayesian BBSMA - SHORT - {{exchange}}:{{ticker}} at {{close}}')


//#################### nQQE

src = input(close)
length = input.int(14, 'RSI Length', minval=1, group='═════ nQQE settings ═════')
SSF = input.int(5, 'SF RSI SMoothing Factor', minval=1)
showsignals = input(title='Show Crossing Signals?', defval=false)
RSII = ta.ema(ta.rsi(src, length), SSF)
TR = math.abs(RSII - RSII[1])
wwalpha = 1 / length
WWMA = 0.0
WWMA := wwalpha * TR + (1 - wwalpha) * nz(WWMA[1])
ATRRSI = 0.0
ATRRSI := wwalpha * WWMA + (1 - wwalpha) * nz(ATRRSI[1])
QQEF = ta.ema(ta.rsi(src, length), SSF)
QUP = QQEF + ATRRSI * 4.236
QDN = QQEF - ATRRSI * 4.236
QQES = 0.0
QQES := QUP < nz(QQES[1]) ? QUP : QQEF > nz(QQES[1]) and QQEF[1] < nz(QQES[1]) ? QDN : QDN > nz(QQES[1]) ? QDN : QQEF < nz(QQES[1]) and QQEF[1] > nz(QQES[1]) ? QUP : nz(QQES[1])
Colorh = QQEF > 60 ? color.lime : QQEF < 40 ? color.red : #E8E81A
QQF = plot(QQEF, 'nQQE FAST', color=color.new(color.maroon, 0), linewidth=2, display=display.none)
plot(QQEF, color=color.new(Colorh, 30), linewidth=2, style=plot.style_area, histbase=50)
QQS = plot(QQES, 'nQQE SLOW', color=color.new(color.white, 0), linewidth=2, display=display.none)
hline(60, color=color.gray, linestyle=hline.style_dashed)
hline(40, color=color.gray, linestyle=hline.style_dashed)
buySignalr = ta.crossover(QQEF, QQES)
plotshape(buySignalr and showsignals ? QQES * 0.995 : na, title='Buy', text='Buy', location=location.absolute, style=shape.labelup, size=size.tiny, color=color.new(color.black, 50), textcolor=color.new(color.white, 50))
sellSignallr = ta.crossunder(QQEF, QQES)
plotshape(sellSignallr and showsignals ? QQES * 1.005 : na, title='Sell', text='Sell', location=location.absolute, style=shape.labeldown, size=size.tiny, color=color.new(color.black, 50), textcolor=color.new(color.white, 50))
alertcondition(ta.cross(QQEF, QQES), title='Cross Alert', message='QQE Crossing Signal!')
alertcondition(ta.crossover(QQEF, QQES), title='Crossover Alarm', message='QQE BUY SIGNAL!')
alertcondition(ta.crossunder(QQEF, QQES), title='Crossunder Alarm', message='QQE SELL SIGNAL!')
alertcondition(ta.crossover(QQEF, 50), title='Cross 0 Up Alert', message='QQE FAST Crossing 0 UP!')
alertcondition(ta.crossunder(QQEF, 50), title='Cross 0 Down Alert', message='QQE FAST Crossing 0 DOWN!')
alertcondition(ta.crossover(QQEF, 60), title='Cross 10 Up Alert', message='QQE Above 10 UPTREND SIGNAL!')
alertcondition(ta.crossunder(QQEF, 40), title='Cross -10 Down Alert', message='QQE Below -10 DOWNTREND SIGNAL!')
alertcondition(ta.crossunder(QQEF, 60) or ta.crossover(QQEF, 40), title='SIDEWAYS', message='QQE Entering Sideways Market!')


//#################### L3 Banker

//functions
xrf(values, length) =>
    r_val = float(na)
    if length >= 1
        for i = 0 to length by 1
            if na(r_val) or not na(values[i])
                r_val := values[i]
                r_val
    r_val

xsa(src, len, wei) =>
    sumf = 0.0
    ma = 0.0
    out = 0.0
    sumf := nz(sumf[1]) - nz(src[len]) + src
    ma := na(src[len]) ? na : sumf / len
    out := na(out[1]) ? ma : (src * wei + out[1] * (len - wei)) / len
    out

//set up a simple model of banker fund flow trend	
fundtrend = (3 * xsa((close - ta.lowest(low, 27)) / (ta.highest(high, 27) - ta.lowest(low, 27)) * 100, 5, 1) - 2 * xsa(xsa((close - ta.lowest(low, 27)) / (ta.highest(high, 27) - ta.lowest(low, 27)) * 100, 5, 1), 3, 1) - 50) * 1.032 + 50
//define typical price for banker fund
typ = (2 * close + high + low + open) / 5
//lowest low with mid term fib # 34
lol = ta.lowest(low, 34)
//highest high with mid term fib # 34
hoh = ta.highest(high, 34)
//define banker fund flow bull bear line
bullbearline = ta.ema((typ - lol) / (hoh - lol) * 100, 13)
//define banker entry signal
bankerentry = ta.crossover(fundtrend, bullbearline) and bullbearline < 25

//banker fund entry with yellow candle
plotcandle(0, 50, 0, 50, color=bankerentry ? color.new(color.yellow, 0) : na, bordercolor=color.new(color.black, 100))

//banker increase position with green candle
plotcandle(fundtrend, bullbearline, fundtrend, bullbearline, color=fundtrend > bullbearline ? color.new(color.green, 0) : na, bordercolor=color.new(color.black, 100))

//banker decrease position with white candle
plotcandle(fundtrend, bullbearline, fundtrend, bullbearline, color=fundtrend < xrf(fundtrend * 0.95, 1) ? color.new(color.white, 0) : na, bordercolor=color.new(color.black, 100))

//banker fund exit/quit with red candle
plotcandle(fundtrend, bullbearline, fundtrend, bullbearline, color=fundtrend < bullbearline ? color.new(color.red, 0) : na, bordercolor=color.new(color.black, 100))

//banker fund Weak rebound with blue candle
plotcandle(fundtrend, bullbearline, fundtrend, bullbearline, color=fundtrend < bullbearline and fundtrend > xrf(fundtrend * 0.95, 1) ? color.new(color.blue, 0) : na, bordercolor=color.new(color.black, 100))

//overbought and oversold threshold lines
//h1 = hline(80,color=color.red, linestyle=hline.style_dotted)
//h2 = hline(20, color=color.yellow, linestyle=hline.style_dotted)
//h3 = hline(10,color=color.lime, linestyle=hline.style_dotted)
//h4 = hline(90, color=color.fuchsia, linestyle=hline.style_dotted)
//fill(h2,h3,color=color.yellow,transp=70)
//fill(h1,h4,color=color.fuchsia,transp=70)

alertcondition(bankerentry, title='Alert on Yellow Candle', message='Yellow Candle!')
alertcondition(fundtrend > bullbearline, title='Alert on Green Candle', message='Green Candle!')
alertcondition(fundtrend < xrf(fundtrend * 0.95, 1), title='Alert on White Candle', message='White Candle!')
alertcondition(fundtrend < bullbearline, title='Alert on Red Candle', message='Red Candle!')
alertcondition(fundtrend < bullbearline and fundtrend > xrf(fundtrend * 0.95, 1), title='Alert on Blue Candle', message='Blue Candle!')

