Custom Moving Averages
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © gliderfund

//@version=5

indicator(title = "Custom Moving Averages", shorttitle = "MA Custom", overlay = true)

// #############################################
// #############################################
//            VERSION
// #############################################
// #############################################
// This is a useful indicator which allows you to plot multiple fully customized Moving Averages. Here are some of its features:
// [list]
// [*]Ability to fine-tune a wide variety of moving averages: smoothing type, periods, offsets, timeframes, sources, thickness, line/label color and text color.
// [*]Descriptive labels to avoid misreading.
// [*]Simple and well-organized Input Tab.
// [/list]
// ---------------------------------------------
// [list]
// [*]Ability to plot up to 7 Moving Averages
// [*]Offset can be positive or negative
// [/list]





// #############################################
// #############################################
//            LIBRARIES
// #############################################
// #############################################
import gliderfund/StapleIndicators/1 as com




// #############################################
// #############################################
//            INPUTS
// #############################################
// #############################################


// Custom MA #1
customMa1 = input.bool(defval = true, title = "MA #1:", group="Custom MA #1", inline = "custom1top")

customMode1 = input.string(defval = "Ema", title = "", options=["Sma", "Ema", "Dema", "Tema", "Wma", "Vwma", "Hma", "Lsma", "Rma", "Alma", "Tma", "Swma", "Dwma", "Smma", "Mav", "Zlema", "Azlema", "Jma", "Ssma", "All-Time"], tooltip = "", group = "Custom MA #1", inline = "custom1top")

inputTF1 = input.timeframe(defval = "", title = "TF", tooltip = "You're able to plot the MAs from a Higher Timeframe. With this feature, you could for instance draw the Daily SMA-100 on a 4-hour chart.\n\nBeware that you must select a higher timeframe than the current one in the chart. Plotting the MAs from lower timeframes could induce some calculation errors.\n\nPlease select 'Chart' to return back to the current selected timeframe at Tradingview toolbar.", group = "Custom MA #1", inline = "custom1top")
chartTF1 = inputTF1 == ""

period1 = input.int(defval = 21, title = "Period", minval = 2, step = 1, group = "Custom MA #1", inline = "custom1mid")

offset1 = input.int(defval = 0, title = "Offset", step = 1, group = "Custom MA #1", inline = "custom1mid")

src1 = input.source(defval = close, title = "Source", group = "Custom MA #1", inline = "custom1mid")

thickLine1 = input.int(defval = 2, title = "Line:   Thickness", minval = 1, step = 1, group = "Custom MA #1", inline = "custom1bottom")

colorMa1 = input.color(defval = #800080, title = "Color", tooltip = "", group = "Custom MA #1", inline = "custom1bottom")

colorText1 = input.color(defval = #FFFFFF, title = "Text", tooltip = "", group = "Custom MA #1", inline = "custom1bottom")



// Custom MA #2
customMa2 = input.bool(defval = true, title = "MA #2:", group="Custom MA #2", inline = "custom2top")

customMode2 = input.string(defval = "Sma", title = "", options=["Sma", "Ema", "Dema", "Tema", "Wma", "Vwma", "Hma", "Lsma", "Rma", "Alma", "Tma", "Swma", "Dwma", "Smma", "Mav", "Zlema", "Azlema", "Jma", "Ssma", "All-Time"], tooltip = "", group = "Custom MA #2", inline = "custom2top")

inputTF2 = input.timeframe(defval = "", title = "TF", tooltip = "You're able to plot the MAs from a Higher Timeframe. With this feature, you could for instance draw the Daily SMA-100 on a 4-hour chart.\n\nBeware that you must select a higher timeframe than the current one in the chart. Plotting the MAs from lower timeframes could induce some calculation errors.\n\nPlease select 'Chart' to return back to the current selected timeframe at Tradingview toolbar.", group = "Custom MA #2", inline = "custom2top")
chartTF2 = inputTF2 == ""

period2 = input.int(defval = 50, title = "Period", minval = 2, step = 1, group = "Custom MA #2", inline = "custom2mid")

offset2 = input.int(defval = 0, title = "Offset", step = 1, group = "Custom MA #2", inline = "custom2mid")

src2 = input.source(defval = close, title = "Source", group = "Custom MA #2", inline = "custom2mid")

thickLine2 = input.int(defval = 2, title = "Line:   Thickness", minval = 1, step = 1, group = "Custom MA #2", inline = "custom2bottom")

colorMa2 = input.color(defval = #008080, title = "Color", tooltip = "", group = "Custom MA #2", inline = "custom2bottom")

colorText2 = input.color(defval = #FFFFFF, title = "Text", tooltip = "", group = "Custom MA #2", inline = "custom2bottom")



// Custom MA #3
customMa3 = input.bool(defval = true, title = "MA #3:", group="Custom MA #3", inline = "custom3top")

customMode3 = input.string(defval = "Sma", title = "", options=["Sma", "Ema", "Dema", "Tema", "Wma", "Vwma", "Hma", "Lsma", "Rma", "Alma", "Tma", "Swma", "Dwma", "Smma", "Mav", "Zlema", "Azlema", "Jma", "Ssma", "All-Time"], tooltip = "", group = "Custom MA #3", inline = "custom3top")

inputTF3 = input.timeframe(defval = "", title = "TF", tooltip = "You're able to plot the MAs from a Higher Timeframe. With this feature, you could for instance draw the Daily SMA-100 on a 4-hour chart.\n\nBeware that you must select a higher timeframe than the current one in the chart. Plotting the MAs from lower timeframes could induce some calculation errors.\n\nPlease select 'Chart' to return back to the current selected timeframe at Tradingview toolbar.", group = "Custom MA #3", inline = "custom3top")
chartTF3 = inputTF3 == ""

period3 = input.int(defval = 200, title = "Period", minval = 2, step = 1, group = "Custom MA #3", inline = "custom3mid")

offset3 = input.int(defval = 0, title = "Offset", step = 1, group = "Custom MA #3", inline = "custom3mid")

src3 = input.source(defval = close, title = "Source", group = "Custom MA #3", inline = "custom3mid")

thickLine3 = input.int(defval = 2, title = "Line:   Thickness", minval = 1, step = 1, group = "Custom MA #3", inline = "custom3bottom")

colorMa3 = input.color(defval = #858500, title = "Color", tooltip = "", group = "Custom MA #3", inline = "custom3bottom")

colorText3 = input.color(defval = #FFFFFF, title = "Text", tooltip = "", group = "Custom MA #3", inline = "custom3bottom")



// Custom MA #4
customMa4 = input.bool(defval = false, title = "MA #4:", group="Custom MA #4", inline = "custom4top")

customMode4 = input.string(defval = "Sma", title = "", options=["Sma", "Ema", "Dema", "Tema", "Wma", "Vwma", "Hma", "Lsma", "Rma", "Alma", "Tma", "Swma", "Dwma", "Smma", "Mav", "Zlema", "Azlema", "Jma", "Ssma", "All-Time"], tooltip = "", group = "Custom MA #4", inline = "custom4top")

inputTF4 = input.timeframe(defval = "", title = "TF", tooltip = "You're able to plot the MAs from a Higher Timeframe. With this feature, you could for instance draw the Daily SMA-100 on a 4-hour chart.\n\nBeware that you must select a higher timeframe than the current one in the chart. Plotting the MAs from lower timeframes could induce some calculation errors.\n\nPlease select 'Chart' to return back to the current selected timeframe at Tradingview toolbar.", group = "Custom MA #4", inline = "custom4top")
chartTF4 = inputTF4 == ""

period4 = input.int(defval = 100, title = "Period", minval = 2, step = 1, group = "Custom MA #4", inline = "custom4mid")

offset4 = input.int(defval = 0, title = "Offset", step = 1, group = "Custom MA #4", inline = "custom4mid")

src4 = input.source(defval = close, title = "Source", group = "Custom MA #4", inline = "custom4mid")

thickLine4 = input.int(defval = 2, title = "Line:   Thickness", minval = 1, step = 1, group = "Custom MA #4", inline = "custom4bottom")

colorMa4 = input.color(defval = #FF8000, title = "Color", tooltip = "", group = "Custom MA #4", inline = "custom4bottom")

colorText4 = input.color(defval = #FFFFFF, title = "Text", tooltip = "", group = "Custom MA #4", inline = "custom4bottom")



// Custom MA #5
customMa5 = input.bool(defval = false, title = "MA #5:", group="Custom MA #5", inline = "custom5top")

customMode5 = input.string(defval = "All-Time", title = "", options=["Sma", "Ema", "Dema", "Tema", "Wma", "Vwma", "Hma", "Lsma", "Rma", "Alma", "Tma", "Swma", "Dwma", "Smma", "Mav", "Zlema", "Azlema", "Jma", "Ssma", "All-Time"], tooltip = "", group = "Custom MA #5", inline = "custom5top")

inputTF5 = input.timeframe(defval = "", title = "TF", tooltip = "You're able to plot the MAs from a Higher Timeframe. With this feature, you could for instance draw the Daily SMA-100 on a 4-hour chart.\n\nBeware that you must select a higher timeframe than the current one in the chart. Plotting the MAs from lower timeframes could induce some calculation errors.\n\nPlease select 'Chart' to return back to the current selected timeframe at Tradingview toolbar.", group = "Custom MA #5", inline = "custom5top")
chartTF5 = inputTF5 == ""

period5 = input.int(defval = 100, title = "Period", minval = 2, step = 1, group = "Custom MA #5", inline = "custom5mid")

offset5 = input.int(defval = 0, title = "Offset", step = 1, group = "Custom MA #5", inline = "custom5mid")

src5 = input.source(defval = close, title = "Source", group = "Custom MA #5", inline = "custom5mid")

thickLine5 = input.int(defval = 2, title = "Line:   Thickness", minval = 1, step = 1, group = "Custom MA #5", inline = "custom5bottom")

colorMa5 = input.color(defval = #008000, title = "Color", tooltip = "", group = "Custom MA #5", inline = "custom5bottom")

colorText5 = input.color(defval = #FFFFFF, title = "Text", tooltip = "", group = "Custom MA #5", inline = "custom5bottom")



// Custom MA #6
customMa6 = input.bool(defval = false, title = "MA #6:", group="Custom MA #6", inline = "custom6top")

customMode6 = input.string(defval = "Wma", title = "", options=["Sma", "Ema", "Dema", "Tema", "Wma", "Vwma", "Hma", "Lsma", "Rma", "Alma", "Tma", "Swma", "Dwma", "Smma", "Mav", "Zlema", "Azlema", "Jma", "Ssma", "All-Time"], tooltip = "", group = "Custom MA #6", inline = "custom6top")

inputTF6 = input.timeframe(defval = "", title = "TF", tooltip = "You're able to plot the MAs from a Higher Timeframe. With this feature, you could for instance draw the Daily SMA-100 on a 4-hour chart.\n\nBeware that you must select a higher timeframe than the current one in the chart. Plotting the MAs from lower timeframes could induce some calculation errors.\n\nPlease select 'Chart' to return back to the current selected timeframe at Tradingview toolbar.", group = "Custom MA #6", inline = "custom6top")
chartTF6 = inputTF6 == ""

period6 = input.int(defval = 5, title = "Period", minval = 2, step = 1, group = "Custom MA #6", inline = "custom6mid")

offset6 = input.int(defval = 0, title = "Offset", step = 1, group = "Custom MA #6", inline = "custom6mid")

src6 = input.source(defval = close, title = "Source", group = "Custom MA #6", inline = "custom6mid")

thickLine6 = input.int(defval = 2, title = "Line:   Thickness", minval = 1, step = 1, group = "Custom MA #6", inline = "custom6bottom")

colorMa6 = input.color(defval = #FF00FF, title = "Color", tooltip = "", group = "Custom MA #6", inline = "custom6bottom")

colorText6 = input.color(defval = #FFFFFF, title = "Text", tooltip = "", group = "Custom MA #6", inline = "custom6bottom")



// Custom MA #7
customMa7 = input.bool(defval = false, title = "MA #7:", group="Custom MA #7", inline = "custom7top")

customMode7 = input.string(defval = "Zlema", title = "", options=["Sma", "Ema", "Dema", "Tema", "Wma", "Vwma", "Hma", "Lsma", "Rma", "Alma", "Tma", "Swma", "Dwma", "Smma", "Mav", "Zlema", "Azlema", "Jma", "Ssma", "All-Time"], tooltip = "", group = "Custom MA #7", inline = "custom7top")

inputTF7 = input.timeframe(defval = "", title = "TF", tooltip = "You're able to plot the MAs from a Higher Timeframe. With this feature, you could for instance draw the Daily SMA-100 on a 4-hour chart.\n\nBeware that you must select a higher timeframe than the current one in the chart. Plotting the MAs from lower timeframes could induce some calculation errors.\n\nPlease select 'Chart' to return back to the current selected timeframe at Tradingview toolbar.", group = "Custom MA #7", inline = "custom7top")
chartTF7 = inputTF7 == ""

period7 = input.int(defval = 9, title = "Period", minval = 2, step = 1, group = "Custom MA #7", inline = "custom7mid")

offset7 = input.int(defval = 0, title = "Offset", step = 1, group = "Custom MA #7", inline = "custom7mid")

src7 = input.source(defval = close, title = "Source", group = "Custom MA #7", inline = "custom7mid")

thickLine7 = input.int(defval = 2, title = "Line:   Thickness", minval = 1, step = 1, group = "Custom MA #7", inline = "custom7bottom")

colorMa7 = input.color(defval = #0000FF, title = "Color", tooltip = "", group = "Custom MA #7", inline = "custom7bottom")

colorText7 = input.color(defval = #FFFFFF, title = "Text", tooltip = "", group = "Custom MA #7", inline = "custom7bottom")





// Labels
showLabel = input.bool(defval = true, title = "Show Labels",  tooltip = "Displays a Label to identify the lines", group = "Labels")



// MA Parameters
// Linear Regression
lrOffset = input.int(defval = 0, title = "Linear Regression: Offset", minval = 0, step = 1, group = "Parameters", inline = "parametersLR")

// Alma
almaOffset = input.float(defval = 0.85, title = "Alma: Offset", minval = 0, step = 1, group = "Parameters", inline = "parametersAlma")
almaSigma = input.int(defval = 6, title = "Sigma", minval = 0, step = 1, group = "Parameters", inline = "parametersAlma")

// Jma
jmaPhase = input.float(defval = 50, title = "Jma: Phase", minval = 0, step = 1, group = "Parameters", inline = "parametersJma")

// Azlema
azlemaMode = input.string(defval = "Cosine", title = "Azlema: Adaptative Mode", tooltip = "", options=["In-Phase & Quadrature", "Cosine", "Average"], group = "Parameters", inline = "parametersAzlema")




// #############################################
// #############################################
//            CALCULATION
// #############################################
// #############################################

ma1 = com.maCustom(customMode1, src1, period1, lrOffset, almaOffset, almaSigma, jmaPhase, azlemaMode)

ma2 = com.maCustom(customMode2, src2, period2, lrOffset, almaOffset, almaSigma, jmaPhase, azlemaMode)

ma3 = com.maCustom(customMode3, src3, period3, lrOffset, almaOffset, almaSigma, jmaPhase, azlemaMode)

ma4 = com.maCustom(customMode4, src4, period4, lrOffset, almaOffset, almaSigma, jmaPhase, azlemaMode)

ma5 = com.maCustom(customMode5, src5, period5, lrOffset, almaOffset, almaSigma, jmaPhase, azlemaMode)

ma6 = com.maCustom(customMode6, src6, period6, lrOffset, almaOffset, almaSigma, jmaPhase, azlemaMode)

ma7 = com.maCustom(customMode7, src7, period7, lrOffset, almaOffset, almaSigma, jmaPhase, azlemaMode)


maTF1 = request.security(syminfo.tickerid, inputTF1, ma1)
maTF2 = request.security(syminfo.tickerid, inputTF2, ma2)
maTF3 = request.security(syminfo.tickerid, inputTF3, ma3)
maTF4 = request.security(syminfo.tickerid, inputTF4, ma4)
maTF5 = request.security(syminfo.tickerid, inputTF5, ma5)
maTF6 = request.security(syminfo.tickerid, inputTF6, ma6)
maTF7 = request.security(syminfo.tickerid, inputTF7, ma7)





// #############################################
// #############################################
//            PLOT
// #############################################
// #############################################

// Custom MAs
plot(series = customMa1 ? maTF1 : na, title = "Custom MA #1", color = colorMa1, linewidth = thickLine1, style = plot.style_line, offset = offset1, editable = true)

plot(series = customMa2 ? maTF2 : na, title = "Custom MA #2", color = colorMa2, linewidth = thickLine2, style = plot.style_line, offset = offset2, editable = true)

plot(series = customMa3 ? maTF3 : na, title = "Custom MA #3", color = colorMa3, linewidth = thickLine3, style = plot.style_line, offset = offset3, editable = true)

plot(series = customMa4 ? maTF4 : na, title = "Custom MA #4", color = colorMa4, linewidth = thickLine4, style = plot.style_line, offset = offset4, editable = true)

plot(series = customMa5 ? maTF5 : na, title = "Custom MA #5", color = colorMa5, linewidth = thickLine5, style = plot.style_line, offset = offset5, editable = true)

plot(series = customMa6 ? maTF6 : na, title = "Custom MA #6", color = colorMa6, linewidth = thickLine6, style = plot.style_line, offset = offset6, editable = true)

plot(series = customMa7 ? maTF7 : na, title = "Custom MA #7", color = colorMa7, linewidth = thickLine7, style = plot.style_line, offset = offset7, editable = true)





// Label Vars
var label label1 = na
offsetText1 = offset1 == 0 ? "" : "x" + str.tostring(offset1)
textLabel1   = chartTF1 ? customMode1 + "-" + str.tostring(period1) + offsetText1 : customMode1 + "-" + str.tostring(period1) + offsetText1 + " (" + inputTF1 + ")"
seriesLabel1 = barstate.islast ? maTF1 : na
offsetLabel1 = offset1 + 1
colorLabel1  = colorMa1
colorTextLabel1 = colorText1
conditionLabel1 = showLabel and customMa1 and barstate.islast

if conditionLabel1
    label.delete(label1)
    label1 := label.new(x = bar_index + offsetLabel1, y = seriesLabel1, text = textLabel1, xloc = xloc.bar_index, yloc = yloc.price, color = colorLabel1, style = label.style_label_left, textcolor = colorTextLabel1, size = size.normal, textalign = text.align_center)



var label label2 = na
offsetText2 = offset2 == 0 ? "" : "x" + str.tostring(offset2)
textLabel2   = chartTF2 ? customMode2 + "-" + str.tostring(period2) + offsetText2 : customMode2 + "-" + str.tostring(period2) + offsetText2 + " (" + inputTF2 + ")"
seriesLabel2 = barstate.islast ? maTF2 : na
offsetLabel2 = offset2 + 1
colorLabel2  = colorMa2
colorTextLabel2 = colorText2
conditionLabel2 = showLabel and customMa2 and barstate.islast

if conditionLabel2
    label.delete(label2)
    label2 := label.new(x = bar_index + offsetLabel2, y = seriesLabel2, text = textLabel2, xloc = xloc.bar_index, yloc = yloc.price, color = colorLabel2, style = label.style_label_left, textcolor = colorTextLabel2, size = size.normal, textalign = text.align_center)



var label label3 = na
offsetText3 = offset3 == 0 ? "" : "x" + str.tostring(offset3)
textLabel3   = chartTF3 ? customMode3 + "-" + str.tostring(period3) + offsetText3 : customMode3 + "-" + str.tostring(period3) + offsetText3 + " (" + inputTF3 + ")"
seriesLabel3 = barstate.islast ? maTF3 : na
offsetLabel3 = offset3 + 1
colorLabel3  = colorMa3
colorTextLabel3 = colorText3
conditionLabel3 = showLabel and customMa3 and barstate.islast

if conditionLabel3
    label.delete(label3)
    label3 := label.new(x = bar_index + offsetLabel3, y = seriesLabel3, text = textLabel3, xloc = xloc.bar_index, yloc = yloc.price, color = colorLabel3, style = label.style_label_left, textcolor = colorTextLabel3, size = size.normal, textalign = text.align_center)



var label label4 = na
offsetText4 = offset4 == 0 ? "" : "x" + str.tostring(offset4)
textLabel4   = chartTF4 ? customMode4 + "-" + str.tostring(period4) + offsetText4 : customMode4 + "-" + str.tostring(period4) + offsetText4 + " (" + inputTF4 + ")"
seriesLabel4 = barstate.islast ? maTF4 : na
offsetLabel4 = offset4 + 1
colorLabel4  = colorMa4
colorTextLabel4 = colorText4
conditionLabel4 = showLabel and customMa4 and barstate.islast

if conditionLabel4
    label.delete(label4)
    label4 := label.new(x = bar_index + offsetLabel4, y = seriesLabel4, text = textLabel4, xloc = xloc.bar_index, yloc = yloc.price, color = colorLabel4, style = label.style_label_left, textcolor = colorTextLabel4, size = size.normal, textalign = text.align_center)




var label label5 = na
offsetText5 = offset5 == 0 ? "" : "x" + str.tostring(offset5)
textLabel5   = chartTF5 ? customMode5 + "-" + str.tostring(period5) + offsetText5 : customMode5 + "-" + str.tostring(period5) + offsetText5 + " (" + inputTF5 + ")"
seriesLabel5 = barstate.islast ? maTF5 : na
offsetLabel5 = offset5 + 1
colorLabel5  = colorMa5
colorTextLabel5 = colorText5
conditionLabel5 = showLabel and customMa5 and barstate.islast

if conditionLabel5
    label.delete(label5)
    label5 := label.new(x = bar_index + offsetLabel5, y = seriesLabel5, text = textLabel5, xloc = xloc.bar_index, yloc = yloc.price, color = colorLabel5, style = label.style_label_left, textcolor = colorTextLabel5, size = size.normal, textalign = text.align_center)




var label label6 = na
offsetText6 = offset6 == 0 ? "" : "x" + str.tostring(offset6)
textLabel6   = chartTF6 ? customMode6 + "-" + str.tostring(period6) + offsetText6 : customMode6 + "-" + str.tostring(period6) + offsetText6 + " (" + inputTF6 + ")"
seriesLabel6 = barstate.islast ? maTF6 : na
offsetLabel6 = offset6 + 1
colorLabel6  = colorMa6
colorTextLabel6 = colorText6
conditionLabel6 = showLabel and customMa6 and barstate.islast

if conditionLabel6
    label.delete(label6)
    label6 := label.new(x = bar_index + offsetLabel6, y = seriesLabel6, text = textLabel6, xloc = xloc.bar_index, yloc = yloc.price, color = colorLabel6, style = label.style_label_left, textcolor = colorTextLabel6, size = size.normal, textalign = text.align_center)




var label label7 = na
offsetText7 = offset7 == 0 ? "" : "x" + str.tostring(offset7)
textLabel7   = chartTF7 ? customMode7 + "-" + str.tostring(period7) + offsetText7 : customMode7 + "-" + str.tostring(period7) + offsetText7 + " (" + inputTF7 + ")"
seriesLabel7 = barstate.islast ? maTF7 : na
offsetLabel7 = offset7 + 1
colorLabel7  = colorMa7
colorTextLabel7 = colorText7
conditionLabel7 = showLabel and customMa7 and barstate.islast

if conditionLabel7
    label.delete(label7)
    label7 := label.new(x = bar_index + offsetLabel7, y = seriesLabel7, text = textLabel7, xloc = xloc.bar_index, yloc = yloc.price, color = colorLabel7, style = label.style_label_left, textcolor = colorTextLabel7, size = size.normal, textalign = text.align_center)

