Indicator · Pine Script v5 · On the chart

Linear Regression MTF + Bands

by g-moe· code credited to goodgains

This indicator plots linear regression bands on the price chart for multiple timeframes.

View on GitHub

GitHub stars3on the repository
Pine versionv5runs as is
Lines of code246
Settings33inputs
LicenceNone statedfile: MPL-2.0
Last update5 months ago27 May 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

246 lines of Pine Script v5 from Tradingview/linear-regression-mtf-bands.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

linear-regression-mtf-bands.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © goodgains


//@version=5
indicator("Linear Regression MTF + Bands", overlay=true)

// @keywords: linear-regression, regression-channel, mtf-channels, deviation-bands, upper-lower-bands, three-timeframes, linefill, stepline-bands, channel-alerts, price-breakout, regression-slope, standard-deviation, wma-sma-blend, band-fill, channel-extension, midline, upper-band, lower-band, breakout-alerts, history-band

 
// CHOOSE ALERTS
ALERTS_TF1 = input.bool(false, 'Alerts TF1', group = 'Choose Active Alerts')
ALERTS_TF2 = input.bool(false, 'Alerts TF2', group = 'Choose Active Alerts')
ALERTS_TF3 = input.bool(true, 'Alerts TF3', group = 'Choose Active Alerts')


// TF1
use_tf1         = input.bool(false, title = 'Show TF1 ', inline='1', group='TF1 Settings')
tf1_band        = input.bool(true, title = 'History Band', inline='1', group='TF1 Settings') 
tf1_timeframe   = input.int(5, title='Timeframe', inline='2',  group='TF1 Settings', options = [1,5,15,30,60,240])
tf1_price       = input.source(close, inline='2', title = ' ',  group='TF1 Settings')
tf1_linreg_length = input.int(title='Length ', defval=100, inline='3', maxval = 500, minval = 10, group='TF1 Settings')
tf1_linreg_deviation = input.float(title='Deviation ', defval=2, step=0.25, minval=0.1, maxval=5.00, inline='3', group='TF1 Settings') 
tf1_color       = input.color(color.new(#ffee58, 0), title='upper Color', inline='4', group='TF1 Settings')
tf1_extend      = input.string(defval = 'None', title = 'Extension', options = ['Both', 'Right', 'Left', 'None'], inline='5', group='TF1 Settings')
tf1_width       = input.int(1, title = 'Width', minval = 1, maxval = 5, inline='5', group='TF1 Settings')
tf1_bg          = input.int(90, minval = 0, maxval = 100, title = 'Background Transparency', inline='4', group='TF1 Settings')
tf1_extendStyle = switch
    tf1_extend == "Both" => extend.both
    tf1_extend == "Left" => extend.left
    tf1_extend == "Right" => extend.right
    => extend.none


// TF2
use_tf2         = input.bool(false, title = 'Show TF2 ', inline='1', group='TF2 Settings') 
tf2_band        = input.bool(true, title = 'History Band', inline='1', group='TF2 Settings') 
tf2_timeframe   = input.int(15, title='Timeframe', inline='2',  group='TF2 Settings', options = [1,5,15,30,60,240])
tf2_price       = input.source(close, inline='2', title = ' ',  group='TF2 Settings')
tf2_linreg_length = input.int(title='Length ', defval=100, inline='3', maxval = 500, minval = 10, group='TF2 Settings')
tf2_linreg_deviation = input.float(title='Deviation ', defval=2, step=0.25, minval=0.1, maxval=5.00, inline='3', group='TF2 Settings') 
tf2_color       = input.color(color.new(#ff9800, 0), title='upper Color', inline='4', group='TF2 Settings')
tf2_extend      = input.string(defval = 'None', title = 'Extension', options = ['Both', 'Right', 'Left', 'None'], inline='5', group='TF2 Settings')
tf2_width       = input.int(3, title = 'Width', minval = 1, maxval = 5, inline='5', group='TF2 Settings')
tf2_bg          = input.int(82, minval = 0, maxval = 100, title = 'Background Transparency', inline='6', group='TF2 Settings')
tf2_extendStyle = switch
    tf2_extend == "Both" => extend.both
    tf2_extend == "Left" => extend.left
    tf2_extend == "Right" => extend.right
    => extend.none


// TF3
use_tf3         = input.bool(true, title = 'Show TF3 ', inline='1', group='TF3 Settings')
tf3_band        = input.bool(true, title = 'History Band', inline='1', group='TF3 Settings') 
tf3_timeframe   = input.int(60, title='Timeframe', inline='2',  group='TF3 Settings', options = [1,5,15,30,60,240])
tf3_price       = input.source(close, inline='2', title = ' ',  group='TF3 Settings')
tf3_linreg_length = input.int(title='Length ', defval=100, inline='3', maxval = 500, minval = 10, group='TF3 Settings')
tf3_linreg_deviation = input.float(title='Deviation ', defval=2, step=0.25, minval=0.1, maxval=5.00, inline='3', group='TF3 Settings') 
tf3_color       = input.color(color.new(#0086ff, 0), title='upper Color', inline='4', group='TF3 Settings')
tf3_extend      = input.string(defval = 'None', title = 'Extension', options = ['Both', 'Right', 'Left', 'None'], inline='5', group='TF3 Settings')
tf3_width       = input.int(5, title = 'Width', minval = 1, maxval = 5, inline='5', group='TF3 Settings')
tf3_bg          = input.int(75, minval = 0, maxval = 100, title = 'Background Transparency', inline='6', group='TF3 Settings')
tf3_extendStyle = switch
    tf3_extend == "Both" => extend.both
    tf3_extend == "Left" => extend.left
    tf3_extend == "Right" => extend.right
    => extend.none



calculate_linreg(source, length, deviation) =>
    a = ta.wma(source, length)
    b = ta.sma(source, length)
    A = 4 * b - 3 * a
    B = 3 * a - 2 * b
    m = (A - B) / (length - 1)
    
    d = 0.00
    for i = 0 to length - 1 by 1
        l = B + m * i
        d += math.pow(source[i] - l, 2)
        d
    linreg_1 = math.sqrt(d / (length - 1)) * deviation
    
    
    y1_midvalue = A + 0
    y2_midvalue = -m + (B + 0)
    
    y1_uppervalue = A + linreg_1
    y2_uppervalue = -m + (B + linreg_1)

    y1_lowervalue = A - linreg_1
    y2_lowervalue = -m + (B - linreg_1)
    
    x1_value = time[length]
    
    [x1_value, y1_midvalue, y2_midvalue, y1_lowervalue, y2_lowervalue, y1_uppervalue, y2_uppervalue]



drawLinReg(color_input, extension_input, width_input, x1_value, y1_value, y2_value, linreg_length, tf_input, draw_label) =>

    if draw_label
        label label_variable = label.new(bar_index + 5, y2_value, text=str.tostring(tf_input) + "min | " + str.tostring(math.round_to_mintick(y2_value)), style=label.style_label_left, textcolor = color.black, color = color_input, textalign = text.align_left)
        label.delete(label_variable[1])
        label.set_tooltip(label_variable, 'testing123')
        
    line line_variable = line.new(x1_value, y1_value, time, y2_value, extend = extension_input, color = color_input, width = width_input, xloc = xloc.bar_time)
    line_variable
    

[tf1_x1_value, tf1_y1_midvalue, tf1_y2_midvalue, tf1_y1_lowervalue, tf1_y2_lowervalue, tf1_y1_uppervalue, tf1_y2_uppervalue]= request.security(syminfo.tickerid, str.tostring(tf1_timeframe), calculate_linreg(tf1_price, tf1_linreg_length, tf1_linreg_deviation))
[tf2_x1_value, tf2_y1_midvalue, tf2_y2_midvalue, tf2_y1_lowervalue, tf2_y2_lowervalue, tf2_y1_uppervalue, tf2_y2_uppervalue]= request.security(syminfo.tickerid, str.tostring(tf2_timeframe), calculate_linreg(tf2_price, tf2_linreg_length, tf2_linreg_deviation))
[tf3_x1_value, tf3_y1_midvalue, tf3_y2_midvalue, tf3_y1_lowervalue, tf3_y2_lowervalue, tf3_y1_uppervalue, tf3_y2_uppervalue]= request.security(syminfo.tickerid, str.tostring(tf3_timeframe), calculate_linreg(tf3_price, tf3_linreg_length, tf3_linreg_deviation))



// plot Bands

p_tf1_upper = plot(tf1_y2_uppervalue, title = 'TF1 Upper', color = tf1_color, style = plot.style_stepline, display = use_tf1  and tf1_band ? display.all:display.none, editable = false)
p_tf1_lower = plot(tf1_y2_lowervalue, title = 'TF1 Lower', color = tf1_color, style = plot.style_stepline, display = use_tf1  and tf1_band ? display.all:display.none, editable = false)
fill(p_tf1_lower, p_tf1_upper, title = 'TF1 Band Fill', color = color.new(tf1_color, 90), display = use_tf1 and tf1_band ? display.all:display.none, editable = false)

p_tf2_upper = plot(tf2_y2_uppervalue, title = 'TF2 Upper', color = tf2_color, style = plot.style_stepline, display = use_tf2 and tf2_band ? display.all:display.none, editable = false)
p_tf2_lower = plot(tf2_y2_lowervalue, title = 'TF2 Lower', color = tf2_color, style = plot.style_stepline, display = use_tf2 and tf2_band ? display.all:display.none, editable = false)
fill(p_tf2_lower, p_tf2_upper, title = 'TF2 Band Fill', color = color.new(tf2_color, 90), display = use_tf2 and tf2_band? display.all:display.none, editable = false)

p_tf3_upper = plot(tf3_y2_uppervalue, title = 'TF3 Upper', color = tf3_color, style = plot.style_stepline, display = use_tf3 and tf3_band ? display.all:display.none, editable = false)
p_tf3_lower = plot(tf3_y2_lowervalue, title = 'TF3 Lower', color = tf3_color, style = plot.style_stepline, display = use_tf3 and tf3_band? display.all:display.none, editable = false)
fill(p_tf3_lower, p_tf3_upper, title = 'TF3 Band Fill', color = color.new(tf3_color, 90), display = use_tf3 and tf3_band ? display.all:display.none, editable = false)



var line tf3_mid = na
var line tf2_mid = na
var line tf1_mid = na

var line tf3_upper = na
var line tf2_upper = na
var line tf1_upper = na

var line tf3_lower = na
var line tf2_lower = na
var line tf1_lower = na


if barstate.islast

    if use_tf3 
        tf3_mid     := drawLinReg(color.new(tf3_color, 80), tf3_extendStyle, tf3_width, tf3_x1_value, tf3_y1_midvalue, tf3_y2_midvalue, tf3_linreg_length, tf3_timeframe, false)
        tf3_upper   := drawLinReg(color.new(tf3_color, 0), tf3_extendStyle, tf3_width, tf3_x1_value, tf3_y1_uppervalue, tf3_y2_uppervalue, tf3_linreg_length, tf3_timeframe, true)
        tf3_lower   := drawLinReg(color.new(tf3_color, 0), tf3_extendStyle, tf3_width, tf3_x1_value, tf3_y1_lowervalue, tf3_y2_lowervalue, tf3_linreg_length, tf3_timeframe,true)
        linefill tf3_fill = linefill.new(tf3_upper, tf3_lower, color.new(tf3_color,tf3_bg)) 
        
        if not na(tf3_mid[1])
            line.delete(tf3_mid[1])
            line.delete(tf3_upper[1])
            line.delete(tf3_lower[1])
            linefill.delete(tf3_fill[1])


    if use_tf2 
        tf2_mid     := drawLinReg(color.new(tf2_color, 80), tf2_extendStyle, tf2_width, tf2_x1_value, tf2_y1_midvalue, tf2_y2_midvalue, tf2_linreg_length, tf2_timeframe, false)
        tf2_upper   := drawLinReg(color.new(tf2_color, 0), tf2_extendStyle, tf2_width, tf2_x1_value, tf2_y1_uppervalue, tf2_y2_uppervalue, tf2_linreg_length, tf2_timeframe, true)
        tf2_lower   := drawLinReg(color.new(tf2_color, 0), tf2_extendStyle, tf2_width, tf2_x1_value, tf2_y1_lowervalue, tf2_y2_lowervalue, tf2_linreg_length, tf2_timeframe,true)
        linefill tf2_fill = linefill.new(tf2_upper, tf2_lower, color.new(tf2_color,tf2_bg)) 
        
        if not na(tf2_mid[1])
            line.delete(tf2_mid[1])
            line.delete(tf2_upper[1])
            line.delete(tf2_lower[1])
            linefill.delete(tf2_fill[1])


    if use_tf1 
        tf1_mid     := drawLinReg(color.new(tf1_color, 80), tf1_extendStyle, tf1_width, tf1_x1_value, tf1_y1_midvalue, tf1_y2_midvalue, tf1_linreg_length, tf1_timeframe, false)
        tf1_upper   := drawLinReg(color.new(tf1_color, 0), tf1_extendStyle, tf1_width, tf1_x1_value, tf1_y1_uppervalue, tf1_y2_uppervalue, tf1_linreg_length, tf1_timeframe, true)
        tf1_lower   := drawLinReg(color.new(tf1_color, 0), tf1_extendStyle, tf1_width, tf1_x1_value, tf1_y1_lowervalue, tf1_y2_lowervalue, tf1_linreg_length, tf1_timeframe,true)
        linefill tf1_fill = linefill.new(tf1_upper, tf1_lower, color.new(tf1_color,tf1_bg)) 
        
        if not na(tf1_mid[1])
            line.delete(tf1_mid[1])
            line.delete(tf1_upper[1])
            line.delete(tf1_lower[1])
            linefill.delete(tf1_fill[1])
    
    
    //ALERTS
    tf1_alert = high >= tf1_y2_uppervalue and ALERTS_TF1 ? 1 : low <= tf1_y2_lowervalue and ALERTS_TF1 ? -1 : 0 
    tf2_alert = high >= tf2_y2_uppervalue and ALERTS_TF2 ? 1 : low <= tf2_y2_lowervalue and ALERTS_TF2 ? -1 : 0 
    tf3_alert = high >= tf3_y2_uppervalue and ALERTS_TF3 ? 1 : low <= tf3_y2_lowervalue and ALERTS_TF3 ? -1 : 0 
    
    new_alert = ((tf1_alert != 0) or (tf2_alert != 0) or (tf3_alert != 0))
    var new_alert_text = ' '

    if new_alert
        if tf1_alert != 1 and tf2_alert != 1 and tf3_alert == 1   //ONLY 3 BULL
            new_alert_text := 'ABOVE: TF3 Channel'
    
        if tf1_alert != 1 and tf2_alert == 1 and tf3_alert != 1   //ONLY 2 BULL
            new_alert_text := 'ABOVE: TF2 Channel'
    
        if tf1_alert == 1 and tf2_alert != 1 and tf3_alert != 1   //ONLY 1 BULL
            new_alert_text := 'ABOVE: TF1 Channel'
    
        if tf1_alert != 1 and tf2_alert == 1 and tf3_alert == 1   //2 and 3 BULL
            new_alert_text := 'ABOVE: TF2 & TF3 Channel'
    
        if tf1_alert == 1 and tf2_alert != 1 and tf3_alert == 1   //1 and 3 BULL
            new_alert_text := 'ABOVE: TF1 & TF3 Channel'
    
        if tf1_alert == 1 and tf2_alert == 1 and tf3_alert != 1   //1 and 2 BULL
            new_alert_text := 'ABOVE: TF1 & TF2 Channel'
    
        if tf1_alert == 1 and tf2_alert == 1 and tf3_alert == 1   //1 and 2 and 3 BULL
            new_alert_text := 'ABOVE: TF1 & TF2 & TF3 Channel'
            
        //////////////////////////////////////////////////////////////////////
        
        if tf1_alert != -1 and tf2_alert != -1 and tf3_alert == -1   //ONLY 3 BEAR
            new_alert_text := 'BELOW: TF3 Channel'
    
        if tf1_alert != -1 and tf2_alert == -1 and tf3_alert != -1   //ONLY 2 BEAR
            new_alert_text := 'BELOW: TF2 Channel'
    
        if tf1_alert == -1 and tf2_alert != -1 and tf3_alert != -1   //ONLY 1 BEAR
            new_alert_text := 'BELOW: TF1 Channel'
    
        if tf1_alert != -1 and tf2_alert == -1 and tf3_alert == -1   //2 and 3 BEAR
            new_alert_text := 'BELOW: TF2 & TF3 Channel'
    
        if tf1_alert == -1 and tf2_alert != -1 and tf3_alert == -1   //1 and 3 BEAR
            new_alert_text := 'BELOW: TF1 & TF3 Channel'
    
        if tf1_alert == -1 and tf2_alert == -1 and tf3_alert != -1   //1 and 2 BEAR
            new_alert_text := 'BELOW: TF1 & TF2 Channel'
    
        if tf1_alert == -1 and tf2_alert == -1 and tf3_alert == -1   //1 and 2 and 3 BEAR
            new_alert_text := 'BELOW: TF1 & TF2 & TF3 Channel'
    
    else 
        new_alert_text := ""
    
    if new_alert == true
        alert(new_alert_text, alert.freq_once_per_bar_close)

Overview

Linear Regression MTF + Bands calculates regression lines with standard deviation bands for up to three timeframes, each configurable with length, deviation, color, width, and background transparency. Bands can be shown as history fills or extended in different directions. Users can enable alerts on breakouts for selected timeframes. The tool draws upper and lower bands plus the midline on the main chart, allowing comparison across short, medium, and long timeframes for trend and volatility analysis.

Details

Published by

g-moe on GitHub

Code credit

goodgains, as written in the script's header

Draws

On the price 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.

Settings

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

SettingTypeDefaultVariable
Alerts TF1boolfalseALERTS_TF1
Alerts TF2boolfalseALERTS_TF2
Alerts TF3booltrueALERTS_TF3
Show TF1 boolfalseuse_tf1
History Bandbooltruetf1_band
Timeframeint5tf1_timeframe
sourceclosetf1_price
Length int100tf1_linreg_length
Deviation float2tf1_linreg_deviation
upper Colorcolorcolor.new(#ffee58, 0)tf1_color
ExtensionstringNonetf1_extend
Widthint1tf1_width
Show all 33 settings
SettingTypeDefaultVariable
Background Transparencyint90tf1_bg
Show TF2 boolfalseuse_tf2
History Bandbooltruetf2_band
Timeframeint15tf2_timeframe
sourceclosetf2_price
Length int100tf2_linreg_length
Deviation float2tf2_linreg_deviation
upper Colorcolorcolor.new(#ff9800, 0)tf2_color
ExtensionstringNonetf2_extend
Widthint3tf2_width
Background Transparencyint82tf2_bg
Show TF3 booltrueuse_tf3
History Bandbooltruetf3_band
Timeframeint60tf3_timeframe
sourceclosetf3_price
Length int100tf3_linreg_length
Deviation float2tf3_linreg_deviation
upper Colorcolorcolor.new(#0086ff, 0)tf3_color
ExtensionstringNonetf3_extend
Widthint5tf3_width
Background Transparencyint75tf3_bg
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

[RS]Donchian Fans

by ricardosantos79
261 stars

This indicator plots Donchian Channel boundary lines along with dynamic fan projections directly on the price chart. It calculates the highest high, lowest low, and median price over a customizable lookback period. Whenever price establishes a new channel high

Indicator v4 Support & resistanceTrend
Updated 4 years ago · None stated GitHub repository of [RS]Donchian Fans

Dynamic Linear Regression

by TradersPost
228 stars

Dynamic Linear Regression calculates and plots linear regression trendlines and standard deviation channels directly on the price chart over a user-selected time period. Traders can configure static channels locked at the end time, dynamic channels that contin

Indicator v6 TrendSupport & resistance
Updated 3 months ago · None stated GitHub repository of Dynamic Linear Regression

ATR Trailing Stop

by mihakralj
99 stars

Calculates an ATR-based trailing stop overlaid on the price chart to assist with trend identification and stop placement. Using a specified ATR period and multiplier, it projects upper and lower bounds around the closing price. The stop line ratchets up during

Indicator v5 TrendVolatility & bands
Updated 4 weeks ago · Apache-2.0 GitHub repository of ATR Trailing Stop

Moon Dev Lunar Sniper

by moondevonyt
92 stars

Moon Dev Lunar Sniper is a multi-indicator overlay that scores confluence across fast and slow EMAs, RSI, MACD, DMI, and BB width to fire signals only when score meets the minimum threshold. It plots buy and sell signals on the price chart, highlights cosmic b

Indicator v6 TrendOscillators & momentum Repaints
Updated 2 months ago · Custom licence GitHub repository of Moon Dev Lunar Sniper

SuperTrend & Pivots

by dcaoyuan
55 stars

This overlay indicator plots a SuperTrend line on the price chart using a fixed ATR length of 10 and a factor of 3. When the trend direction is up it draws a green line and a light green fill toward the candle midpoint; when down it draws a red line and a ligh

Indicator v6 TrendVolatility & bands
Updated 6 months ago · Apache-2.0 GitHub repository of SuperTrend & Pivots

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