Blocky's EMA Ribbon
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// Extended EMA inspiration from https://www.tradingview.com/script/hWdwt5XH-Multi-Moving-Average-with-Forecast/

// © godzcopilot

//@version=5
indicator(title="Blocky's EMA Ribbon", shorttitle="BREMA", overlay=true)

// Display Options
show_outer = input.bool(false, "Show outer EMAs", group = "Display")
show_inner = input.bool(false, "Show inner EMAs",  group = "Display")
show_gradient = input.bool(true, "Show gradient fill",  group = "Display")
show_channels = input.bool(true, "Show offset EMA channel",  group = "Display")

// Gradient Options
opacity_multiplier = input.int(6, minval=1, maxval = 100, title="Opacity Multiplier",  group = "Display")
bear_color = input.color(color.red,"Bear Color",  group = "Display")
bull_color = input.color(color.green,"Bull Color",  group = "Display")
ribbon_highlight = input.bool(false, "Highlight gradient",  group = "Display")

// Set EMA Colors
ema1color = color.new(color.rgb(102,255,102),0)
ema2color = color.new(color.rgb(153,255,153),0)
ema3color = color.new(color.rgb(178,255,102),0)
ema4color = color.new(color.rgb(255,255,51),0)
ema5color = color.new(color.rgb(255,178,102),0)
ema6color = color.new(color.rgb(255,153,51),0)
ema7color = color.new(color.rgb(255,153,153),0)
ema8color = color.new(color.rgb(255,51,51),0)


// Select EMA Source and lengths
src = input(close, title="Source", group = "Source")

len1 = input.int(21, minval=1, title="Length 1 [Fastest]", group = "EMA")
len2 = input.int(25, minval=1, title="Length 2", group = "EMA")
len3 = input.int(30, minval=1, title="Length 3", group = "EMA")
len4 = input.int(35, minval=1, title="Length 4", group = "EMA")
len5 = input.int(40, minval=1, title="Length 5", group = "EMA")
len6 = input.int(45, minval=1, title="Length 6", group = "EMA")
len7 = input.int(50, minval=1, title="Length 7", group = "EMA")
len8 = input.int(55, minval=1, title="Length 8 [Slowest]", group = "EMA")

len9 = input.int(200, minval=1, title="Length", group = "EMA")

channel_multiplier = input.float(1.5, minval=0.1, maxval = 10.0, title="Channel Multiplier",  group = "EMA Channel")

// Calculate EMA's
ema1 = ta.ema(src, len1)
ema2 = ta.ema(src, len2)
ema3 = ta.ema(src, len3)
ema4 = ta.ema(src, len4)
ema5 = ta.ema(src, len5)
ema6 = ta.ema(src, len6)
ema7 = ta.ema(src, len7)
ema8 = ta.ema(src, len8)

ema9 = ta.ema(src, len9)

// Calculate outer channels
upper_channel = math.max(ema1, ema8) + (math.abs(ema1 - ema8) * channel_multiplier)
lower_channel = math.min(ema1, ema8) - (math.abs(ema1 - ema8) * channel_multiplier)


// Calculate gradient transparency based on percentage separation of outer EMA's
color_transp = 100 - math.min(math.round(math.abs(ema1 - ema8) / ((ema1 + ema8) / 2) * 100 * opacity_multiplier,0) + 2,100)

// Calculate color based on EMA's laying in order ie short - fast / fast - short
color_weight = 0

if ema1 > ema2
    color_weight := color_weight + 1
if ema1 > ema3
    color_weight := color_weight + 1
if ema1 > ema4
    color_weight := color_weight + 1
if ema1 > ema5
    color_weight := color_weight + 1
if ema1 > ema6
    color_weight := color_weight + 1
if ema1 > ema7
    color_weight := color_weight + 1
if ema1 > ema8
    color_weight := color_weight + 1
if ema2 > ema1
    color_weight := color_weight - 1
if ema2 > ema3
    color_weight := color_weight + 1
if ema2 > ema4
    color_weight := color_weight + 1
if ema2 > ema5
    color_weight := color_weight + 1
if ema2 > ema6
    color_weight := color_weight + 1
if ema2 > ema7
    color_weight := color_weight + 1
if ema2 > ema8
    color_weight := color_weight + 1
if ema3 > ema1
    color_weight := color_weight - 1
if ema3 > ema2
    color_weight := color_weight - 1
if ema3 > ema4
    color_weight := color_weight + 1
if ema3 > ema5
    color_weight := color_weight + 1
if ema3 > ema6
    color_weight := color_weight + 1
if ema3 > ema7
    color_weight := color_weight + 1
if ema3 > ema8
    color_weight := color_weight + 1
if ema4 > ema1
    color_weight := color_weight - 1
if ema4 > ema2
    color_weight := color_weight - 1
if ema4 > ema3
    color_weight := color_weight - 1
if ema4 > ema5
    color_weight := color_weight + 1
if ema4 > ema6
    color_weight := color_weight + 1
if ema4 > ema7
    color_weight := color_weight + 1
if ema4 > ema8
    color_weight := color_weight + 1
if ema5 > ema1
    color_weight := color_weight - 1
if ema5 > ema2
    color_weight := color_weight - 1
if ema5 > ema3
    color_weight := color_weight - 1
if ema5 > ema4
    color_weight := color_weight - 1
if ema5 > ema6
    color_weight := color_weight + 1
if ema5 > ema7
    color_weight := color_weight + 1
if ema5 > ema8
    color_weight := color_weight + 1
if ema6 > ema1
    color_weight := color_weight - 1
if ema6 > ema2
    color_weight := color_weight - 1
if ema6 > ema3
    color_weight := color_weight - 1
if ema6 > ema4
    color_weight := color_weight - 1
if ema6 > ema5
    color_weight := color_weight - 1
if ema6 > ema7
    color_weight := color_weight + 1
if ema6 > ema8
    color_weight := color_weight + 1
if ema8 > ema1
    color_weight := color_weight - 1
if ema8 > ema2
    color_weight := color_weight - 1
if ema8 > ema3
    color_weight := color_weight - 1
if ema8 > ema4
    color_weight := color_weight - 1
if ema8 > ema5
    color_weight := color_weight - 1
if ema8 > ema6
    color_weight := color_weight - 1
if ema8 > ema7
    color_weight := color_weight - 1

// Calculate prediction extension
ma_prediction(_src, _period, _offset) =>
    (ta.ema(_src, _period - _offset) * (_period - _offset) + _src * _offset) / _period

pma1_1 = ma_prediction(src, len1, 1)
pma1_2 = ma_prediction(src, len1, 2)
pma1_3 = ma_prediction(src, len1, 3)
pma1_4 = ma_prediction(src, len1, 4)
pma1_5 = ma_prediction(src, len1, 5)

pma2_1 = ma_prediction(src, len2, 1)
pma2_2 = ma_prediction(src, len2, 2)
pma2_3 = ma_prediction(src, len2, 3)
pma2_4 = ma_prediction(src, len2, 4)
pma2_5 = ma_prediction(src, len2, 5)

pma3_1 = ma_prediction(src, len3, 1)
pma3_2 = ma_prediction(src, len3, 2)
pma3_3 = ma_prediction(src, len3, 3)
pma3_4 = ma_prediction(src, len3, 4)
pma3_5 = ma_prediction(src, len3, 5)

pma4_1 = ma_prediction(src, len4, 1)
pma4_2 = ma_prediction(src, len4, 2)
pma4_3 = ma_prediction(src, len4, 3)
pma4_4 = ma_prediction(src, len4, 4)
pma4_5 = ma_prediction(src, len4, 5)

pma5_1 = ma_prediction(src, len5, 1)
pma5_2 = ma_prediction(src, len5, 2)
pma5_3 = ma_prediction(src, len5, 3)
pma5_4 = ma_prediction(src, len5, 4)
pma5_5 = ma_prediction(src, len5, 5)

pma6_1 = ma_prediction(src, len6, 1)
pma6_2 = ma_prediction(src, len6, 2)
pma6_3 = ma_prediction(src, len6, 3)
pma6_4 = ma_prediction(src, len6, 4)
pma6_5 = ma_prediction(src, len6, 5)

pma7_1 = ma_prediction(src, len7, 1)
pma7_2 = ma_prediction(src, len7, 2)
pma7_3 = ma_prediction(src, len7, 3)
pma7_4 = ma_prediction(src, len7, 4)
pma7_5 = ma_prediction(src, len7, 5)

pma8_1 = ma_prediction(src, len8, 1)
pma8_2 = ma_prediction(src, len8, 2)
pma8_3 = ma_prediction(src, len8, 3)
pma8_4 = ma_prediction(src, len8, 4)
pma8_5 = ma_prediction(src, len8, 5)


// Plot all EMA's
p1 = plot(ema1, title="EMA", color=ema1color, style =plot.style_line, linewidth = 1, editable = false, display = show_outer ? display.all : display.none)
p2 = plot(ema2, title="EMA", color=ema2color, style =plot.style_line, linewidth = 1, editable = false, display = show_inner ? display.all : display.none)
p3 = plot(ema3, title="EMA", color=ema3color, style =plot.style_line, linewidth = 1, editable = false, display = show_inner ? display.all : display.none)
p4 = plot(ema4, title="EMA", color=ema4color, style =plot.style_line, linewidth = 1, editable = false, display = show_inner ? display.all : display.none)
p5 = plot(ema5, title="EMA", color=ema5color, style =plot.style_line, linewidth = 1, editable = false, display = show_inner ? display.all : display.none)
p6 = plot(ema6, title="EMA", color=ema6color, style =plot.style_line, linewidth = 1, editable = false, display = show_inner ? display.all : display.none)
p7 = plot(ema7, title="EMA", color=ema7color, style =plot.style_line, linewidth = 1, editable = false, display = show_inner ? display.all : display.none)
p8 = plot(ema8, title="EMA", color=ema8color, style =plot.style_line, linewidth = 1, editable = false, display = show_outer ? display.all : display.none)

p9 = plot(ema9, title="EMA", color=color.new(color.rgb(0,150,150),0), editable = true, linewidth = 2)

// Plot predictive EMA's
plot(pma1_1, title='MA 1 Forecast 1', color=ema1color, linewidth=1, style=plot.style_circles, offset=1, show_last=1)
plot(pma1_2, title='MA 1 Forecast 2', color=ema1color, linewidth=1, style=plot.style_circles, offset=2, show_last=1)
plot(pma1_3, title='MA 1 Forecast 3', color=ema1color, linewidth=1, style=plot.style_circles, offset=3, show_last=1)
plot(pma1_4, title='MA 1 Forecast 4', color=ema1color, linewidth=1, style=plot.style_circles, offset=4, show_last=1)
plot(pma1_5, title='MA 1 Forecast 5', color=ema1color, linewidth=1, style=plot.style_circles, offset=5, show_last=1)

plot(pma2_1, title='MA 1 Forecast 1', color=ema2color, linewidth=1, style=plot.style_circles, offset=1, show_last=1)
plot(pma2_2, title='MA 1 Forecast 2', color=ema2color, linewidth=1, style=plot.style_circles, offset=2, show_last=1)
plot(pma2_3, title='MA 1 Forecast 3', color=ema2color, linewidth=1, style=plot.style_circles, offset=3, show_last=1)
plot(pma2_4, title='MA 1 Forecast 4', color=ema2color, linewidth=1, style=plot.style_circles, offset=4, show_last=1)
plot(pma2_5, title='MA 1 Forecast 5', color=ema2color, linewidth=1, style=plot.style_circles, offset=5, show_last=1)

plot(pma3_1, title='MA 1 Forecast 1', color=ema3color, linewidth=1, style=plot.style_circles, offset=1, show_last=1)
plot(pma3_2, title='MA 1 Forecast 2', color=ema3color, linewidth=1, style=plot.style_circles, offset=2, show_last=1)
plot(pma3_3, title='MA 1 Forecast 3', color=ema3color, linewidth=1, style=plot.style_circles, offset=3, show_last=1)
plot(pma3_4, title='MA 1 Forecast 4', color=ema3color, linewidth=1, style=plot.style_circles, offset=4, show_last=1)
plot(pma3_5, title='MA 1 Forecast 5', color=ema3color, linewidth=1, style=plot.style_circles, offset=5, show_last=1)

plot(pma4_1, title='MA 1 Forecast 1', color=ema4color, linewidth=1, style=plot.style_circles, offset=1, show_last=1)
plot(pma4_2, title='MA 1 Forecast 2', color=ema4color, linewidth=1, style=plot.style_circles, offset=2, show_last=1)
plot(pma4_3, title='MA 1 Forecast 3', color=ema4color, linewidth=1, style=plot.style_circles, offset=3, show_last=1)
plot(pma4_4, title='MA 1 Forecast 4', color=ema4color, linewidth=1, style=plot.style_circles, offset=4, show_last=1)
plot(pma4_5, title='MA 1 Forecast 5', color=ema4color, linewidth=1, style=plot.style_circles, offset=5, show_last=1)

plot(pma5_1, title='MA 1 Forecast 1', color=ema5color, linewidth=1, style=plot.style_circles, offset=1, show_last=1)
plot(pma5_2, title='MA 1 Forecast 2', color=ema5color, linewidth=1, style=plot.style_circles, offset=2, show_last=1)
plot(pma5_3, title='MA 1 Forecast 3', color=ema5color, linewidth=1, style=plot.style_circles, offset=3, show_last=1)
plot(pma5_4, title='MA 1 Forecast 4', color=ema5color, linewidth=1, style=plot.style_circles, offset=4, show_last=1)
plot(pma5_5, title='MA 1 Forecast 5', color=ema5color, linewidth=1, style=plot.style_circles, offset=5, show_last=1)

plot(pma6_1, title='MA 1 Forecast 1', color=ema6color, linewidth=1, style=plot.style_circles, offset=1, show_last=1)
plot(pma6_2, title='MA 1 Forecast 2', color=ema6color, linewidth=1, style=plot.style_circles, offset=2, show_last=1)
plot(pma6_3, title='MA 1 Forecast 3', color=ema6color, linewidth=1, style=plot.style_circles, offset=3, show_last=1)
plot(pma6_4, title='MA 1 Forecast 4', color=ema6color, linewidth=1, style=plot.style_circles, offset=4, show_last=1)
plot(pma6_5, title='MA 1 Forecast 5', color=ema6color, linewidth=1, style=plot.style_circles, offset=5, show_last=1)

plot(pma7_1, title='MA 1 Forecast 1', color=ema7color, linewidth=1, style=plot.style_circles, offset=1, show_last=1)
plot(pma7_2, title='MA 1 Forecast 2', color=ema7color, linewidth=1, style=plot.style_circles, offset=2, show_last=1)
plot(pma7_3, title='MA 1 Forecast 3', color=ema7color, linewidth=1, style=plot.style_circles, offset=3, show_last=1)
plot(pma7_4, title='MA 1 Forecast 4', color=ema7color, linewidth=1, style=plot.style_circles, offset=4, show_last=1)
plot(pma7_5, title='MA 1 Forecast 5', color=ema7color, linewidth=1, style=plot.style_circles, offset=5, show_last=1)

plot(pma8_1, title='MA 1 Forecast 1', color=ema8color, linewidth=1, style=plot.style_circles, offset=1, show_last=1)
plot(pma8_2, title='MA 1 Forecast 2', color=ema8color, linewidth=1, style=plot.style_circles, offset=2, show_last=1)
plot(pma8_3, title='MA 1 Forecast 3', color=ema8color, linewidth=1, style=plot.style_circles, offset=3, show_last=1)
plot(pma8_4, title='MA 1 Forecast 4', color=ema8color, linewidth=1, style=plot.style_circles, offset=4, show_last=1)
plot(pma8_5, title='MA 1 Forecast 5', color=ema8color, linewidth=1, style=plot.style_circles, offset=5, show_last=1)


pUpper = plot(upper_channel, title="Upper Channel", color=color.new(color.yellow, 50), linewidth = 1, style = plot.style_line)
pLower = plot(lower_channel, title="Upper Channel", color=color.new(color.blue, 50), linewidth = 1, style = plot.style_line)

// Fill between fast and slow EMAs with weighted coloring and transparency
fill(p1,p8,color=color.new(color.white, 90),editable = false,  display = ribbon_highlight ? display.all : display.none)
fill(p1,p8,color=show_gradient ? color.new(color.from_gradient(math.abs(color_weight),0,28,color.navy,color_weight > 0 ? bull_color : bear_color),color_transp) : na,editable = false)