CDC Divergences
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © piriya33

//@version=4
study("CDC Divergences","CDC Divergences",overlay=true, max_labels_count = 500)


// Inputs for Higher Highs and Lower Lows calculations
g_hhll      = "Higher highs / Lower lows"
src         = input(close,"Price Source",type=input.source,group=g_hhll)
UseDifSrc   = input(false,"Use different sources for High and Low",group=g_hhll)
srcHi       = input(high,"High:",input.source,group=g_hhll,inline="Diffsrc")
srcLo       = input(low,"Low:",input.source,group=g_hhll,inline="Diffsrc")
lenL        = input(5,"Pivot Lookback Left:",input.integer,minval=1,group=g_hhll,inline="pivotLR")
lenR        = input(5,"Right:",input.integer,group=g_hhll,inline="pivotLR")

chksrc = input("RSI","Check Against:",input.string,options=["RSI","MACD","Stoch","Volume","OBV"])

g_rsi       = "RSI Calculations"
rsi_src     = input(close,"RSI source:",input.source,group=g_rsi,inline="rsi")
rsi_len     = input(14,"/ length:",input.integer,minval=1,group=g_rsi,inline="rsi")
rsi_ob      = input(70,"Overbought",input.float,group=g_rsi,inline="rsi_obos")
rsi_os      = input(30,"Oversold",input.float,group=g_rsi,inline="rsi_obos")

g_macd      = "MACD Calculations"
macd_src    = input(close,"MACD source:",input.source,group=g_macd)
macd_fast   = input(12,"MACD Lookback Fast:",input.integer,group=g_macd,inline="macdlen")
macd_slow   = input(26,"/ Slow:",input.integer,group=g_macd,inline="macdlen")

g_sto       = "Stochastic Oscillator Calculations"
sto_klen    = input(14,"\%k Length:",input.integer,minval=1,group=g_sto,inline="stok")
sto_ksmt    = input(1,"/ \%k smoothing",input.integer,minval=1,group=g_sto,inline="stok")
sto_dsmt    = input(3,"\%d smoothing",input.integer,minval=1, group=g_sto, inline="stod")
sto_sel     = input("d","Use value:",input.string,options=["d","k","min/max"], group=g_sto, inline="stod")
sto_ob      = input(80,"Overbought",input.float,group=g_sto,inline="sto_obos")
sto_os      = input(20,"Oversold",input.float,group=g_sto,inline="sto_obos")

g_obv       = "On Balance Volume Calculation"

// Calculates Highs and Lows

_lows   = pivotlow(UseDifSrc  ? srcLo : src, lenL,lenR)
_highs  = pivothigh(UseDifSrc ? srcHi : src, lenL,lenR)

_low0   = valuewhen(_lows,  (UseDifSrc ? srcLo : src)[lenR], 0)
_high0  = valuewhen(_highs, (UseDifSrc ? srcHi : src)[lenR], 0)
_low1   = valuewhen(_lows,  (UseDifSrc ? srcLo : src)[lenR], 1)
_high1  = valuewhen(_highs, (UseDifSrc ? srcHi : src)[lenR], 1)

HH      = _high0 > _high0[1] and _high0 > _high1    // Checks for Higher Highs
LL      = _low0 < _low0[1] and _low0 < _low1        // Cheks for Lower Lows


// Plot Lines Showing Pivot Highs and Pivot Lows on occurance 0 and 1
// plot(src)
// plot(_low0, color=color.red, style=plot.style_stepline, offset=-len1)
// plot(_low1, color=color.orange, style=plot.style_stepline, offset=-len1)
// plot(_high0, color=color.green, style=plot.style_stepline, offset=-lenL)
// plot(_high1, color=color.blue, style=plot.style_stepline, linewidth=2, offset=-lenL)

// Plots arrows indicating higher highs and lower lows
plotshape(HH,"Higher High",style=shape.triangledown, location=location.abovebar, offset=-lenR)
plotshape(LL,"Lower Low", style=shape.triangleup,location=location.belowbar,offset=-lenR)

// Signals

// Buy on higher high and sell on lower lows

// isLong  = barssince(HH) < barssince(LL)
// isShort = barssince(HH) > barssince(LL)

// bcolor  = isLong ? color.green : isShort ? color.red : color.blue
// barcolor(bcolor)


// Check for convergence divergence

var BullishDiv = false
var BearishDiv = false


if chksrc == "RSI" // Check against RSI
    rsi         = rsi(rsi_src,rsi_len)
    
    rsi_low0    = valuewhen(_lows,  rsi[lenR], 0)
    rsi_high0   = valuewhen(_highs, rsi[lenR], 0)
    rsi_low1    = valuewhen(_lows,  rsi[lenR], 1)
    rsi_high1   = valuewhen(_highs, rsi[lenR], 1)
    
    BullishDiv := LL and rsi_low1 < rsi_os  and rsi_low0 > rsi_low1
    BearishDiv := HH and rsi_high1 > rsi_ob and rsi_high0 < rsi_high1
 
 
else if chksrc == "MACD" //Check Against MACD
 
 
    [macd,_,_]  = macd(macd_src,macd_fast,macd_slow,9)
    
    macd_low0   = valuewhen(_lows,   macd[lenR], 0)
    macd_high0  = valuewhen(_highs,  macd[lenR], 0)
    macd_low1   = valuewhen(_lows,   macd[lenR], 1)
    macd_high1  = valuewhen(_highs,  macd[lenR], 1)
    
    BullishDiv := LL and macd_low0 > macd_low1
    BearishDiv := HH and macd_high0 < macd_high1
 
  
else if (chksrc == "Stoch") // Check Against STO
   
    k   = sma(stoch(close,high,low,sto_klen),sto_ksmt)
    d   = sma(k,sto_dsmt)
    
    sto_low     = sto_sel == "d" ? d : sto_sel == "k" ? k : sto_sel == "min/max" ? min(k,d) : na
    sto_high    = sto_sel == "d" ? d : sto_sel == "k" ? k : sto_sel == "min/max" ? max(k,d) : na
    
    sto_low0    = valuewhen(_lows, sto_low[lenR], 0)
    sto_high0   = valuewhen(_highs, sto_high[lenR], 0)
    sto_low1    = valuewhen(_lows, sto_low[lenR], 1)
    sto_high1   = valuewhen(_highs, sto_high[lenR], 1)
    
    BullishDiv  := LL and sto_low1 < sto_os and sto_low0 > sto_low1
    BearishDiv  := HH and sto_high1 > sto_ob and sto_high0 < sto_high1
    
    
else if chksrc == "Volume" // Check Against Volume

    vol = volume
    
    vol_low0    = valuewhen(_lows, vol[lenR], 0)
    vol_high0   = valuewhen(_highs, vol[lenR], 0)
    vol_low1    = valuewhen(_lows, vol[lenR], 1)
    vol_high1   = valuewhen(_highs, vol[lenR], 1)
    
    BullishDiv  := LL and vol_low0 < vol_low1
    BearishDiv  := HH and vol_high0 < vol_high1
    
    
else if chksrc == "OBV" // Check Against OBV

    _obv = obv
    
    obv_low0    = valuewhen(_lows, _obv[lenR], 0)
    obv_high0   = valuewhen(_highs, _obv[lenR], 0)
    obv_low1    = valuewhen(_lows, _obv[lenR], 1)
    obv_high1   = valuewhen(_highs, _obv[lenR], 1)
    
    BullishDiv  := LL and obv_low0 > obv_low1
    BearishDiv  := HH and obv_high0 < obv_high1
    
    
    
else
    na

// Plotshapes to quickly check if code is working correctly
// plotshape(BullishDiv,"Bullsih Divergence",style=shape.arrowup,location=location.belowbar,
//  offset=-lenR,size=size.large,color=color.green)
// plotshape(BearishDiv,"Bearish Divergence",style=shape.arrowdown,location=location.abovebar,
//  offset=-lenR,size=size.large,color=color.red)

// Plots Labels Indicating Bullish / Bearish Divergences
plotLabel(_offset, _div, _style, _color, _text) =>
    if not na(_div)
        label.new(bar_index[_offset], _div,_text,style=_style,color=_color)


BullDivVal  = BullishDiv ? _lows : na
BearDivVal  = BearishDiv ? _highs : na

plotLabel(lenR, BullDivVal, label.style_label_up, color.green, chksrc + " Bullish Divergence")
plotLabel(lenR, BearDivVal, label.style_label_down, color.red, chksrc + " Bearish Divergence")