Rotational Gravity Oscillator
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © burgercrisis, parts © Cheatcountry

//@version=5
//Written using elements from Cheatcountry scripts ( https://www.tradingview.com/u/cheatcountry/ )
//  https://www.tradingview.com/script/UyA4515j-Stock-Rotation-Model-CC/                    
//  https://www.tradingview.com/script/pOc6pmT3-True-Range-Adjusted-Exponential-Moving-Average-CC/
//Most of the code was technically written by him via these two scripts; I modified parts, tweaked the COG slightly, looked at possibilities that I didn't incorporate, and essentially "linked" these blocks of code together to form a novel new oscillator using recycled code from Cheatcountry, mostly.
//Give him a follow. Seriously. His work enables awesome stuff like this and he's super chill.

indicator("Rotational Gravity Oscillator", 'RGO')
spSym = input.symbol(title='Comparative Symbol', defval='CRYPTOCAP:TOTAL')      //  https://www.tradingview.com/script/UyA4515j-Stock-Rotation-Model-CC/          
inp = input(title='Source', defval=hlcc4)
res = input.timeframe(title='Resolution', defval='')
rep = input(title='Allow Repainting?', defval=false)
bar = input(title='Allow Bar Color Change?', defval=false)
src = request.security(syminfo.tickerid, res, inp[rep ? 0 : barstate.isrealtime ? 1 : 0])[rep ? 0 : barstate.isrealtime ? 0 : 1]
spSrc = request.security(spSym, res, inp[rep ? 0 : barstate.isrealtime ? 1 : 0])[rep ? 0 : barstate.isrealtime ? 0 : 1]     //end       //  https://www.tradingview.com/script/UyA4515j-Stock-Rotation-Model-CC/          
bandhide = input(true, 'Hide Distant Bands?', 'True = only displays the bands that are above and below the main oscillator. False = always display bands.')
BandColors = input(false, 'Band Colors', 'True: Band colors are set by their own directional movement ; False: Band colors are set by the moving averages position above or below the 0 line')
Arrows = input(true, 'Display Arrows', 'Potential trend reversals')
triangles = input(true, 'Triangles', 'True = display arrows as triangles. False, display arrows as... arrows.') 
transp = input.int(50, title= 'Arrow Transparency', minval=0, maxval=100)

Length1   =   input(10, "Internal Length 1", "Length of internal oscillator 1")
Length2   =   input(25, "Internal Length 2", "Length of internal oscillator 2")
Length3   =   input(50, "Internal Length 3", "Length of internal oscillator 3")
Length4   =   input(100, "Internal Length 4", "Length of internal oscillator 4")
Length5   =   input(12, "Internal Smoothing Length", "Length of internal moving average smoothing")
Length6   =   input(12, "External Smoothing Length", "Length of final external moving average smoothing")
mult   =   input(5.0, "Moving Average Multiplier", "The multiplier for the internal ATR for the All-True-Range Adjusted EMAs used in the script")

Length7   =   input(500, "Bollinger Bands Length", "Length of Bollinger Bands")
Length8   =   input(0, "Bollinger Bands StdDEV Modifier", "Adds this length to the length of the STDdev for the Bollinger Bands, without affecting the moving average length for them.")
dev11   =   input(1.0, "Bollinger Bands Multiplier 1", "The multiplier for the first Bollinger Bands")
dev22   =   input(2.0, "Bollinger Bands Multiplier 2", "The multiplier for the second Bollinger Bands")

trAdjEma(src, lengthy) =>       //  https://www.tradingview.com/script/pOc6pmT3-True-Range-Adjusted-Exponential-Moving-Average-CC/
    int lengthe = int(lengthy)
    float alpha = 2.0 / (lengthe + 1)
    float trL = ta.lowest(ta.tr, lengthe)
    float trH = ta.highest(ta.tr, lengthe)
    float trAdj = trH - trL != 0 ? (ta.tr - trL) / (trH - trL) : 0
    float trAdjEma = 0.0
    trAdjEma := nz(trAdjEma[1]) + (alpha * (1 + (trAdj * mult)) * (src - nz(trAdjEma[1])))      //end //  https://www.tradingview.com/script/pOc6pmT3-True-Range-Adjusted-Exponential-Moving-Average-CC/


pine_cog(source, length) =>
    sum = math.sum(source, length)
    num = 0.0
    for i = 0 to length - 1
        price = source - source[i]
        num := num + price * (i + 1)
    num / sum




satan1 = trAdjEma(pine_cog(src, Length1), Length5)      //  https://www.tradingview.com/script/UyA4515j-Stock-Rotation-Model-CC/    
satan2 = trAdjEma(pine_cog(src, Length2), Length5)
satan3 = trAdjEma(pine_cog(src, Length3), Length5)
satan4 = trAdjEma(pine_cog(src, Length4), Length5)

god1 = trAdjEma(pine_cog(spSrc, Length1), Length5)
god2 = trAdjEma(pine_cog(spSrc, Length2), Length5)
god3 = trAdjEma(pine_cog(spSrc, Length3), Length5)
god4 = trAdjEma(pine_cog(spSrc, Length4), Length5)

satan = trAdjEma((satan1 * 4) + (satan2 * 3) + (satan3 * 2) + satan4, Length6)
god = trAdjEma((god1 * 4) + (god2 * 3) + (god3 * 2) + god4, Length6)

dank = satan - god

slo = dank - nz(dank[1])
sig = slo > 0 ? slo > nz(slo[1]) ? 2 : 1 : slo < 0 ? slo < nz(slo[1]) ? -2 : -1 : 0
alertcondition(ta.crossover(sig, 1), "Strong Buy Signal", "Strong Bullish Change Detected")
alertcondition(ta.crossunder(sig, -1), "Strong Sell Signal", "Strong Bearish Change Detected")
alertcondition(ta.crossover(sig, 0), "Buy Signal", "Bullish Change Detected")
alertcondition(ta.crossunder(sig, 0), "Sell Signal", "Bearish Change Detected")
alertcondition(ta.crossover(sig, 0) or ta.crossover(sig, 1), "All Buy Signals", "Any Bullish Change Detected")
alertcondition(ta.crossunder(sig, 0) or ta.crossunder(sig, -1), "All Sell Signals", "Any Bearish Change Detected")
dankColor = sig > 1 ? color.rgb(150, 255, 150) : sig > 0 ? color.rgb(0, 126, 0) : sig < -1 ? color.rgb(255, 120, 120) : sig < 0 ? color.rgb(126, 0, 0) : color.black



float alpha = 2.0 / (Length7 + 1)       //  https://www.tradingview.com/script/pOc6pmT3-True-Range-Adjusted-Exponential-Moving-Average-CC/
float trL = ta.lowest(ta.tr, Length7)
float trH = ta.highest(ta.tr, Length7)
float trAdj = trH - trL != 0 ? (ta.tr - trL) / (trH - trL) : 0

float trAdjEma = 0.0
trAdjEma := nz(trAdjEma[1]) + (alpha * (1 + (trAdj * 1)) * ((satan - god) - nz(trAdjEma[1])))       //end //  https://www.tradingview.com/script/pOc6pmT3-True-Range-Adjusted-Exponential-Moving-Average-CC/

dev = dev11 * ta.stdev(satan - god, Length7 + Length8)
dev2 = dev22 * ta.stdev(satan - god, Length7 + Length8)
upper = trAdjEma + dev
lower = trAdjEma - dev
upper2 = trAdjEma + dev2
lower2 = trAdjEma - dev2


slo2 = trAdjEma - nz(trAdjEma[1])   //  https://www.tradingview.com/script/UyA4515j-Stock-Rotation-Model-CC/    
sig2 = slo2 > 0 ? slo2 > nz(slo2[1]) ? 2 : 1 : slo2 < 0 ? slo2 < nz(slo2[1]) ? -2 : -1 : 0
dankColor2 = sig2 > 1 ? color.rgb(150, 255, 150) : sig2 > 0 ? color.rgb(0, 126, 0) : sig2 < -1 ? color.rgb(255, 120, 120) : sig2 < 0 ? color.rgb(126, 0, 0) : color.black

slo3 = upper - nz(upper[1])
sig3 = slo3 > 0 ? slo3 > nz(slo3[1]) ? 2 : 1 : slo3 < 0 ? slo3 < nz(slo3[1]) ? -2 : -1 : 0
dankColor3 = sig3 > 1 ? color.rgb(120, 255, 120) : sig3 > 0 ? color.rgb(0, 90, 0) : sig3 < -1 ? color.rgb(255, 90, 90) : sig3 < 0 ? color.rgb(90, 0, 0) : color.black
slo4 = lower - nz(lower[1])
sig4 = slo4 > 0 ? slo4 > nz(slo4[1]) ? 2 : 1 : slo4 < 0 ? slo4 < nz(slo4[1]) ? -2 : -1 : 0
dankColor4 = sig4 > 1 ? color.rgb(120, 255, 120) : sig4 > 0 ? color.rgb(0, 90, 0) : sig4 < -1 ? color.rgb(255, 90, 90) : sig4 < 0 ? color.rgb(90, 0, 0) : color.black

slo5 = upper2 - nz(upper2[1])
sig5 = slo5 > 0 ? slo5 > nz(slo5[1]) ? 2 : 1 : slo5 < 0 ? slo5 < nz(slo5[1]) ? -2 : -1 : 0
dankColor5 = sig5 > 1 ? color.rgb(120, 255, 120) : sig5 > 0 ? color.rgb(0, 90, 0) : sig5 < -1 ? color.rgb(255, 90, 90) : sig5 < 0 ? color.rgb(90, 0, 0) : color.black
slo6 = lower2 - nz(lower2[1])
sig6 = slo6 > 0 ? slo6 > nz(slo6[1]) ? 2 : 1 : slo6 < 0 ? slo6 < nz(slo6[1]) ? -2 : -1 : 0
dankColor6 = sig6 > 1 ? color.rgb(120, 255, 120) : sig6 > 0 ? color.rgb(0, 90, 0) : sig6 < -1 ? color.rgb(255, 90, 90) : sig6 < 0 ? color.rgb(90, 0, 0) : color.black   //end //  https://www.tradingview.com/script/UyA4515j-Stock-Rotation-Model-CC/    


barcolor(bar ? dankColor : na)

plotshape(Arrows ? sig==2 and sig2==2 and dank>0  and ta.barssince(sig>=1 and  sig2>=1 and dank>0  )[1]>1  and ta.barssince(dank<0)<ta.barssince(sig<=1 and  dank>0  )[1] : na, 'Strong Uptrend Started', triangles ? shape.triangleup : shape.arrowup, location=location.bottom, size=size.large, color=color.new(color.blue, transp))
plotshape(Arrows ? sig==2 and sig2==2 and ta.barssince(sig==2 and sig2==2)[1]>ta.barssince(sig2<0) : na, 'Uptrend Started', triangles ? shape.triangleup : shape.arrowup, location=location.bottom, size=size.small, color=color.new(color.blue, transp))
plotshape(Arrows ? sig==2 and sig2==2 and dank>0 and ta.barssince(sig==2 and sig2==2 and dank>0 )[1]>ta.barssince(sig2<0) : na, 'Uptrend Started', triangles ? shape.triangleup : shape.arrowup, location=location.bottom, size=size.small, color=color.new(color.teal, transp))
plotshape(Arrows ? sig==2 and sig2<0 and dank<0  and ta.barssince(sig>=1 and  sig2<0 and dank<0  )[1]>1 : na, 'Early Uptrend Started', triangles ? shape.triangleup : shape.arrowup, location=location.bottom, size=size.tiny, color=color.new(color.blue, transp))

plotshape(Arrows ? sig==-2 and sig2==-2 and dank<0  and ta.barssince(sig<=-1 and  sig2<=-1 and dank<0  )[1]>1  and ta.barssince(dank>0)<ta.barssince(sig<=-1 and  dank<0  )[1] : na, 'Strong Downtrend Started', triangles ? shape.triangledown : shape.arrowdown, location=location.top, size=size.large, color=color.new(color.yellow, transp))
plotshape(Arrows ? sig==-2 and sig2==-2 and ta.barssince(sig==-2 and sig2==-2)[1]>ta.barssince(sig2>0) : na, 'Downtrend Started', triangles ? shape.triangledown : shape.arrowdown, location=location.top, size=size.small, color=color.new(color.yellow, transp))
plotshape(Arrows ? sig==-2 and sig2==-2 and dank<0 and ta.barssince(sig==-2 and sig2==-2 and dank<0)[1]>ta.barssince(sig2>0) : na, 'Downtrend Started', triangles ? shape.triangledown : shape.arrowdown, location=location.top, size=size.small, color=color.new(color.rgb(143, 86, 0), transp))
plotshape(Arrows ? sig==-2 and sig2>0 and dank>0  and ta.barssince(sig<=-1 and  sig2>0 and dank>0  )[1]>1 : na, 'Early Downtrend Started', triangles ? shape.triangledown : shape.arrowdown, location=location.top, size=size.tiny, color=color.new(color.yellow, transp))

//plotshape(Arrows ?  : na, 'Early Downtrend Started', shape.xcross, location=location.absolute, size=size.tiny, color=color.yellow)

plot(dank, color=dankColor, linewidth = 2, title='RGO')     //end //  https://www.tradingview.com/script/UyA4515j-Stock-Rotation-Model-CC/    

linexx = plot(0, color=dank>0 ? color.green : color.red, title='0-Line')

trAdjEmapl = plot(trAdjEma, "MA", dankColor2)
plot(bandhide ? dank > trAdjEma ? upper : na : upper, "Upper Band 1", BandColors ? dankColor3 : trAdjEma>0 ? color.green : color.red, style=plot.style_linebr)
plot(bandhide ? dank < trAdjEma ? lower : na : lower, "Lower Band 1", BandColors ? dankColor4 : trAdjEma>0 ? color.green : color.red, style=plot.style_linebr)
plot(bandhide ? dank > upper ? upper2 : na : upper2, "Upper Band 2", BandColors ? dankColor5 : trAdjEma>0 ? color.green : color.red, style=plot.style_linebr)
plot(bandhide ? dank < lower ? lower2 : na : lower2, "Lower Band 2", BandColors ? dankColor6 : trAdjEma>0 ? color.green : color.red, style=plot.style_linebr)


fill(trAdjEmapl, linexx, color=trAdjEma>0 ? color.new(color.green, 80) : color.new(color.red, 80))