Skip to content

Free TradingView indicator

MTF Trend Dashboard

Table showing EMA trend direction and RSI on five configurable timeframes, using closed bars only so values never repaint.

Multi-timeframev1.0TradingView (Pine Script v6) Non-repainting signals Alerts

What it does

The dashboard puts the trend of five timeframes in one small table on your chart. For each timeframe it shows whether the trend is up, down or mixed, based on two moving averages, plus the current RSI. A score row adds them up so you can see at a glance whether the timeframes agree.

How it works

For each timeframe the script requests the last closed bar's close, fast EMA, slow EMA and RSI, using lookahead off and a one-bar offset. That means every value comes from a completed bar of that timeframe and will not change later.

  • Up: close above the fast EMA and the fast EMA above the slow EMA.
  • Down: close below the fast EMA and the fast EMA below the slow EMA.
  • Mixed: anything else.

Each timeframe scores +1 for up, −1 for down and 0 for mixed. The score row shows the total from −5 to +5, and reads "All up" or "All down" when every timeframe agrees. The RSI cell is tinted green at 50 or above and red below 50.

The table is updated on the last bar only, so it adds very little load to the chart. Five data requests are used.

How to use it

  • A common approach is to trade in the direction of the higher timeframes and use the lower ones for timing. For example, only look for long setups on M15 when H4 and D are both up.
  • A score of +5 or −5 shows strong agreement. Scores near 0 suggest a range or a transition, where trend-following methods often struggle.
  • RSI adds a momentum read. Uptrends with RSI well above 50 on several timeframes show strong momentum; an uptrend with RSI drifting below 50 may be weakening. See the RSI and moving averages lessons.
  • Choose timeframes equal to or above your chart timeframe for the clearest results.

Alerts: all five timeframes turn up, all five turn down. They are checked on candle close.

Settings

InputDefaultWhat it changes
Timeframe 1-515, 60, 240, D, WTimeframes shown
Fast EMA20Fast trend average
Slow EMA50Slow trend average
RSI length14RSI period
Table positionTop rightPlacement
Text sizeSmallTable text size
Up / down / mixed colorsTeal / red / grayAppearance only

Limitations

Because only closed bars are used, the higher timeframes lag: the weekly row reflects last week's close until the new week ends. Historical bars can show values that are one higher-timeframe bar older than the live display, a side effect of avoiding lookahead. Choosing a timeframe lower than the chart timeframe gives less meaningful values. EMA trends lag at turning points, and agreement across timeframes does not guarantee the move will continue.

Pine Script source

In TradingView open Pine Editor, paste the code, click Save and then Add to chart.

FXP_MtfTrendDashboard.pine

98 lines

// © FXPIPS ONLINE — https://fxpips.online/tradingview-indicators/mtf-trend-dashboard/
// License: MIT. Educational tool — not financial advice. Trading involves substantial risk.
//@version=6
// Shows a table with the EMA trend direction and RSI on five configurable timeframes.
// Every request uses lookahead off and the previous (closed) bar of each timeframe, so
// values never change after the fact.
indicator("FXP MTF Trend Dashboard", shorttitle = "FXP MTF Trend", overlay = true)

// ── Inputs ─────────────────────────────────────────────────────────────
grpTf   = "Timeframes"
tf1     = input.timeframe("15", "Timeframe 1", group = grpTf)
tf2     = input.timeframe("60", "Timeframe 2", group = grpTf)
tf3     = input.timeframe("240", "Timeframe 3", group = grpTf)
tf4     = input.timeframe("D", "Timeframe 4", group = grpTf)
tf5     = input.timeframe("W", "Timeframe 5", group = grpTf)

grpCalc = "Calculation"
fastLen = input.int(20, "Fast EMA", minval = 1, group = grpCalc)
slowLen = input.int(50, "Slow EMA", minval = 2, group = grpCalc)
rsiLen  = input.int(14, "RSI length", minval = 2, group = grpCalc)

grpDisp = "Display"
posIn   = input.string("Top right", "Table position", options = ["Top right", "Top left", "Bottom right", "Bottom left", "Middle right"], group = grpDisp)
sizeIn  = input.string("Small", "Text size", options = ["Tiny", "Small", "Normal"], group = grpDisp)
colUp   = input.color(#26a69a, "Up", group = grpDisp)
colDn   = input.color(#ef5350, "Down", group = grpDisp)
colMix  = input.color(color.gray, "Mixed", group = grpDisp)

// ── Data (closed bars only) ────────────────────────────────────────────
getTf(string tf) =>
    [ef, es, r, c] = request.security(syminfo.tickerid, tf, [ta.ema(close, fastLen)[1], ta.ema(close, slowLen)[1], ta.rsi(close, rsiLen)[1], close[1]], lookahead = barmerge.lookahead_off)
    int dir = na(es) ? 0 : c > ef and ef > es ? 1 : c < ef and ef < es ? -1 : 0
    [dir, r]

[d1, r1] = getTf(tf1)
[d2, r2] = getTf(tf2)
[d3, r3] = getTf(tf3)
[d4, r4] = getTf(tf4)
[d5, r5] = getTf(tf5)

int score = d1 + d2 + d3 + d4 + d5

// ── Table ──────────────────────────────────────────────────────────────
tablePos = switch posIn
    "Top left"     => position.top_left
    "Bottom right" => position.bottom_right
    "Bottom left"  => position.bottom_left
    "Middle right" => position.middle_right
    => position.top_right

txtSize = switch sizeIn
    "Tiny"   => size.tiny
    "Normal" => size.normal
    => size.small

tfLabel(string tf) =>
    string t = tf == "" ? timeframe.period : tf
    int secs = timeframe.in_seconds(t)
    secs < 3600 ? str.tostring(secs / 60) + "m" : secs < 86400 ? str.tostring(secs / 3600) + "H" : t

dirText(int d) =>
    d == 1 ? "Up" : d == -1 ? "Down" : "Mixed"

dirColor(int d) =>
    d == 1 ? colUp : d == -1 ? colDn : colMix

rsiColor(float r) =>
    na(r) ? colMix : r >= 50 ? color.new(colUp, 30) : color.new(colDn, 30)

var table dash = table.new(tablePos, 3, 7, bgcolor = color.new(color.black, 20), frame_color = color.new(color.gray, 60), frame_width = 1, border_color = color.new(color.gray, 80), border_width = 1)

fillRow(int row, string tf, int d, float r) =>
    table.cell(dash, 0, row, tfLabel(tf), text_color = color.white, text_size = txtSize)
    table.cell(dash, 1, row, dirText(d), text_color = color.white, bgcolor = color.new(dirColor(d), 40), text_size = txtSize)
    table.cell(dash, 2, row, na(r) ? "-" : str.tostring(r, "#.0"), text_color = color.white, bgcolor = rsiColor(r), text_size = txtSize)
    true

if barstate.islast
    table.cell(dash, 0, 0, "TF", text_color = color.gray, text_size = txtSize)
    table.cell(dash, 1, 0, "Trend", text_color = color.gray, text_size = txtSize)
    table.cell(dash, 2, 0, "RSI", text_color = color.gray, text_size = txtSize)
    fillRow(1, tf1, d1, r1)
    fillRow(2, tf2, d2, r2)
    fillRow(3, tf3, d3, r3)
    fillRow(4, tf4, d4, r4)
    fillRow(5, tf5, d5, r5)
    int scoreDir = score == 5 ? 1 : score == -5 ? -1 : 0
    table.cell(dash, 0, 6, "Score", text_color = color.white, text_size = txtSize)
    table.cell(dash, 1, 6, (score > 0 ? "+" : "") + str.tostring(score) + " / 5", text_color = color.white, bgcolor = color.new(dirColor(scoreDir), 40), text_size = txtSize)
    table.cell(dash, 2, 6, scoreDir == 1 ? "All up" : scoreDir == -1 ? "All down" : "", text_color = color.white, text_size = txtSize)

// ── Alerts ─────────────────────────────────────────────────────────────
bool allUp   = barstate.isconfirmed and score == 5 and score[1] != 5
bool allDown = barstate.isconfirmed and score == -5 and score[1] != -5

alertcondition(allUp, "All timeframes up", "{{ticker}}: all five timeframes are in an up trend")
alertcondition(allDown, "All timeframes down", "{{ticker}}: all five timeframes are in a down trend")

Key inputs

Key inputs of MTF Trend Dashboard
InputDefaultDescription
Timeframes 1-515m, 1H, 4H, D, WThe five timeframes shown in the table.
Fast EMA20Fast moving average used for trend direction.
Slow EMA50Slow moving average used for trend direction.
RSI length14RSI period shown for each timeframe.
Table positionTop rightWhere the dashboard sits on the chart.

Educational tools, not advice. Indicators and Expert Advisors describe price; they do not predict it, and past behaviour does not guarantee future results. Test everything on a demo account first and never risk money you cannot afford to lose. See our disclaimer.

Keep exploring

Related tradingview indicators