Klinger Volume Divergence Indicator
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © seslly

//@version=4
// Modified version of the divergence indicator by seslly 

study(title="Klinger Volume Divergence Indicator", shorttitle="Divergence Indicator", format=format.volume, resolution="")
lbR = input(title="Pivot Lookback Right", defval=5)
lbL = input(title="Pivot Lookback Left", defval=5)
rangeUpper = input(title="Max of Lookback Range", defval=60)
rangeLower = input(title="Min of Lookback Range", defval=5)
plotBull = input(title="Plot Bullish", defval=true)
plotHiddenBull = input(title="Plot Hidden Bullish", defval=false)
plotBear = input(title="Plot Bearish", defval=true)
plotHiddenBear = input(title="Plot Hidden Bearish", defval=false)
bearColor = color.red
bullColor = color.green
hiddenBullColor = color.new(color.green, 80)
hiddenBearColor = color.new(color.red, 80)
textColor = color.white
noneColor = color.new(color.white, 100)
sv = change(hlc3) >= 0 ? volume : -volume
kvo = ema(sv, 34) - ema(sv, 55)
sig = ema(kvo, 13)


pressure = kvo < 0 ? color.red : color.green
plot(kvo, title="KVO", linewidth=2, color=pressure)
plot(sig, title="Signal", linewidth=1, color = #8D1699)
hline(0, title="Middle Line", linestyle=hline.style_dotted)

plFound = na(pivotlow(kvo, lbL, lbR)) ? false : true
// TODO add separate price and vol pivots and lh/ll
// volplFound = na(pivotlow(kvo, lbL, lbR)) ? false : true
phFound = na(pivothigh(kvo, lbL, lbR)) ? false : true
// volphFound = na(pivothigh(kvo, lbL, lbR)) ? false : true

_inRange(cond) =>
	bars = barssince(cond == true)
	rangeLower <= bars and bars <= rangeUpper

//------------------------------------------------------------------------------
// Regular Bullish
// kvo: Higher Low

kvoHL = kvo[lbR] > valuewhen(plFound, kvo[lbR], 1) and _inRange(plFound[1])

// Price: Lower Low

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

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

plotshape(
	 bullCond ? kvo[lbR] : na,
	 offset=-lbR,
	 title="Regular Bullish Label",
	 text=" Bull ",
	 style=shape.labelup,
	 location=location.absolute,
	 color=bullColor,
	 textcolor=textColor
	 )
alertcondition(bullCond, "Bullish Signal Alert", "{{exchange}}:{{ticker}}, price = {{close}}")
//------------------------------------------------------------------------------
// Hidden Bullish
// kvo: Lower Low

kvoLL = kvo[lbR] < valuewhen(plFound, kvo[lbR], 1) and _inRange(plFound[1])

// Price: Higher Low

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

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

plotshape(
	 hiddenBullCond ? kvo[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bullish Label",
	 text=" H Bull ",
	 style=shape.labelup,
	 location=location.absolute,
	 color=bullColor,
	 textcolor=textColor
	 )
alertcondition(hiddenBullCond, "Hidden Bullish Signal Alert", "{{exchange}}:{{ticker}}, price = {{close}}")
//------------------------------------------------------------------------------
// Regular Bearish
// kvo: Lower High

kvoLH = kvo[lbR] < valuewhen(phFound, kvo[lbR], 1) and _inRange(phFound[1])

// Price: Higher High

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

bearCond = plotBear and priceHH and kvoLH and phFound

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

plotshape(
	 bearCond ? kvo[lbR] : na,
	 offset=-lbR,
	 title="Regular Bearish Label",
	 text=" Bear ",
	 style=shape.labeldown,
	 location=location.absolute,
	 color=bearColor,
	 textcolor=textColor
	 )
alertcondition(bearCond, "Bearish Signal Alert", "{{exchange}}:{{ticker}}, price = {{close}}")
//------------------------------------------------------------------------------
// Hidden Bearish
// kvo: Higher High

kvoHH = kvo[lbR] > valuewhen(phFound, kvo[lbR], 1) and _inRange(phFound[1])

// Price: Lower High

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

hiddenBearCond = plotHiddenBear and priceLH and kvoHH and phFound

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

plotshape(
	 hiddenBearCond ? kvo[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bearish Label",
	 text=" H Bear ",
	 style=shape.labeldown,
	 location=location.absolute,
	 color=bearColor,
	 textcolor=textColor
	 )
alertcondition(hiddenBearCond, "Hidden Bearish Signal Alert", "{{exchange}}:{{ticker}}, price = {{close}}")