Indicator · Pine Script v5 · On the chart

LinReg Bands

by g-moe· code credited to goodgains

LinReg Bands calculates a linear regression channel and multiple deviation bands over a user-defined length directly on the price chart.

View on GitHub

Repaints

GitHub stars3on the repository
Pine versionv5runs as is
Lines of code211
Settings12inputs
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

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

linreg-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("LinReg Bands", overlay=true)

// @keywords: linear-regression-bands, linreg-line, deviation-bands, zone-alerts, wma-sma-blend, slope-calculation, upper-band, lower-band, triple-deviation, band-extension, zone-fill, regression-slope, standard-deviation, price-source, configurable-length, zone-crossover, alert-zones, overlay-bands, regression-channel, deviation-zones

//
//TF1
//
tf1_price = input.source(close, inline='2', title = 'Source',  group='Settings')
tf1_linreg_length = input.int(title='Length ', defval=100, inline='2', maxval = 1000, minval = 10, group='Settings')
tf1_linreg_deviation1 = input.float(title='Deviation 1', defval=2.00, step=0.25, minval=0.1, maxval=10.00, inline='3', group='Settings')
tf1_linreg_deviation2 = input.float(title='Deviation 2', defval=3.00, step=0.25, minval=0.1, maxval=10.00, inline='4', group='Settings')
tf1_linreg_deviation3 = input.float(title='Deviation 3', defval=4.00, step=0.25, minval=0.1, maxval=10.00, inline='5', group='Settings')


tf1_color = input.color(color.new(#353865, 0), title='Zone 1 Color', inline='6', group='Settings')
tf2_color = input.color(color.new(#383d84, 0), title='Zone 2 Color', inline='6', group='Settings')
tf3_color = input.color(color.new(#5763ff, 0), title='Zone 3 Color', inline='6', group='Settings')

tf1_extend = input.string(defval = 'None', title = 'Extension', options = ['Both', 'Right', 'Left', 'None'], inline='7', group='Settings')
tf1_width = input.int(1, title = 'Width', minval = 1, maxval = 5, inline='7', group='Settings')
tf1_bg = 90
tf1_extendStyle = switch
    tf1_extend == "Both" => extend.both
    tf1_extend == "Left" => extend.left
    tf1_extend == "Right" => extend.right
    => extend.none

zone1alerts = input.bool(false, title = 'Zone 1 Alerts', group = 'Settings')
zone2alerts = input.bool(false, title = 'Zone 2 Alerts', group = 'Settings')
//
//FUNCTION TO CALCULATE VALUES
//
calculate_linreg(source, length, deviation1, deviation2, deviation3) =>
    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)) * deviation1
    linreg_2 = math.sqrt(d / (length - 1)) * deviation2
    linreg_3 = math.sqrt(d / (length - 1)) * deviation3
    

    // mid 
    y1_midvalue = A + 0
    y2_midvalue = -m + (B + 0)
    
    // zone 1
    y1_lowervalue = A - linreg_1
    y2_lowervalue = -m + (B - linreg_1)
    y1_uppervalue = A + linreg_1
    y2_uppervalue = -m + (B + linreg_1)

    // zone 2
    y1_lowervalue2 = A - linreg_2
    y2_lowervalue2 = -m + (B - linreg_2)
    y1_uppervalue2 = A + linreg_2
    y2_uppervalue2 = -m + (B + linreg_2)

    // zone 3
    y1_lowervalue3 = A - linreg_3
    y2_lowervalue3 = -m + (B - linreg_3)
    y1_uppervalue3 = A + linreg_3
    y2_uppervalue3 = -m + (B + linreg_3)

    
    x1_value = time[length]
    
    [x1_value, y1_midvalue, y2_midvalue, y1_uppervalue, y2_uppervalue, y1_lowervalue, y2_lowervalue,
     y1_uppervalue2, y2_uppervalue2, y1_lowervalue2, y2_lowervalue2,
     y1_uppervalue3, y2_uppervalue3, y1_lowervalue3, y2_lowervalue3]
//
//

//
//FUNCTION TO DRAW LINES
//
drawLinReg(color_input, extension_input, width_input, x1_value, y1_value, y2_value, linreg_length) =>
        
    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_uppervalue, tf1_y2_uppervalue, tf1_y1_lowervalue, tf1_y2_lowervalue,
     y1_uppervalue2, y2_uppervalue2, y1_lowervalue2, y2_lowervalue2,
     y1_uppervalue3, y2_uppervalue3, y1_lowervalue3, y2_lowervalue3]

 = calculate_linreg(tf1_price, tf1_linreg_length, tf1_linreg_deviation1, tf1_linreg_deviation2, tf1_linreg_deviation3)


plot(tf1_y2_uppervalue, title = 'Upper 1', color = tf1_color, display = display.none, style = plot.style_stepline)
plot(tf1_y2_lowervalue, title = 'Lower 1', color = tf1_color, display = display.none, style = plot.style_stepline)

plot(y2_uppervalue2, title = 'Upper 2', color = tf2_color, display = display.none, style = plot.style_stepline)
plot(y2_lowervalue2, title = 'Lower 2', color = tf2_color, display = display.none, style = plot.style_stepline)

plot(y2_uppervalue3, title = 'Upper 3', color = tf3_color, display = display.all, style = plot.style_stepline)
plot(y2_lowervalue3, title = 'Lower 3', color = tf3_color, display = display.all, style = plot.style_stepline)
//
//DRAW LINES AND RUN ALERTS  
//
if barstate.islast

    //TF1
    tf1_mid = drawLinReg(color.new(tf1_color, 20), tf1_extendStyle, tf1_width, tf1_x1_value, tf1_y1_midvalue, tf1_y2_midvalue, tf1_linreg_length)
    tf1_upper1 = drawLinReg(color.new(tf1_color, 0), tf1_extendStyle, tf1_width, tf1_x1_value, tf1_y1_uppervalue, tf1_y2_uppervalue, tf1_linreg_length)
    tf1_lower1 = drawLinReg(color.new(tf1_color, 0), tf1_extendStyle, tf1_width, tf1_x1_value, tf1_y1_lowervalue, tf1_y2_lowervalue, tf1_linreg_length)

    tf1_upper2 = drawLinReg(color.new(tf2_color, 0), tf1_extendStyle, tf1_width, tf1_x1_value, y1_uppervalue2, y2_uppervalue2, tf1_linreg_length)
    tf1_lower2 = drawLinReg(color.new(tf2_color, 0), tf1_extendStyle, tf1_width, tf1_x1_value, y1_lowervalue2, y2_lowervalue2, tf1_linreg_length)

    tf1_upper3 = drawLinReg(color.new(tf3_color, 0), tf1_extendStyle, tf1_width, tf1_x1_value, y1_uppervalue3, y2_uppervalue3, tf1_linreg_length)
    tf1_lower3 = drawLinReg(color.new(tf3_color, 0), tf1_extendStyle, tf1_width, tf1_x1_value, y1_lowervalue3, y2_lowervalue3, tf1_linreg_length)

    linefill tf1_fill1 = linefill.new(tf1_upper1, tf1_lower1, color.new(tf1_color,100)) 
    linefill tf1_fill2 = linefill.new(tf1_upper2, tf1_upper3, color.new(tf3_color,tf1_bg)) 
    linefill tf1_fill3 = linefill.new(tf1_lower2, tf1_lower3, color.new(tf3_color,tf1_bg)) 

    linefill tf1_fill4 = linefill.new(tf1_lower1, tf1_lower2, color.new(tf2_color,tf1_bg)) 
    linefill tf1_fill5 = linefill.new(tf1_upper1, tf1_upper2, color.new(tf2_color,tf1_bg)) 
    

    if not na(tf1_mid[1])

        // mid
        line.delete(tf1_mid[1])

        // zone 1
        line.delete(tf1_upper1[1])
        line.delete(tf1_lower1[1])
        linefill.delete(tf1_fill1[1])

        // zone 2
        line.delete(tf1_upper2[1])
        line.delete(tf1_lower2[1])
        linefill.delete(tf1_fill2[1])

        // zone 3
        line.delete(tf1_upper3[1])
        line.delete(tf1_lower3[1])
        linefill.delete(tf1_fill3[1])
    
    
var bool high_alert = na
var bool low_alert = na

var bool zone1_bullalert = na
var bool zone1_bearalert = na
var bool zone2_bullalert = na
var bool zone2_bearalert = na

high_alert := ta.crossover(high, y2_uppervalue3)
low_alert := ta.crossunder(low, y2_lowervalue3)

zone1_bearalert := (high >= tf1_y2_uppervalue and high <= y2_uppervalue2) 
zone2_bearalert := (high >= y2_uppervalue2 and high <= y2_uppervalue3)

zone1_bullalert := (low <= tf1_y2_lowervalue and low >= y2_lowervalue2) 
zone2_bullalert := (low <= y2_lowervalue2 and low >= y2_lowervalue3)

if low_alert and barstate.isconfirmed
    long_label = label.new(x = bar_index,y = low, text = 'CALL ' + str.tostring(close),
     color = color.green, style = label.style_label_up, yloc =  yloc.belowbar,
     textcolor = color.black, size = size.normal, textalign = text.align_left)

    
if high_alert and barstate.isconfirmed
    short_label = label.new(bar_index, y = high , text = 'PUT ' + str.tostring(close),
     color = color.red, style = label.style_label_down , yloc =  yloc.abovebar,
     textcolor = color.black, size = size.normal, textalign = text.align_left)

 
// show_exit_bubble = input.bool(true, title = 'Show Exit Bubble')
// if show_exit_bubble and barstate.isconfirmed
//     if (dtek_bull[1] and not dtek_bull and last_signal[1] == 1)
//         exit_long = label.new(bar_index, y = close , text = 'Exit ' + str.tostring(close), color = color.white, style = label.style_label_down, yloc =  yloc.abovebar, textcolor = color.black, size = size.normal, textalign = text.align_left)
//     if (dtek_bear[1] and not dtek_bear and last_signal[1] == -1)
//         exit_short = label.new(bar_index, y = close , text = 'Exit ' + str.tostring(close), color = color.white, style = label.style_label_up, yloc =  yloc.belowbar, textcolor = color.black, size = size.normal, textalign = text.align_left)
       

//ALERTS
if high_alert
    alert("Upper Band Alert", alert.freq_once_per_bar_close)
if low_alert
    alert("Lower Band Alert", alert.freq_once_per_bar_close)

if zone1alerts and (zone1_bullalert and not zone1_bullalert[1])
    alert("Zone 1 Bull", alert.freq_once_per_bar_close)
if zone1alerts and (zone1_bearalert and not zone1_bearalert[1])
    alert("Zone 1 Bear", alert.freq_once_per_bar_close)

if zone2alerts and (zone2_bullalert and not zone2_bullalert[1])
    alert("Zone 2 Bull", alert.freq_once_per_bar_close)
if zone2alerts and (zone2_bullalert and not zone2_bullalert[1])
    alert("Zone 2 Bear", alert.freq_once_per_bar_close)
    
    
    
barcolor(zone2_bullalert ? color.lime : zone2_bearalert ? color.red : na)

Overview

LinReg Bands determines the linear regression slope using weighted and simple moving averages, then projects three configurable upper and lower standard deviation zones. Users can customize line extensions, line colors, line width, and enable alert conditions for specific deviation zones. Because linear regression lines recalculate across the lookback period on every bar, historical lines update as new market data arrives.

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

  • Signals can change on the live bar or after it closes (repainting)

Settings

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

SettingTypeDefaultVariable
Sourcesourceclosetf1_price
Length int100tf1_linreg_length
Deviation 1float2.00tf1_linreg_deviation1
Deviation 2float3.00tf1_linreg_deviation2
Deviation 3float4.00tf1_linreg_deviation3
Zone 1 Colorcolorcolor.new(#353865, 0)tf1_color
Zone 2 Colorcolorcolor.new(#383d84, 0)tf2_color
Zone 3 Colorcolorcolor.new(#5763ff, 0)tf3_color
ExtensionstringNonetf1_extend
Widthint1tf1_width
Zone 1 Alertsboolfalsezone1alerts
Zone 2 Alertsboolfalsezone2alerts
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