SPDR Tracker
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © syntaxgeek

//@version=5
indicator("SPDR Tracker", "SpdrT")
import TradingView/ta/5

// { consts
c_tableStyle_vertical = "Vertical"
c_tableStyle_horizontal = "Horizontal"

c_sym1 = "XLF"
c_sym2 = "XLK"
c_sym3 = "XLV"
c_sym4 = "XLY"
c_sym5 = "XLP"
c_sym6 = "XLI"
c_sym7 = "XLU"
c_sym8 = "XLC"
c_sym9 = "XLB"
c_sym10 = "XLRE"
c_sym11 = "XLE"

c_mode_sma = "SMA"
c_mode_ema = "EMA"
c_mode_hma = "HMA"
c_mode_vwma = "VWMA"
c_mode_swma = "SWMA"
c_mode_alma = "ALMA"
c_mode_median = "Median"
c_mode_bbw = "BBW"
c_mode_kcw = "KCW"
c_mode_rsi = "RSI"
c_mode_atr = "ATR"
c_mode_cci = "CCI"
c_mode_mfi = "MFI"
c_mode_change = "Change"
c_mode_linreg = "LinReg"
c_mode_vwap = "VWAP"
c_mode_wpr = "WPR"
c_mode_roc = "ROC"
c_mode_adr = "ADR"
c_mode_cog = "COG"
c_mode_cmo = "CMO"
c_mode_dev = "DEV"
// } consts

// { inputs

i_symColor = input.color(color.white, "Symbol", inline="sym", group="Symbols")
i_symEnabled = input.bool(true, "", inline="sym", group="Symbols")

i_sym1Color = input.color(color.gray, "Financial (XLF)", inline="sym1", group="Symbols")
i_sym1Enabled = input.bool(true, "", inline="sym1", group="Symbols")
i_sym2Color = input.color(color.aqua, "Technology (XLK)", inline="sym2", group="Symbols")
i_sym2Enabled = input.bool(true, "", inline="sym2", group="Symbols")
i_sym3Color = input.color(color.blue, "Health Care (XLV)", inline="sym3", group="Symbols")
i_sym3Enabled = input.bool(true, "", inline="sym3", group="Symbols")
i_sym4Color = input.color(color.navy, "Consumer Discretionary (XLY)", inline="sym4", group="Symbols")
i_sym4Enabled = input.bool(true, "", inline="sym4", group="Symbols")
i_sym5Color = input.color(color.purple, "Consumer Staples (XLP)", inline="sym5", group="Symbols")
i_sym5Enabled = input.bool(true, "", inline="sym5", group="Symbols")
i_sym6Color = input.color(color.maroon, "Industrial (XLI)", inline="sym6", group="Symbols")
i_sym6Enabled = input.bool(true, "", inline="sym6", group="Symbols")
i_sym7Color = input.color(color.fuchsia, "Utilities (XLU)", inline="sym7", group="Symbols")
i_sym7Enabled = input.bool(true, "", inline="sym7", group="Symbols")
i_sym8Color = input.color(color.red, "Communication Services (XLC)", inline="sym8", group="Symbols")
i_sym8Enabled = input.bool(true, "", inline="sym8", group="Symbols")
i_sym9Color = input.color(color.yellow, "Materials (XLB)", inline="sym9", group="Symbols")
i_sym9Enabled = input.bool(true, "", inline="sym9", group="Symbols")
i_sym10Color = input.color(color.orange, "Real-Estate (XLRE)", inline="sym10", group="Symbols")
i_sym10Enabled = input.bool(true, "", inline="sym10", group="Symbols")
i_sym11Color = input.color(color.green, "Energy (XLE)", inline="sym11", group="Symbols")
i_sym11Enabled = input.bool(true, "", inline="sym11", group="Symbols")

i_mode = input.string("SMA", "Mode", options=[c_mode_sma, c_mode_ema, c_mode_hma, c_mode_vwma, c_mode_swma, c_mode_alma, c_mode_median, c_mode_bbw, c_mode_kcw, c_mode_rsi, c_mode_atr, c_mode_cci, c_mode_mfi, c_mode_change, c_mode_linreg, c_mode_vwap, c_mode_wpr, c_mode_roc, c_mode_adr, c_mode_cog, c_mode_cmo, c_mode_dev], inline="Mode", group="Presentation")
i_modeLength = input.int(20, "Length", minval=1, step=1, inline="Mode", group="Presentation", tooltip="Only applies to certain modes, VWAP not included.")
i_modeSource = input.source(close, "Source", inline="Mode", group="Presentation", tooltip="Will be the source for the mode if applicable, not all modes use source (such as " + c_mode_atr + ")")
i_modeVWAPAnchor = input.string("Month", "Anchor", options=["Session", "Week", "Month", "Quarter", "Year", "Decade", "Century", "Earnings", "Dividends", "Splits"], tooltip="Only applies to VWAP")

i_tableStyle = input.string(c_tableStyle_horizontal, "Style", options=[c_tableStyle_vertical, c_tableStyle_horizontal], group="Info Table")

v_modeVWAPAnchor = switch i_modeVWAPAnchor
	"Session"   => timeframe.change("D")
	"Week"      => timeframe.change("W")
	"Month"     => timeframe.change("M")
	"Quarter"   => timeframe.change("3M")
	"Year"      => timeframe.change("12M")
	"Decade"    => timeframe.change("12M") and year % 10 == 0
	"Century"   => timeframe.change("12M") and year % 100 == 0
	=> false
// } inputs

// { funcs
f_symDataMode() =>
    switch(i_mode)
        c_mode_sma => ta.sma(i_modeSource, i_modeLength)
        c_mode_ema => ta.ema(i_modeSource, i_modeLength)
        c_mode_hma => ta.hma(i_modeSource, i_modeLength)
        c_mode_vwma => ta.vwma(i_modeSource, i_modeLength)
        c_mode_swma => ta.swma(i_modeSource)
        c_mode_median => ta.median(i_modeSource, i_modeLength)
        c_mode_bbw => ta.bbw(i_modeSource, i_modeLength, 2)
        c_mode_kcw => ta.kcw(i_modeSource, i_modeLength, 2, true)
        c_mode_rsi => ta.rsi(i_modeSource, i_modeLength)
        c_mode_atr => ta.atr(i_modeLength)
        c_mode_cci => ta.cci(i_modeSource, i_modeLength)
        c_mode_mfi => ta.mfi(i_modeSource, i_modeLength)
        c_mode_change => ta.change(i_modeSource, i_modeLength)
        c_mode_linreg => ta.linreg(i_modeSource, i_modeLength, 0)
        c_mode_vwap => ta.vwap(i_modeSource, v_modeVWAPAnchor)
        c_mode_wpr => ta.wpr(i_modeLength)
        c_mode_roc => ta.roc(i_modeSource, i_modeLength)
        c_mode_adr => ta.sma(high, i_modeLength) - ta.sma(low, i_modeLength)
        c_mode_cog => ta.cog(i_modeSource, i_modeLength)
        c_mode_cmo => ta.cmo(i_modeSource, i_modeLength)
        c_mode_dev => ta.dev(i_modeSource, i_modeLength)
        c_mode_alma => ta.alma(i_modeSource, i_modeLength, 0.85, 6)

f_getSymData(_sym) => request.security(ticker.modify(_sym, session=session.extended), timeframe.period, [f_symDataMode(), volume, ta.change(close, 1)])

f_addTableSymbolStat(_table, _sym, _symColor, _symModeValue, _symChange, _symVolume, _symTooltip, _positionX, _positionY) =>
    v_symTooltip = _symTooltip + " (" + i_mode + ", Price Change, Volume)"
    v_symStat = _sym + " (" + str.tostring(_symModeValue, format.mintick) + ", " + str.tostring(_symChange, format.mintick) + ", " + str.tostring(_symVolume, format.volume) + ")"

    table.cell(_table, _positionX, _positionY, v_symStat, bgcolor=color.white, tooltip=v_symTooltip, text_halign=text.align_left, text_size=size.small)
    table.cell(_table, _positionX + 1, _positionY, bgcolor=_symColor, width=0.5, tooltip=v_symTooltip)
    table.cell(_table, _positionX + 2, _positionY)

f_createStatsTable() =>
    if i_tableStyle == c_tableStyle_horizontal
        table.new(position.bottom_center, 37, 2)
    else
        table.new(position.top_left, 4, 13)
// } funcs

// { vars
[_sym1ModeValue, _sym1Volume, _sym1Change] = f_getSymData(c_sym1)
[_sym2ModeValue, _sym2Volume, _sym2Change] = f_getSymData(c_sym2)
[_sym3ModeValue, _sym3Volume, _sym3Change] = f_getSymData(c_sym3)
[_sym4ModeValue, _sym4Volume, _sym4Change] = f_getSymData(c_sym4)
[_sym5ModeValue, _sym5Volume, _sym5Change] = f_getSymData(c_sym5)
[_sym6ModeValue, _sym6Volume, _sym6Change] = f_getSymData(c_sym6)
[_sym7ModeValue, _sym7Volume, _sym7Change] = f_getSymData(c_sym7)
[_sym8ModeValue, _sym8Volume, _sym8Change] = f_getSymData(c_sym8)
[_sym9ModeValue, _sym9Volume, _sym9Change] = f_getSymData(c_sym9)
[_sym10ModeValue, _sym10Volume, _sym10Change] = f_getSymData(c_sym10)
[_sym11ModeValue, _sym11Volume, _sym11Change] = f_getSymData(c_sym11)
[_symModeValue, _symVolume, _symChange] = f_getSymData(syminfo.tickerid)

var v_statsTable = f_createStatsTable()

f_addTableSymbolStat(v_statsTable, c_sym1, i_sym1Color, _sym1ModeValue, _sym1Change, _sym1Volume, "Financial", i_tableStyle == c_tableStyle_vertical ? 1 : 1, i_tableStyle == c_tableStyle_vertical ? 1 : 1)
f_addTableSymbolStat(v_statsTable, c_sym2, i_sym2Color, _sym2ModeValue, _sym2Change, _sym2Volume, "Technology", i_tableStyle == c_tableStyle_vertical ? 1 : 1 + 3, i_tableStyle == c_tableStyle_vertical ? 2 : 1)
f_addTableSymbolStat(v_statsTable, c_sym3, i_sym3Color, _sym3ModeValue, _sym3Change, _sym3Volume, "Health Care", i_tableStyle == c_tableStyle_vertical ? 1 : 1 + 6, i_tableStyle == c_tableStyle_vertical ? 3 : 1)
f_addTableSymbolStat(v_statsTable, c_sym4, i_sym4Color, _sym4ModeValue, _sym4Change, _sym4Volume, "Consumer Discretionary", i_tableStyle == c_tableStyle_vertical ? 1 : 1 + 9, i_tableStyle == c_tableStyle_vertical ? 4 : 1)
f_addTableSymbolStat(v_statsTable, c_sym5, i_sym5Color, _sym5ModeValue, _sym5Change, _sym5Volume, "Consumer Staples", i_tableStyle == c_tableStyle_vertical ? 1 : 1 + 12, i_tableStyle == c_tableStyle_vertical ? 5 : 1)
f_addTableSymbolStat(v_statsTable, c_sym6, i_sym6Color, _sym6ModeValue, _sym6Change, _sym6Volume, "Industrial", i_tableStyle == c_tableStyle_vertical ? 1 : 1 + 15, i_tableStyle == c_tableStyle_vertical ? 6 : 1)
f_addTableSymbolStat(v_statsTable, c_sym7, i_sym7Color, _sym7ModeValue, _sym7Change, _sym7Volume, "Utilities", i_tableStyle == c_tableStyle_vertical ? 1 : 1 + 18, i_tableStyle == c_tableStyle_vertical ? 7 : 1)
f_addTableSymbolStat(v_statsTable, c_sym8, i_sym8Color, _sym8ModeValue, _sym8Change, _sym8Volume, "Communication Services", i_tableStyle == c_tableStyle_vertical ? 1 : 1 + 21, i_tableStyle == c_tableStyle_vertical ? 8 : 1)
f_addTableSymbolStat(v_statsTable, c_sym9, i_sym9Color, _sym9ModeValue, _sym9Change, _sym9Volume, "Materials", i_tableStyle == c_tableStyle_vertical ? 1 : 1 + 24, i_tableStyle == c_tableStyle_vertical ? 9 : 1)
f_addTableSymbolStat(v_statsTable, c_sym10, i_sym10Color, _sym10ModeValue, _sym10Change, _sym10Volume, "Real-Estate", i_tableStyle == c_tableStyle_vertical ? 1 : 1 + 27, i_tableStyle == c_tableStyle_vertical ? 10 : 1)
f_addTableSymbolStat(v_statsTable, c_sym11, i_sym11Color, _sym11ModeValue, _sym11Change, _sym11Volume, "Energy", i_tableStyle == c_tableStyle_vertical ? 1 : 1 + 30, i_tableStyle == c_tableStyle_vertical ? 11 : 1)
f_addTableSymbolStat(v_statsTable, syminfo.ticker, i_symColor, _symModeValue, _symChange, _symVolume, syminfo.description, i_tableStyle == c_tableStyle_vertical ? 1 : 1 + 33, i_tableStyle == c_tableStyle_vertical ? 12 : 1)

v_style = plot.style_line

// } vars

// { plots
plot(i_sym1Enabled ? _sym1ModeValue : na, c_sym1, color=i_sym1Color, style=v_style)
plot(i_sym2Enabled ? _sym2ModeValue : na, c_sym2, color=i_sym2Color, style=v_style)
plot(i_sym3Enabled ? _sym3ModeValue : na, c_sym3, color=i_sym3Color, style=v_style)
plot(i_sym4Enabled ? _sym4ModeValue : na, c_sym4, color=i_sym4Color, style=v_style)
plot(i_sym5Enabled ? _sym5ModeValue : na, c_sym5, color=i_sym5Color, style=v_style)
plot(i_sym6Enabled ? _sym6ModeValue : na, c_sym6, color=i_sym6Color, style=v_style)
plot(i_sym7Enabled ? _sym7ModeValue : na, c_sym7, color=i_sym7Color, style=v_style)
plot(i_sym8Enabled ? _sym8ModeValue : na, c_sym8, color=i_sym8Color, style=v_style)
plot(i_sym9Enabled ? _sym9ModeValue : na, c_sym9, color=i_sym9Color, style=v_style)
plot(i_sym10Enabled ? _sym10ModeValue : na, c_sym10, color=i_sym10Color, style=v_style)
plot(i_sym11Enabled ? _sym11ModeValue : na, c_sym11, color=i_sym11Color, style=v_style)
plot(i_symEnabled ? _symModeValue : na, "Sym", color=i_symColor, style=v_style, linewidth=2)

// rsi plots
p_upperRSIBand = hline(70, 'Upper Band', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_rsi ? display.all : display.none)
hline(50, 'Middle Band', color.new(color.gray, 50), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_rsi ? display.all : display.none)
p_lowerRSIBand = hline(30, 'Lower Band', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_rsi ? display.all : display.none)
fill(p_upperRSIBand, p_lowerRSIBand, color=color.new(color.gray, 90), editable=false, display=i_mode == c_mode_rsi ? display.all : display.none)

// cci plots
p_upperCCIBand = hline(100, 'Upper Band', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_cci ? display.all : display.none)
hline(0, 'Middle Band', color.new(color.gray, 50), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_cci ? display.all : display.none)
p_lowerCCIBand = hline(-100, 'Lower Band', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_cci ? display.all : display.none)
fill(p_upperCCIBand, p_lowerCCIBand, color=color.new(color.gray, 90), editable=false, display=i_mode == c_mode_cci ? display.all : display.none)

// mfi plots
p_upperMFIBand = hline(80, 'Overbought', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_mfi ? display.all : display.none)
hline(50, 'Middle Band', color.new(color.gray, 50), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_mfi ? display.all : display.none)
p_lowerMFIBand = hline(20, 'Oversold', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_mfi ? display.all : display.none)
fill(p_upperMFIBand, p_lowerMFIBand, color=color.new(color.gray, 90), editable=false, display=i_mode == c_mode_mfi ? display.all : display.none)

// wpr plots
p_upperWPRBand = hline(-20, 'Upper Band', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_wpr ? display.all : display.none)
hline(-50, 'Middle Band', color.new(color.gray, 50), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_wpr ? display.all : display.none)
p_lowerWPRBand = hline(-80, 'Lower Band', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_wpr ? display.all : display.none)
fill(p_upperWPRBand, p_lowerWPRBand, color=color.new(color.gray, 90), editable=false, display=i_mode == c_mode_wpr ? display.all : display.none)

// roc plot
hline(0, 'Zero Line', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_roc ? display.all : display.none)

// cmo plot
hline(0, 'Zero Line', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_cmo ? display.all : display.none)

// change plot
hline(0, 'Zero Line', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_change ? display.all : display.none)

// bbw plot
hline(0, 'Zero Line', color.new(color.gray, 0), hline.style_dashed, 1, editable=false, display=i_mode == c_mode_bbw ? display.all : display.none)
// } plots