Trend and Momentum Dashboard
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Lantzwat
//@version=5
indicator('Trend and Momentum Dashboard', "TMD", max_bars_back = 5000)
// ... based on Fibonacci levels

SetTFperiod(tf,b ) =>
    setper = tf == 'M' ? 6 : tf == 'W' ? 12 : tf=="2D"? 12: tf == 'D' ? 20 : tf == '240' ? 28 : tf == '180' ? 28 : tf == '120' ? 32 : tf == '60' ? 36 : tf == '45' ? 36 : tf == '30' ? 42 : tf == '15' ? 42 : tf == '5' ? 48 : tf == '3' ? 60 : tf == '1' ? 60 : 20
    if b == true
        // calculation taken from Dynamic RSI Momentum (DRM Strategy) by QuantNomad
        mlen = 10
        dsrc = close
        mVal = dsrc - dsrc[mlen]
        // Calculation Price vs Momentum
        dcorr  = ta.correlation(dsrc, mVal, mlen)
        dcorr := dcorr > 1 or dcorr < -1 ? float(na) : dcorr
        var dLen = 0
        min_d = int(setper/2)  
        max_d = int(setper * 1.5) 
        setper := int(min_d + nz(math.round((1 - dcorr) * (max_d-min_d) / 2, 0), 0))
    setper

lw          = input(25,"Linewidth")
bcolor      = input.bool(true, "5 color vs 3 color")
bbar        = input.bool(true,"Background - last bar in period vs trading zones")
baseline    = input.int(1, "Bullish/Bearish threshold")

bDyn = true
len = SetTFperiod(timeframe.period, bDyn)

//Tickers = "SPY;XLY;XLC;XLK;XLRE;XLP;XLV;XLF;XLB;XLU;XLI;XLE;IYT"
//Descriptions="S&P500;Consumer Discretionary;Communication;Technology;Real Estate;Consumer Staples;Health Care;Financials;Materials;Utilities;Industrials;Energy;Transport"

tick0 = input.string("SPY", inline="0")
descr0 = input.string("S&P500", inline="0")
tick1 = input.string("XLY", inline="1")
descr1 = input.string("Consumer Discretionary", inline="1")
tick2 = input.string("XLC", inline="2")
descr2 = input.string("Communication", inline="2")
tick3 = input.string("XLK", inline="3")
descr3 = input.string("Technology", inline="3")
tick4 = input.string("XLRE", inline="4")
descr4 = input.string("Real Estate", inline="4")
tick5 = input.string("XLP", inline="5")
descr5 = input.string("Consumer Staples", inline="5")
tick6 = input.string("XLV", inline="6")
descr6 = input.string("Health Care", inline="6")
tick7 = input.string("XLF", inline="7")
descr7 = input.string("Financials", inline="7")
tick8 = input.string("XLB", inline="8")
descr8 = input.string("Materials", inline="8")
tick9 = input.string("XLU", inline="9")
descr9 = input.string("Utilities", inline="9")
tick10 = input.string("XLI", inline="10")
descr10 = input.string("Industrials", inline="10")
tick11 = input.string("XLE", inline="11")
descr11 = input.string("Energy", inline="11")
tick12 = input.string("IYT", inline="12")
descr12 = input.string("Transport", inline="12")

_label(float yPosition, string Name) =>     
    var TEXTCOLOR = color.new(color.white,50)     
    if barstate.islast          
        var _label = label.new(bar_index, y=yPosition, text=Name, color=color.new(color.white, 100), textcolor=TEXTCOLOR, style=label.style_label_left, size=size.small, textalign=text.align_left, text_font_family=font.family_monospace)          
        label.set_x(_label, bar_index) 

// ====================================================================================================================================================================================================
// Helper functions because of Series int and Simple int issue in Pinescript
// Script Functions Allowing Series As Length - PineCoders FAQ
// @author=alexgrover, for PineCoders

Ema2(src,p) =>
    ema = 0.
    sf = 2/(p+1)
    ema := nz(ema[1] + sf*(src - ema[1]),src)

Atr2(p) =>
    atr = 0.
    Tr = math.max(high,close[1]) - math.min(low,close[1])
    atr := nz(atr[1] + (Tr - atr[1])/p,Tr)

/// ----------------------------------------------------------------------------------------------------------------------------------
// Fibonacci calculation is a modified version of eykpunters "Fibonacci Zone Oscillator With MACD Histogram"
CalcFibRange(sec) =>
    //Calculate Donchian Channel
    per = SetTFperiod(timeframe.period, bDyn)
    src_close = request.security(sec, timeframe.period, close)
    src_high = request.security(sec, timeframe.period, high)
    src_low = request.security(sec, timeframe.period, low)

    hl      = ta.highest(src_high,per) //High Line (Border)
    ll      = ta.lowest(src_low,per)   //Low Line  (Border)
    
    varwidth = math.round(2 + per / 25 - 6 / per, 1)
    dis = Atr2(per)

    //Calculate Fibonacci levels
    don     =   hl - ll          //range of the Donchian channel 
    hf      =   hl - don * 0.236    //Highest Fibonacci line
    cfh     =   hl - don * 0.382    //Center High Fibonacci line
    cfl     =   hl - don * 0.618    //Center Low Fibonacci line
    lf      =   hl - don * 0.786    //Lowest Fibonacci line 0.764

    ohf      =   cfh + varwidth * dis
    llf      =   cfl - varwidth * dis

    //Calculate relative position of close
    poshigh  =  src_close > ohf
    posup    =  src_close <= ohf and src_close >= hf  //in uptrend area
    posabove =  src_close <= hf  and src_close > cfh  //in prudent buyers area
    posmiddle=  src_close <= cfh and src_close > cfl  //in center area
    posunder =  src_close <= cfl and src_close > lf   //in prudent sellers area
    posdown  =  src_close <= lf  and src_close > llf  //in downtrend area
    poslow   =  src_close < llf

    fibrange = poshigh? 2: posup? 2: posabove? 1: posmiddle ? 0: posunder? -1: posdown? -2: 0

    if sec == ""
        fibrange := 0

    fibrange


FibColoring(fibrange, postransp) =>
    fibcolor = color.gray
    if bcolor 
        fibcolor := fibrange == 3 ? color.new(color.navy, postransp): fibrange == 2 ? color.new(color.blue,postransp): fibrange == 1 ? color.new(color.rgb(128, 194, 248),postransp): fibrange == 0 ? color.new(color.gray,postransp): fibrange == -1 ? color.new(color.rgb(250, 149, 149),postransp): fibrange == -2 ? color.new(color.red,postransp): color.new(color.maroon, postransp)
    else
        fibcolor := fibrange == 3 ? color.new(color.navy, postransp): fibrange == 2 ? color.new(color.blue,postransp): fibrange == 1 ? color.new(color.blue,postransp): fibrange == 0 ? color.new(color.gray,90): fibrange == -1 ? color.new(color.red,postransp): fibrange == -2 ? color.new(color.red,postransp): color.new(color.maroon, postransp)
    fibcolor

/// ----------------------------------------------------------------------------------------------------------------------------------

// initializing
ps = plot.style_stepline
pos = 00
fib = 0
fibrange = 0
col = color.red

// Calculation and plotting starts here ....

pos := pos - 10
fibrange := CalcFibRange(tick0)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr0)

pos := pos - 10
fibrange := CalcFibRange(tick1)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr1)

pos := pos - 10
fibrange := CalcFibRange(tick2)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr2)

pos := pos - 10
fibrange := CalcFibRange(tick3)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr3)

pos := pos - 10
fibrange := CalcFibRange(tick4)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr4)

pos := pos - 10
fibrange := CalcFibRange(tick5)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr5)

pos := pos - 10
fibrange := CalcFibRange(tick6)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr6)

pos := pos - 10
fibrange := CalcFibRange(tick7)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr7)

pos := pos - 10
fibrange := CalcFibRange(tick8)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr8)

pos := pos - 10
fibrange := CalcFibRange(tick9)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr9)

pos := pos - 10
fibrange := CalcFibRange(tick10)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr10)

pos := pos - 10
fibrange := CalcFibRange(tick11)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr11)

pos := pos - 10
fibrange := CalcFibRange(tick12)
col := FibColoring(fibrange,20)
fib := fib + fibrange
plot(pos, linewidth=lw, style=ps, color=col)
_label(pos, descr12)

/// ----------------------------------------------------------------------------------------------------------------------------------

// Plot trading zones - sum of all fibonacci levels ...
fibcol = fib > baseline ? color.blue : color.red
plot(5, color = fib > baseline ? color.blue : color.red, style=ps, linewidth = lw / 4)
bgcolor(not bbar ? color.new(fibcol, 70) : na)

/// ----------------------------------------------------------------------------------------------------------------------------------
// Highlight last bar in period
tf = timeframe.period
period = tf=="M"? "W": tf=="W"? "D": tf=="D"? "W": tf=="240"? "D": tf=="180"? "D": tf=="120"? "D": tf=="60"? "D": tf=="30"? "D": tf=="15"? "D": tf=="5"? "60": tf=="3"? "60": tf=="1"? "60": "W"
is_newbar(res) =>
    t = time(res)
    ta.change(t) != 0 ? 1 : 0
bgcolor(is_newbar(period) == 1 and bbar ? color.new(color.gray,96) : na, offset=-1)


