Moving Average Continuity [QuantVue]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © QuantVue

//@version=5
indicator('Moving Average Continuity [QuantVue]', overlay = true)

tt = 'Please select a chart time frame lower than or equal to your lowest selected moving average time frame'

// inputs
tf1 = input.timeframe('D', 'Time Frame 1', tooltip = tt)
tf2 = input.timeframe('240', 'Time Frame 2', tooltip = tt)
tf3 = input.timeframe('60', 'Time Frame 3', tooltip = tt)
fastMaLen = input.int(8, 'Fast MA', inline = '2')
slowMaLen = input.int(21, 'Slow MA', inline = '3')
slowMaType = input.string(defval = 'EMA', title = 'MA Type', options = ['EMA', 'SMA', 'HMA', 'WMA', 'VWMA'], inline = '2')
fastMaType = input.string(defval = 'EMA', title = 'MA Type', options = ['EMA', 'SMA', 'HMA', 'WMA', 'VWMA'], inline = '3')
yPos = input.string('Top', 'Table Position', options = ['Top', 'Middle', 'Bottom'], inline = '1')
xPos = input.string('Right', ' ', options = ['Right','Center', 'Left'], inline = '1')

//runtime error
if timeframe.in_seconds() > timeframe.in_seconds(tf1) or timeframe.in_seconds() > timeframe.in_seconds(tf2) or timeframe.in_seconds() > timeframe.in_seconds(tf3)
    runtime.error(tt)

//create labels
var table maLabels = table.new(str.lower(yPos) + '_' + str.lower(xPos), 3, 2, color.new(color.white,100), color.new(color.white,100), 2 , color.new(color.white,100), 2)

// get moving average data
fastMa = switch fastMaType
    'EMA' => ta.ema(close, fastMaLen)  
    'SMA' => ta.sma(close, fastMaLen)
    'HMA' => ta.hma(close, fastMaLen) 
    'WMA' => ta.wma(close, fastMaLen)
    'VWMA' => ta.vwma(close, fastMaLen)

slowMa = switch slowMaType
    'EMA' => ta.ema(close, slowMaLen)  
    'SMA' => ta.sma(close, slowMaLen)
    'HMA' => ta.hma(close, slowMaLen) 
    'WMA' => ta.wma(close, slowMaLen)
    'VWMA' => ta.vwma(close, slowMaLen)

tf1FastMa = request.security(syminfo.tickerid, tf1, fastMa)
tf1SlowMa = request.security(syminfo.tickerid, tf1, slowMa)

tf2FastMa = request.security(syminfo.tickerid, tf2, fastMa)
tf2SlowMa = request.security(syminfo.tickerid, tf2, slowMa)

tf3FastMa = request.security(syminfo.tickerid, tf3, fastMa)
tf3SlowMa = request.security(syminfo.tickerid, tf3, slowMa)

// table variables
cell1Text = timeframe.in_seconds(tf1) < timeframe.in_seconds('D') ? str.tostring(tf1) + 'm : ' + str.tostring(fastMaLen) + ':' + str.tostring(slowMaLen) : 
     str.tostring(tf1) + ' : ' + str.tostring(fastMaLen) + ':' + str.tostring(slowMaLen)
cell2Text = timeframe.in_seconds(tf2) < timeframe.in_seconds('D') ? str.tostring(tf2) + 'm : ' + str.tostring(fastMaLen) + ':' + str.tostring(slowMaLen) : 
     str.tostring(tf2) + ' : ' + str.tostring(fastMaLen) + ':' + str.tostring(slowMaLen)
cell3Text = timeframe.in_seconds(tf3) < timeframe.in_seconds('D') ? str.tostring(tf3) + 'm : ' + str.tostring(fastMaLen) + ':' + str.tostring(slowMaLen) : 
     str.tostring(tf3) + ' : ' + str.tostring(fastMaLen) + ':' + str.tostring(slowMaLen)
     
tf1CellColor = tf1FastMa > tf1SlowMa ? color.green : color.red
tf2CellColor = tf2FastMa > tf2SlowMa ? color.green : color.red
tf3CellColor = tf3FastMa > tf3SlowMa ? color.green : color.red

// plot the data
if barstate.islast
    maLabels.cell(0,0, ' ')
    maLabels.merge_cells(0,0,2,0)
    maLabels.cell(0,1, cell1Text, bgcolor = tf1CellColor)
    maLabels.cell(1,1, cell2Text, bgcolor = tf2CellColor)
    maLabels.cell(2,1, cell3Text, bgcolor = tf3CellColor)

//alerts
bullish = tf1FastMa > tf1SlowMa and tf2FastMa > tf2SlowMa and tf3FastMa > tf3SlowMa
bearish = tf1FastMa < tf1SlowMa and tf2FastMa < tf2SlowMa and tf3FastMa < tf3SlowMa

alertcondition((not bullish and bullish[1]) or (not bearish and bearish[1]), 'Mixed Moving Averages', 'Moving Averages No Longer Aligned')
alertcondition(bearish and not bearish[1], 'Bearish Moving Averages', 'Moving Averages on All Time Frames Aligned Bearish')

if bullish and not bullish[1]
    alert('Moving Averages on All Time Frames Aligned Bullish', alert.freq_once_per_bar_close)
if (not bearish and bearish[1]) or (not bullish and bullish[1])
    alert('Moving Averages No Longer Aligned', alert.freq_once_per_bar_close)
if bearish and not bearish[1]
    alert('Moving Averages on All Time Frames Aligned Bearish', alert.freq_once_per_bar_close)