Indicator · Pine Script v6 · Own pane

MTF Trend Alignment Dashboard [WavesUnchained]

by casoon

This indicator scores trend alignment across the chart timeframe and three configurable higher timeframes.

View on GitHub

GitHub stars9on the repository
Pine versionv6current
Lines of code370
Settings12inputs
LicenceMIT
Last update3 days ago27 Oct 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

370 lines of Pine Script v6 from archive/indicators/mtf_trend_alignment/mtf_trend_alignment.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

mtf_trend_alignment.pine
//@version=6
// ============================================================================
// MTF Trend Alignment Dashboard [WavesUnchained]
// Version: 1.0.0
// Author: WavesUnchained
// Build: 2026-02-23 00:00:00
// ============================================================================
// Scores trend alignment across up to four timeframes using Supertrend and
// volatility regime classification, combining results into a 0–100 confluence score.
//
// Features:
//   ✓ Four timeframe analysis (current + three configurable HTFs)
//   ✓ Supertrend direction and strength per timeframe
//   ✓ Volatility regime classification per timeframe
//   ✓ Overall alignment score (0–100)
//   ✓ Visual trend matrix dashboard
//   ✓ Entry quality signals from cross-timeframe confluence
//
// ============================================================================

indicator("MTF Trend Alignment Dashboard [WavesUnchained]", "📊 MTF Alignment", overlay=false, max_boxes_count=50)

import WavesUnchained/RTAFramework/1 as RTA

// ============================================================================
// USER INPUTS
// ============================================================================

// --- Timeframe Settings ---
var g1 = "⏰ Timeframes"
timeframe1 = input.timeframe("60", "HTF 1", group=g1)
timeframe2 = input.timeframe("240", "HTF 2", group=g1)
timeframe3 = input.timeframe("D", "HTF 3", group=g1)

// --- Supertrend Settings ---
var g2 = "📈 Supertrend"
stFactor = input.float(3.0, "Factor", minval=1.0, maxval=10.0, step=0.1, group=g2)
stLength = input.int(10, "ATR Length", minval=5, maxval=50, group=g2)

// --- Volatility Regime ---
var g3 = "💨 Volatility"
enableVolatility = input.bool(true, "Show Volatility Regime", group=g3)
volLookback = input.int(100, "Lookback Period", minval=20, maxval=500, group=g3)

// --- Alignment Scoring ---
var g4 = "🎯 Alignment"
minAlignmentScore = input.int(75, "Min Score for Signal", minval=0, maxval=100, group=g4)
requireAllAligned = input.bool(false, "Require All Timeframes", group=g4)

// --- Display ---
var g5 = "🎨 Display"
showMatrix = input.bool(true, "Show Trend Matrix", group=g5)
showScorePlot = input.bool(true, "Plot Alignment Score", group=g5)
dashboardSize = input.string("normal", "Dashboard Size",
     options=["tiny", "small", "normal", "large"], group=g5)

// ============================================================================
// CALCULATE LOCAL TIMEFRAME
// ============================================================================

var ltfRegime = RTA.newVolatilityRegime()
RTA.updateVolatilityRegime(ltfRegime, 14, volLookback)

ltfConfig = RTA.newSupertrendConfig(stFactor, stLength)
[ltfLine, ltfDir] = RTA.calculateSupertrend(ltfConfig)

ltfTrend = ltfDir == 1 ? "BULLISH" : "BEARISH"
ltfColor = ltfDir == 1 ? color.new(color.green, 0) : color.new(color.red, 0)

// ============================================================================
// CALCULATE HIGHER TIMEFRAMES
// ============================================================================

// HTF 1
htf1Dir = request.security(syminfo.tickerid, timeframe1,
    RTA.getSupertrendDirection(stFactor, stLength),
    lookahead=barmerge.lookahead_off)
htf1Trend = htf1Dir == 1 ? "BULLISH" : "BEARISH"
htf1Color = htf1Dir == 1 ? color.new(color.green, 0) : color.new(color.red, 0)

// HTF 2
htf2Dir = request.security(syminfo.tickerid, timeframe2,
    RTA.getSupertrendDirection(stFactor, stLength),
    lookahead=barmerge.lookahead_off)
htf2Trend = htf2Dir == 1 ? "BULLISH" : "BEARISH"
htf2Color = htf2Dir == 1 ? color.new(color.green, 0) : color.new(color.red, 0)

// HTF 3
htf3Dir = request.security(syminfo.tickerid, timeframe3,
    RTA.getSupertrendDirection(stFactor, stLength),
    lookahead=barmerge.lookahead_off)
htf3Trend = htf3Dir == 1 ? "BULLISH" : "BEARISH"
htf3Color = htf3Dir == 1 ? color.new(color.green, 0) : color.new(color.red, 0)

// ============================================================================
// CALCULATE ALIGNMENT SCORE
// ============================================================================

// Count bullish timeframes
bullishCount = (ltfDir == 1 ? 1 : 0) +
     (htf1Dir == 1 ? 1 : 0) +
     (htf2Dir == 1 ? 1 : 0) +
     (htf3Dir == 1 ? 1 : 0)

// Calculate alignment score (0-100)
// 100 = all aligned, 50 = mixed, 0 = opposite alignment
alignmentScore = 0.0
if bullishCount == 4 or bullishCount == 0
    // Perfect alignment (all bullish or all bearish)
    alignmentScore := 100.0
else if bullishCount == 3 or bullishCount == 1
    // Strong alignment (3 of 4)
    alignmentScore := 75.0
else
    // No alignment (2-2 split)
    alignmentScore := 50.0

// Determine overall direction
overallDirection = bullishCount >= 3 ? "BULLISH" :
     bullishCount <= 1 ? "BEARISH" : "MIXED"

// ============================================================================
// CONFLUENCE CALCULATION
// ============================================================================

// Weight higher timeframes more
ltfWeight = 1.0
htf1Weight = 1.5
htf2Weight = 2.0
htf3Weight = 2.5

totalWeight = ltfWeight + htf1Weight + htf2Weight + htf3Weight

// Calculate weighted bullish percentage
bullishWeighted = (ltfDir == 1 ? ltfWeight : 0) +
     (htf1Dir == 1 ? htf1Weight : 0) +
     (htf2Dir == 1 ? htf2Weight : 0) +
     (htf3Dir == 1 ? htf3Weight : 0)

confluenceScore = (bullishWeighted / totalWeight) * 100

// ============================================================================
// ENTRY SIGNAL LOGIC
// ============================================================================

// Strong bullish signal
strongBullish = alignmentScore >= minAlignmentScore and
     overallDirection == "BULLISH" and
     (not requireAllAligned or bullishCount == 4)

// Strong bearish signal
strongBearish = alignmentScore >= minAlignmentScore and
     overallDirection == "BEARISH" and
     (not requireAllAligned or bullishCount == 0)

// Entry quality (0-100)
entryQuality = 0.0
if strongBullish or strongBearish
    // Base quality from alignment
    baseQuality = alignmentScore

    // Bonus from volatility regime
    volBonus = 0.0
    if enableVolatility
        if ltfRegime.isExpansion
            volBonus := 10.0  // Trending conditions
        else if ltfRegime.isCompression and ltfRegime.breakoutProbability > 70
            volBonus := 15.0  // Breakout setup

    entryQuality := math.min(100, baseQuality + volBonus)

// ============================================================================
// PLOTS - ALIGNMENT SCORE
// ============================================================================

if showScorePlot
    plot(alignmentScore, "Alignment Score", color.new(color.blue, 0), 2)
    plot(confluenceScore, "Confluence Score", color.new(color.purple, 30), 1)

    hline(100, "Perfect", color.new(color.gray, 80), hline.style_dotted)
    hline(75, "Strong", color.new(color.gray, 80), hline.style_dotted)
    hline(50, "Neutral", color.new(color.gray, 60), hline.style_solid)
    hline(minAlignmentScore, "Min Signal", color.new(color.orange, 50), hline.style_dashed)

// Background color for signals
bgcolor(strongBullish ? color.new(color.green, 90) :
     strongBearish ? color.new(color.red, 90) : na)

// ============================================================================
// DASHBOARD - TREND MATRIX
// ============================================================================

if showMatrix and barstate.islast
    // Determine size
    cellSize = dashboardSize == "tiny" ? size.tiny :
        dashboardSize == "small" ? size.small :
        dashboardSize == "large" ? size.large : size.normal

    var table matrix = table.new(position.top_right, 3, 7,
        border_width=2,
        border_color=color.new(color.gray, 50),
        frame_width=1,
        frame_color=color.new(color.gray, 70))

    // === HEADER ===
    table.cell(matrix, 0, 0, "📊 MTF ALIGNMENT",
        text_color=color.white,
        bgcolor=color.new(color.blue, 20),
        text_size=cellSize,
        text_halign=text.align_center)
    table.merge_cells(matrix, 0, 0, 2, 0)

    // === TIMEFRAME LABELS ===
    table.cell(matrix, 0, 1, "Timeframe", text_color=color.gray, text_size=cellSize)
    table.cell(matrix, 1, 1, "Trend", text_color=color.gray, text_size=cellSize)
    table.cell(matrix, 2, 1, "Status", text_color=color.gray, text_size=cellSize)

    // === LOCAL TIMEFRAME ===
    table.cell(matrix, 0, 2, timeframe.period, text_color=color.white, text_size=cellSize)
    table.cell(matrix, 1, 2, ltfTrend, text_color=ltfColor, text_size=cellSize)
    table.cell(matrix, 2, 2, ltfDir == 1 ? "🟢" : "🔴",
        text_color=color.white, text_size=cellSize)

    // === HTF 1 ===
    table.cell(matrix, 0, 3, timeframe1, text_color=color.white, text_size=cellSize)
    table.cell(matrix, 1, 3, htf1Trend, text_color=htf1Color, text_size=cellSize)
    table.cell(matrix, 2, 3, htf1Dir == 1 ? "🟢" : "🔴",
        text_color=color.white, text_size=cellSize)

    // === HTF 2 ===
    table.cell(matrix, 0, 4, timeframe2, text_color=color.white, text_size=cellSize)
    table.cell(matrix, 1, 4, htf2Trend, text_color=htf2Color, text_size=cellSize)
    table.cell(matrix, 2, 4, htf2Dir == 1 ? "🟢" : "🔴",
        text_color=color.white, text_size=cellSize)

    // === HTF 3 ===
    table.cell(matrix, 0, 5, timeframe3, text_color=color.white, text_size=cellSize)
    table.cell(matrix, 1, 5, htf3Trend, text_color=htf3Color, text_size=cellSize)
    table.cell(matrix, 2, 5, htf3Dir == 1 ? "🟢" : "🔴",
        text_color=color.white, text_size=cellSize)

    // === SEPARATOR ===
    table.cell(matrix, 0, 6, "", bgcolor=color.new(color.gray, 80))
    table.merge_cells(matrix, 0, 6, 2, 6)

    // === ALIGNMENT SCORE ===
    table.cell(matrix, 0, 7, "Alignment",
        text_color=color.gray, text_size=cellSize)
    table.cell(matrix, 1, 7,
        str.format("{0}/100", str.tostring(alignmentScore, "#")),
        text_color=alignmentScore >= 75 ? color.lime :
            alignmentScore >= 50 ? color.yellow : color.red,
        text_size=cellSize)
    table.merge_cells(matrix, 1, 7, 2, 7)

// ============================================================================
// DASHBOARD - DETAILS
// ============================================================================

if barstate.islast
    cellSize = dashboardSize == "tiny" ? size.tiny :
        dashboardSize == "small" ? size.small :
        dashboardSize == "large" ? size.large : size.normal

    var table details = table.new(position.bottom_right, 2, 6,
        border_width=1,
        border_color=color.new(color.gray, 60),
        frame_width=1,
        frame_color=color.new(color.gray, 70))

    // === OVERALL DIRECTION ===
    directionColor = overallDirection == "BULLISH" ? color.new(color.green, 20) :
        overallDirection == "BEARISH" ? color.new(color.red, 20) :
        color.new(color.gray, 50)

    table.cell(details, 0, 0, "Direction",
        text_color=color.gray, text_size=cellSize)
    table.cell(details, 1, 0, overallDirection,
        text_color=color.white,
        bgcolor=directionColor,
        text_size=cellSize,
        text_halign=text.align_center)

    // === CONFLUENCE ===
    table.cell(details, 0, 1, "Confluence",
        text_color=color.gray, text_size=cellSize)
    table.cell(details, 1, 1,
        str.format("{0}%", str.tostring(confluenceScore, "#.#")),
        text_color=color.white, text_size=cellSize)

    // === ENTRY QUALITY ===
    if entryQuality > 0
        table.cell(details, 0, 2, "Entry Quality",
            text_color=color.gray, text_size=cellSize)
        table.cell(details, 1, 2,
            str.format("{0}/100", str.tostring(entryQuality, "#")),
            text_color=entryQuality >= 80 ? color.lime :
                entryQuality >= 60 ? color.yellow : color.orange,
            text_size=cellSize)
    else
        table.cell(details, 0, 2, "Entry Quality",
            text_color=color.gray, text_size=cellSize)
        table.cell(details, 1, 2, "No Setup",
            text_color=color.new(color.gray, 50), text_size=cellSize)

    // === VOLATILITY REGIME ===
    if enableVolatility
        regimeColor = ltfRegime.isCompression ? color.new(color.blue, 20) :
            ltfRegime.isExpansion ? color.new(color.orange, 20) :
            color.new(color.gray, 50)

        table.cell(details, 0, 3, "Volatility",
            text_color=color.gray, text_size=cellSize)
        table.cell(details, 1, 3, ltfRegime.regimeType,
            text_color=color.white,
            bgcolor=regimeColor,
            text_size=cellSize,
            text_halign=text.align_center)

        // Regime details
        regimeDetail = ltfRegime.isCompression ?
            str.format("Breakout: {0}%", str.tostring(ltfRegime.breakoutProbability, "#")) :
            ltfRegime.isExpansion ?
            str.format("Score: {0}", str.tostring(ltfRegime.volatilityScore, "#")) :
            str.format("P{0}", str.tostring(ltfRegime.atrPercentile, "#"))

        table.cell(details, 0, 4, "Details",
            text_color=color.gray, text_size=cellSize)
        table.cell(details, 1, 4, regimeDetail,
            text_color=color.white, text_size=cellSize)

    // === RECOMMENDATION ===
    recommendation = strongBullish ? "🟢 LONG SETUP" :
        strongBearish ? "🔴 SHORT SETUP" :
        alignmentScore < 50 ? "⚠️ NO ALIGNMENT" :
        "⏳ WAIT"

    recColor = strongBullish ? color.new(color.green, 20) :
        strongBearish ? color.new(color.red, 20) :
        color.new(color.gray, 50)

    table.cell(details, 0, 5, "Signal",
        text_color=color.gray, text_size=cellSize)
    table.cell(details, 1, 5, recommendation,
        text_color=color.white,
        bgcolor=recColor,
        text_size=cellSize,
        text_halign=text.align_center)

// ============================================================================
// ALERTS
// ============================================================================

alertcondition(strongBullish and strongBullish[1] == false,
    "Strong Bullish Alignment",
    "MTF Alignment: Strong bullish setup detected")

alertcondition(strongBearish and strongBearish[1] == false,
    "Strong Bearish Alignment",
    "MTF Alignment: Strong bearish setup detected")

alertcondition(alignmentScore >= 100 and alignmentScore[1] < 100,
    "Perfect Alignment",
    "MTF Alignment: All timeframes aligned")

if enableVolatility
    alertcondition(ltfRegime.isCompression and ltfRegime.breakoutProbability > 80,
        "High Breakout Probability",
        str.format("Volatility: {0}% breakout probability",
            str.tostring(ltfRegime.breakoutProbability, "#")))

Overview

MTF Trend Alignment Dashboard [WavesUnchained] classifies each timeframe as bullish or bearish with Supertrend and, when enabled, a volatility regime, then combines the results into a 0–100 confluence score plotted in a separate pane. A trend matrix dashboard summarizes direction by timeframe. Users set Supertrend factor and ATR length, volatility lookback, a minimum score for signals, and whether every timeframe must agree. It does not place trades or define exits.

Details

Published by

casoon on GitHub

Draws

Separate pane below the chart

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Topics

pine-scriptpinescripttechnical-analysistrading-indicatorstrading-strategiestradingview

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
HTF 1timeframe60timeframe1
HTF 2timeframe240timeframe2
HTF 3timeframeDtimeframe3
Factorfloat3.0stFactor
ATR Lengthint10stLength
Show Volatility RegimebooltrueenableVolatility
Lookback Periodint100volLookback
Min Score for Signalint75minAlignmentScore
Require All TimeframesboolfalserequireAllAligned
Show Trend MatrixbooltrueshowMatrix
Plot Alignment ScorebooltrueshowScorePlot
Dashboard SizestringnormaldashboardSize
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

This indicator scans a pasted list of symbols and shows matching long and short setups in a table in a separate pane. It uses a Supertrend crossover, then applies an ATR or fixed-point volatility range so quiet, sideways conditions can be skipped. Optional fil

Indicator v5 TrendVolatility & bands
Updated 1 year ago · MPL-2.0 GitHub repository of Trend Following Setup - Sideways Market Skipper Scanner

Strategy-Picker

by hintheman
13 stars

Strategy-Picker evaluates market trend, momentum, and volatility across multiple timeframes (5m, 15m, and 60m) to recommend suitable options trading structures. It combines MACD, an 8-period EMA, and ADX readings with external VIX levels to suggest Put Credit

Indicator v6 TrendVolatility & bands
Updated 2 months ago · Custom licence GitHub repository of Strategy-Picker

Manias, Panics and Crashes

by MeridianAlgo
9 stars

Manias, Panics and Crashes is a separate-pane market regime indicator that quantifies market sentiment and systemic risk. It processes technical metrics including RSI, moving averages, and volume alongside optional intermarket data such as VIX volatility and c

Indicator v6 Oscillators & momentumVolatility & bands
Updated 4 months ago · MIT GitHub repository of Manias, Panics and Crashes

Elton's Screener

by eltonaguiar
4 stars

Elton's Screener is an indicator that runs in a separate pane and scores one of twenty selectable strategies, or auto-selects a route from the symbol type. It filters signals by a minimum confidence level and a higher-timeframe EMA trend alignment. ATR multipl

Indicator v6 Screeners & dashboardsOscillators & momentum Repaints
Updated 2 days ago · None stated GitHub repository of Elton's Screener
4 stars

Meridian - Futures Context is an intraday analysis indicator designed for US index futures. It measures volume participation using relative volume, calculates rolling realized volatility, and evaluates trend context through VWAP slope and EMA structures. Displ

Indicator v6 VolumeVolatility & bands
Updated 7 weeks ago · MPL-2.0 GitHub repository of Meridian - Futures Context

This indicator draws a SPY scalping panel in a separate pane. It calculates a Supertrend side from ATR smoothed by a selectable average, defaulting to HMA, and uses three moving averages of selectable type, defaulting to EMA lengths 13, 50, and 75. Colors mark

Indicator v5 TrendMoving averages
Updated 5 months ago · None stated GitHub repository of J8 30 123 Spy Scalping Lower Pro 2 Jerry

More Trend scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers