Cipher & Divergence
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

// Thanks to LazyBear for his WaveTrend Oscillator https://www.tradingview.com/script/2KE8wTuF-Indicator-WaveTrend-Oscillator-WT/
// Thanks to vumanchu for his script vmc sipher B https://www.tradingview.com/script/Msm4SjwI-VuManChu-Cipher-B-Divergences/
// I especially want to thank TradingView for its platform that facilitates development and learning.

// NOTES:
//  - I use it not to buy the bottom, but to get a confirmation when to enter
//  - Watch for a divergence to appear
//  - Wait for our wave trend to cross the zero line
//  - Enter on a pullback at key fib levels 

//@version=4
study("Cipher & Divergence")

//----------------------------------------------------------------------
// Helpers
//----------------------------------------------------------------------
// Thanks to vumanchu for his div finder https://www.tradingview.com/script/Msm4SjwI-VuManChu-Cipher-B-Divergences/
f_top_fractal(src) => src[4] < src[2] and src[3] < src[2] and src[2] > src[1] and src[2] > src[0]
f_bot_fractal(src) => src[4] > src[2] and src[3] > src[2] and src[2] < src[1] and src[2] < src[0]
f_fractalize(src) => f_top_fractal(src) ? 1 : f_bot_fractal(src) ? -1 : 0

f_findDivs(src, topLimit, botLimit, useLimits) =>
    fractalTop = f_fractalize(src) > 0 and (useLimits ? src[2] >= topLimit : true) ? src[2] : na
    fractalBot = f_fractalize(src) < 0 and (useLimits ? src[2] <= botLimit : true) ? src[2] : na
    highPrev = valuewhen(fractalTop, src[2], 0)[2]
    highPrice = valuewhen(fractalTop, high[2], 0)[2]
    lowPrev = valuewhen(fractalBot, src[2], 0)[2]
    lowPrice = valuewhen(fractalBot, low[2], 0)[2]
    bearSignal = fractalTop and high[2] > highPrice and src[2] < highPrev
    bullSignal = fractalBot and low[2] < lowPrice and src[2] > lowPrev
    [fractalTop, fractalBot, bearSignal, bullSignal]

//----------------------------------------------------------------------
// 0 line
//----------------------------------------------------------------------
plot(0, color=color.gray)

//----------------------------------------------------------------------
// Main signal
//----------------------------------------------------------------------
chanLength = input(20, "Channel Length", group="Wave trend")
avgLength = input(5, "Average Length", group="Wave trend")
maLength = input(2, "MA Length", group="Wave trend")
src = input(title="Source", defval=hlc3, type=input.source, group="Wave trend")

esa = ema(src, chanLength)
d = ema(abs(src - esa), chanLength)
ci = (src - esa) / (0.015 * d)
wt1 = ema(ci, avgLength)
wt2 = sma(wt1, maLength)

wt1p = plot(wt1, color=color.gray, transp=100)
wt2p = plot(wt2, color=color.gray, transp=100)

fill(wt1p, wt2p, color=(wt1 > wt2 ? color.green : color.red), transp=0)

//----------------------------------------------------------------------
// Divs
//----------------------------------------------------------------------
wtDivOBLevel = input(45, title = 'Bearish Divergence min', type = input.integer, group="Divergences")
wtDivOSLevel = input(-65, title = 'Bullish Divergence min', type = input.integer, group="Divergences")
[fractalTop, fractalBot, bearDiv, bullDiv] = f_findDivs(wt2, wtDivOBLevel, wtDivOSLevel, true)

bearDivColor = bearDiv ? color.red : na
bullDivColor = bullDiv ? color.green : na

plot(series = fractalTop ? wt2[2] : na, title = 'Bearish Divergence', color = bearDivColor, linewidth = 2, offset = -2)
plot(series = fractalBot ? wt2[2] : na, title = 'Bullish Divergence', color = bullDivColor, linewidth = 2, offset = -2)

//----------------------------------------------------------------------
// Alerts
//----------------------------------------------------------------------
alertcondition(bearDiv, title="Bearish diversion")
alertcondition(bullDiv, title="Bullish diversion")
alertcondition(crossover(wt2, 0), title="Wave trend crossed over 0 line")
alertcondition(crossunder(wt2, 0), title="Wave trend crossed under 0 line")