Kase Peak Oscillator w/ Divergences [Loxx]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © loxx

//@version=5
indicator("Kase Peak Oscillator w/ Divergences [Loxx]",
     shorttitle="KPOD [Loxx]",
     overlay = false, 
     timeframe="", 
     timeframe_gaps = true)


greencolor = #2DD204
redcolor = #D2042D

lightgreencolor = #96E881 
lightredcolor =  #DF4F6C

darkGreenColor =  #1B7E02 
darkRedColor = #93021F

kpoDeviations = input.float(2.0, "Deviations", group= "Basic Settings") // Kase peak oscillator deviations
kpoShortCycle = input.int(8, "Short Cycle Period", group= "Basic Settings") // Kase peak oscillator short cycle
kpoLongCycle = input.int(65, "Long Cycle Period", group= "Basic Settings") // Kase peak oscillator long cycle
kpoSensitivity = input.float(40, "Sensitivity", group= "Basic Settings") // Kase peak oscillator sensitivity
allPeaksMode = input.bool(true, "Show all peaks?", group= "Basic Settings") // Show all peaks?

colorbars = input.bool(false, "Color bars?", group= "UI Options")
mutebars = input.bool(false, "Mute bars?", group= "UI Options")

lbR = input(title="Pivot Lookback Right", defval=5, group = "Divergences Settings")
lbL = input(title="Pivot Lookback Left", defval=5, group = "Divergences Settings")
rangeUpper = input(title="Max of Lookback Range", defval=60, group = "Divergences Settings")
rangeLower = input(title="Min of Lookback Range", defval=5, group = "Divergences Settings")
plotBull = input(title="Plot Bullish", defval=true, group = "Divergences Settings")
plotHiddenBull = input(title="Plot Hidden Bullish", defval=false, group = "Divergences Settings")
plotBear = input(title="Plot Bearish", defval=true, group = "Divergences Settings")
plotHiddenBear = input(title="Plot Hidden Bearish", defval=false, group = "Divergences Settings")
bearColor = darkRedColor
bullColor = darkGreenColor
hiddenBullColor = color.new(darkGreenColor, 80)
hiddenBearColor = color.new(darkRedColor, 80)
textColor = color.white
noneColor = color.new(color.white, 100)

x1 = 0.
xs = 0.

x1 := nz(x1[1])
xs := nz(xs[1])

ccLog = math.log(close / nz(close[1]))
ccDev = ta.stdev(ccLog, 9)
avg = ta.sma(ccDev, 30)


max1 = 0.
maxs = 0.

for k = kpoShortCycle to kpoLongCycle - 1
    max1 := math.max(math.log(high / nz(low[k])) / math.sqrt(k), max1)
    maxs := math.max(math.log(nz(high[k]) / low) / math.sqrt(k), maxs)
    
x1 := max1 / avg
xs := maxs / avg

xp = kpoSensitivity * (ta.sma(x1, 3) - ta.sma(xs, 3))
xpAbs = math.abs(xp)

kppBuffer  = 0.
kpoBuffer = xp
kphBuffer = xp

tmpVal = ta.sma(xpAbs, 50) + kpoDeviations * (ta.stdev(xpAbs, 50))
maxVal = math.max(90.0, tmpVal)
minVal = math.min(90.0, tmpVal)

kpdBuffer = 0.
kpmBuffer = 0.

if kpoBuffer > 0.
    kpdBuffer := maxVal
    kpmBuffer := minVal
else 
    kpdBuffer := -maxVal
    kpmBuffer := -minVal

if (not allPeaksMode)
    if (nz(kpoBuffer[1]) > 0 and nz(kpoBuffer[1]) > kpoBuffer and nz(kpoBuffer[1]) >= nz(kpoBuffer[2]) and nz(kpoBuffer[1]) >= maxVal) 
        kppBuffer := kpoBuffer
    if (nz(kpoBuffer[1]) < 0 and nz(kpoBuffer[1]) < kpoBuffer and nz(kpoBuffer[1]) <= nz(kpoBuffer[2]) and nz(kpoBuffer[1]) <= -maxVal) 
        kppBuffer := kpoBuffer
else 
    if (nz(kpoBuffer[1]) > 0 and nz(kpoBuffer[1]) > kpoBuffer and nz(kpoBuffer[1]) >= nz(kpoBuffer[2])) 
        kppBuffer := kpoBuffer
    if (nz(kpoBuffer[1]) < 0 and nz(kpoBuffer[1]) < kpoBuffer and nz(kpoBuffer[1]) <= nz(kpoBuffer[2])) 
        kppBuffer := kpoBuffer
        
plot(kpoBuffer, "Kase Peak Oscillator", color = color.gray)
plot(kphBuffer, "Kase Peak Oscillator Histogram", color = color.gray, style=plot.style_histogram)
plot(kpdBuffer, "Max Peak Value", color = color.yellow, linewidth = 1) //Blue Kpeak-Min line is a maximum of two standard deviations of the PeakOscillator value.
plot(kpmBuffer, "Min Peak Value", color = color.white, linewidth = 1) //Red PeakOut line is a minimum of two standard deviations of the PeakOscillator value

colorout = kppBuffer ? kppBuffer > 0 ? redcolor : greencolor : mutebars ? color.gray : na

plot(kppBuffer, "Market Extreme", color = kppBuffer ? colorout : na, style = plot.style_histogram, linewidth = 3)

barcolor(colorbars ? colorout : na)

osc = kpoBuffer

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=textColor
	 )

//------------------------------------------------------------------------------
// 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=textColor
	 )

//------------------------------------------------------------------------------
// 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
	 )
	 
	 
goLong = kppBuffer < 0 
goShort = kppBuffer > 0 


alertcondition(goLong, title="Long", message="Kase Peak Oscillator w/ Divergences [Loxx]: Long\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(goShort, title="Short", message="Kase Peak Oscillator w/ Divergences [Loxx]: Short\nSymbol: {{ticker}}\nPrice: {{close}}")

alertcondition(hiddenBearCond, title="Hidden Bear Divergence", message="Kase Peak Oscillator w/ Divergences [Loxx]: Hidden Bear Divergence\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(bearCond, title="Regular Bear Divergence", message="Kase Peak Oscillator w/ Divergences [Loxx]: Regular Bear Divergence\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(hiddenBullCond, title="Hidden Bull Divergence", message="Kase Peak Oscillator w/ Divergences [Loxx]: Hidden Bull Divergence\nSymbol: {{ticker}}\nPrice: {{close}}")
alertcondition(bullCond, title="Regular Bull Divergence", message="Kase Peak Oscillator w/ Divergences [Loxx]: Regular Bull Divergence\nSymbol: {{ticker}}\nPrice: {{close}}")


