Indicator · Pine Script v6 · On the chart

Multi-Anchored Linear Regression Channels [TANHEF]

by regalouisei· code credited to TanHef

This indicator plots several linear regression channels on the price chart.

View on GitHub

GitHub stars2on the repository
Pine versionv6current
Lines of code1,145
Settings40inputs
LicenceNone statedfile: MPL-2.0
Last update8 months ago25 Feb 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

1,145 lines of Pine Script v6 from pinescript/editors_picks/multi-anchored-linear-regression-channels-tanhef.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

multi-anchored-linear-regression-channels-tanhef.pine
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TanHef

//@version=6

indicator('Multi-Anchored Linear Regression Channels [TANHEF]', overlay = true, max_bars_back = 5000)

import TanHef/LinearRegression/1 as LR

//Enum -Table Sizes
enum TableSizes
    Tiny = 'Tiny'
    Small = 'Small'
    Normal = 'Normal'
    Large = 'Large'
    Huge = 'Huge'

//Enum - Table Location
enum TableLocation
    TopLeft        = "Top Left"
    TopCenter      = "Top Center"
    TopRight       = "Top Right"
    MiddleLeft     = "Middle Left"
    MiddleRight    = "Middle Right"
    BottomLeft     = "Bottom Left"
    BottomCenter   = "Bottom Center"
    BottomRight    = "Bottom Right"

//ENUM - Display Linear Regression
enum DisplayLinReg
    Hide = '─ Hide ─'
    Channel = 'Channel'
    Bands = 'Bands'
    All = 'Bands+Channel'

//ENUM - Anchor Sources (LinReg Calculation Length)
enum AnchorSource
    Length = 'Length'
    BarHighest = 'Bar Highest'
    BarLowest = 'Bar Lowest'
    VolHighest = 'Volume Highest'
    VolLowest = 'Volume Lowest'
    SpreadHighest = 'Spread Highest'
    SpreadLowest = 'Spread Lowest'
    RZero = 'R Zero'
    RHighest = 'R Highest'
    RLowest = 'R Lowest'
    RAbsolute = 'R Absolute'
    SlopeZero = 'Slope Zero'
    SlopeHighest = 'Slope Highest'
    SlopeLowest = 'Slope Lowest'
    SlopeAbsolute = 'Slope Absolute'
    AdxHighest = 'ADX Highest'
    AdxLowest = 'ADX Lowest'
    AtrHighest = 'ATR Highest'
    AtrLowest = 'ATR Lowest'
    BbwHighest = 'BBW Highest'
    BbwLowest = 'BBW Lowest'
    CciHighest = 'CCI Highest'
    CciLowest = 'CCI Lowest'
    MacdHighest = 'MACD Highest'
    MacdLowest = 'MACD Lowest'
    RsiHighest = 'RSI Highest'
    RsiLowest = 'RSI Lowest'
    StochHighest = 'Stoch Highest'
    StochLowest = 'Stoch Lowest'
    TimeDay = 'Day'
    TimeWeek = 'Week'
    TimeMonth = 'Month'
    TimeQuarter = 'Quarter'
    TimeYear = 'Year'
    TimeDecade = 'Decade'
    TimeCustom = 'Date Custom'
    SessionTokyo = 'Session Tokyo'
    SessionLondon = 'Session London '
    SessionNewYork = 'Session New York'
    SessionSydney = 'Session Sydney'
    SessionChart = 'Session Charts'
    SessionCustom = 'Session Custom'
    Earnings = 'Earnings'
    Dividends = 'Dividends'
    Splits = 'Splits'
    ExternalHighest = 'External Highest'
    ExternalLowest = 'External Lowest'
    SourceHighest = 'Source Highest'
    SourceLowest = 'Source Lowest'

//ENUM - Regression Calculation Types (Formulas)
enum RegressionType
    Standard = 'Standard'
    Ridge = 'Ridge'
    Lasso = 'Lasso'
    ElasticNet = 'Elastic Net'
    Huber = 'Huber'
    LAD = 'LAD'
    Bayesian = 'Bayesian'

//ENUM - Deviation Calculation Types (Formulas)
enum DeviationType
    Reverse = 'Reverse'   // Regressive Linear Deviation (Reverse)
    Forward = 'Forward'   // Progressive Linear Deviation (Forward)
    Balanced = 'Balanced' // Balanced Linear Deviation
    Mean = 'Mean'         // Mean Absolute Deviation
    Median = 'Median'     // Median Absolute Deviation
    Percent = 'Percent'   // Percent Deviation
    ATR = 'ATR'           // Average True Range Deviation
    Fitted = 'Fitted'     // Fitted Deviation

//ENUM - Signal Label Styles
enum SignalLabelStyle
    BG = 'Background'
    Top = 'Top'
    Bottom = 'Bottom'
    Price = 'Price (Above/Below)'

//ENUM - Signal Percent
enum SignalPercent
    Any = ''
    Above = 'Above %'
    Below = 'Below %'

//ENUM - Signal R
enum SignalR
    Any = ''
    Above = 'Above R'
    Below = 'Below R'
    AbsBelow = 'Below│ᴿ│'
    AbsAbove = 'Above│ᴿ│'
    Mid = 'Zero to R'

//ENUM - Rounding Value
enum RoundingValue
    Decimals = 'Decimals'
    SigFigs = 'Sig Figs'

//ENUM - Extension Options
enum ExtensionType
    ExtendNo = 'No Extend'
    ExtendLeft = 'Extend ←'
    ExtendRight = 'Extend →'
    ExtendBoth = 'Extend ↔'

//ENUM - Line Styles
enum LineStyle
    Solid = 'Solid'
    Dotted = 'Dotted'
    Dashed = 'Dashed'

//TYPE - Time
type Time
    int hour
    int minute

//SETUP - Sessions Start Times
timeTokyo = Time.new(0, 0)
timeLondon = Time.new(8, 0)
timeNewYork = Time.new(13, 0)
timeSydney = Time.new(21, 0)

//TOOLTIP - Scale Type
const string tt_log = "█ Log Scale\nSelect for logarithmic scaling, otherwise linear."

//TOOLTIP - LinReg Display Type, Anchor type, Source
const string tt_linreg = '█ Display Linear Regression (LinReg) option\n● Channel: Channel only (ideal for live).\n● Bands: Bands only (ideal for backtesting).\n● Both: Channels and Bands.\n● Hide: None.\n\n█ Anchor Type for LinReg Length\n● Fixed: Length.\n● Bar-Based: Highest/Lowest ($Bar,Vol,Spread).\n● Correlation: R (Zero, Highest, Lowest, Abs.)\n● Slope: Slope (Zero, Highest, Lowest, Abs.)\n● Indicator-Based: Indicators Highest/Lowest\n   (ADX, ATR, BBW, CCI, MACD, RSI, Stoch).\n● Time & Session: Time (Day, Week, Month,\n   Quarter, Year, Decade, Custom).\n   Sessions [UTC] (Tokyo[12am], London[7am],\n   New York[1pm], Sydney[9pm], Custom).\n● Event-Based: Earnings, Dividends, Splits.\n● External: External Source Highest/Lowest.\n● Source: Regression Source Highest/Lowest.\n\n█ Source\nData source for LinReg calculation.'

//TOOLTIP - Max Length, Min Length, Step Length
const string tt_length = "█ Length Maximum\n(Larger length increases indicator\'s load time) \n\n█ Length Minimum\nApplies to all anchor types except fixed 'length'.\nIf min > max , min becomes 2.\n\n█ Length Step *WARNING: REDUCES ACCURACY*\nSkips bars for improved loading time, but reduces accuracy. Ideal for R and Slope anchors.\n(Step=1 checks all bars, Step=2 every 2nd bar, ...)"

//TOOLTIP - Regression Type, Regression Emphasis
const string tt_reg = "█ Regression Type (find their settings below)\n   *Some change more on short lengths (~10bars)*\n● Standard: Fits a linear trend to data.\n● Ridge (L2 penalty): Penalizes large coefficients.\n● Lasso (L1 penalty): Promotes sparse solutions.\n● Elastic Net: Combines Lasso (L1) & Ridge (L2).\n● Huber: Huber loss for outlier robustness.\n● LAD (Least Absolute Deviations): Less error.\n● Bayesian: Incorporates prior information.\n\n█ Deviation Bias (Weighting)\n >0: Most recent prices weighted more. (EMA)\n  0: All prices equally weighted.\n <0: Oldest prices weighted more. (Inversed EMA)"

//TOOLTIP - Deviation Type, Deviation Emphasis, Deviation Multiplier
const string tt_dev = '█ Deviation Type\n● \'Reverse\' Linear (TradingView\'s default):\n   deviation against linear trend (new→oldest).\n● \'Forward\' Linear:\n   deviation along linear trend (old→newest). \n● \'Balanced\' Linear: compute regression forward,\n   and deviation in reverse, for \'balance\'.\n● \'Mean\' Absolute: averages absolute differences.\n● \'Median\' Absolute: finds median. \n● \'Percent\': fixed percentage scale. \n● \'Fitted\' Extreme: highest/lowest fit.\n● \'ATR\': iteratively computes (ATR-style).\n\n█ Deviation Bias (Weighting)\nEMA-style weight (Ignored if Type=Percent).\n >0: Most recent prices weighted more. (EMA)\n  0: All prices equally weighted.\n <0: Oldest prices weighted more. (Inversed EMA)\n\n█ Deviation Multiplier (✕)\nUpper and Lower Deviation Multiplier.'

//TOOLTIP - Signal Display For External Use
const string tt_displayForExternal = '█ Plots Values for External Use\n0 = no signal\n1 = entry signal\n2 = exit signal\n3 = entry & exit signal'

//TOOLTIP - Adaptive Length
const string tt_adapative = "█ Adaptive Lookback\nIf selected, the regression will plot regardless of number of bars being less than the 'max' length input."

//TOOLTIP - Step Warning
const string tt_stepWarning = "█ Warning message for Step > 1\nStep is the sampling interval (e.g., 1 checks every bar, 2 checks every other bar, etc.). Increasing the step reduces the loading time, most applicable to “Slope” and “R” anchors."

//TOOLTIP - Signal Types
const string tt_signalsTypes = '█ Location of signals\n● Background (Color): background colored. \n● Top (Symbols): symbol at chart top. \n● Bottom (Symbols): symbol at chart bottom. \n● Price (Symbols): Entry below, Exit above price.'

//Tooltip - Signal Criteria
const string tt_signalsCriteria = "All criteria must be true. Only includes displayed channels/bands. Avg = average of all displayed. \n\n█ Percent Direction \n● Blank: percent excluded from signal criteria. \n● Above %: price above input percentage. \n● Below %: price below input percentage. \n\n█ Percent Value (Price vs. Deviation) \n(+dev. = 100%, midline = 50%, -dev. = 0%) \n\n█ R Direction \n● Blank: R excluded from signal criteria. \n● Above R: R above input R value. \n● Below R: R below input R value. \n● Above│R│: R above input R (Absolute values). \n● Below│R│: R below input R (Absolute values). \n● Zero to R: R between input R and 0. \nAbsolute (|-1| = 1): Always positive, ignores sign. \n\n█ R Value\n(>0 = uptrend , <0 = downtrend) \n(±1 = perfect correlation , 0 = none) \n\nSettings Examples:\n-Buy dip in uptrend: 'below%'  '0'  'aboveR'  '0'\n-Sell rise in downtrend: 'above%'  '100'  'belowR'  '0'"

//TOOLTIPS - Indicators and Time
const string tt_ext = '█ External Source\nSelect any external source, such as another indicator or chart (e.g., VIX).\n\nApplicable to the \'Anchor\' type \'External\'.'
const string tt_adx = '█ ADX (Average Directional Index) Length\nLength for DI (Directional Movement).\n\n█ ADX (Average Directional Index) Smoothing\nPeriod for smoothing ADX.\n\nApplicable to the \'Anchor\' type \'ADX\'.'
const string tt_atr = '█ ATR (Average True Range) Length\nLength for ATR.\n\n█ ATR (Average True Range) Smoothing\nMoving average type.\n\nApplicable to the \'Anchor\' type \'ATR\'.'
const string tt_bbw = '█ BBW (Bollinger Bands Width) Length\nLength for BBW. \n\n█ BBW (Bollinger Bands Width) Mult\nStandard deviation multiplier.\n\nApplicable to the \'Anchor\' type \'BBW\'.'
const string tt_cci = '█ CCI (Commodity Channel Index) Length\nLength for CCI.\n█ CCI (Commodity Channel Index) Source\nSource for calculation.\n\nApplicable to the \'Anchor\' type \'CCI\'.'
const string tt_macd = '█ MACD (Moving Average Convergence/Divergence) Fast Length\nFast ma periods.\n\n█ MACD (Moving Average Convergence/Divergence) Slow Length\nSlow ma periods.\n\n█ MACD (Moving Average Convergence/Divergence) Source\nSource for calculation.\n\n█ MACD (Moving Average Convergence/Divergence) MA Type\nSmoothing type.\n\nApplicable to the \'Anchor\' type \'MACD\'.'
const string tt_rsi = '█ RSI (Relative Strength Index) Source\nData series to calculate RSI.\n\n█ RSI (Relative Strength Index) Length\nNumber of bars for RSI calculation.\n\nApplicable to the \'Anchor\' type \'RSI\'.'
const string tt_stoch = '█ Stochastic %K Length\nBars for Stochastic calculation.\n\n█ Stochastic %K Smoothing\nSmoothing factor.\n\nApplicable to the \'Anchor\' type \'Stoch\'.'
const string tt_Sessions = " █ Custom\nApplicable to 'Custom Date' and 'Custom Session''\n\n █ Show (Vertical) Line\nPlot backcolor where date/time is.\n\nApplicable to the \'Anchor\' type \'Custom\'.'"

//TOOLTIPS - Deviation Calculations Params
const string tt_ridge = '█ Ridge regression L2 penalty\nHigher values impose a stronger penalty on coefficient sizes, resulting in smoother coefficient estimates.\n\nApplicable to the \'Regression Type\' type \'Ridge\'.'
const string tt_lasso = '█ Lasso regression L1 penalty\nHigher values promote sparsity by driving some coefficients to zero.\n\nApplicable to the \'Regression Type\' type \'Lasso\'.'
const string tt_huber = '█ Huber loss regression delta threshold\nDetermines the point at which errors are down-weighted to reduce outlier impact.\n\n█ Huber loss regression number of iterations\nRefines Huber regression estimates.\n\nApplicable to the \'Regression Type\' type \'Huber\'.'
const string tt_LAD = '█ LAD (Least Absolute Deviations) regression Iterations\nNumber of iterations for regression optimization.\n\nApplicable to the \'Regression Type\' type \'LAD\'.'
const string tt_bayesian = '█ Bayesian Prior mean\nPrior mean for Bayesian regression to influence initial estimates for the regression coefficients.\n\n█ Bayesian Prior span\nPrior span (variance) for Bayesian regression. Adjust to control the weight of the prior relative to the data.\n\n█ Bayesian Error (Sigma)\nError representing expected noise in data.\n\nApplicable to the \'Regression Type\' type \'Bayesian\'.'

//TOOLTIP - Styling
const string tt_styling = '◆◆◆Channel◆◆◆ \n█ Up lines color \n█ Down lines color \n█ Up fill color \n█ Down fill color \n█ Extend lines (no,left,right,both) \n█ Line style of deviations (solid,dotted,dashed)\n(Mid-line is always solid) \n\n◆◆◆Bands◆◆◆ \n█ Lines (top/bottom) color \n█ Lines (middle) color \n█ Fill color \n\n█Line width: Applies to both channel/bands lines'

//INPUTS - Log Scale
scaleTypeLog = input.bool(false, title="Log Scale", tooltip=tt_log)

//Easily change max bars of inputs (remember to change max_bars_back if modifying this)
const int max_bars = 5000

//INPUTS - #1 Regression
g_reg1 = 'Regression #1 Settings'
inputDisplay1 = input.enum(DisplayLinReg.Hide, title = '#1', inline = 'len1a', group = g_reg1)
showChannel1 = inputDisplay1 == DisplayLinReg.Channel or inputDisplay1 == DisplayLinReg.All ? true : false
showBands1 = inputDisplay1 == DisplayLinReg.Bands or inputDisplay1 == DisplayLinReg.All ? true : false
show1 = showChannel1 or showBands1 ? true : false
inputType1 = input.enum(AnchorSource.BarHighest, title = 'Anchor', inline = 'len1a', group = g_reg1, active = inputDisplay1 != DisplayLinReg.Hide)
inputSource1 = input.source(close, title = 'Source', inline = 'len1a', group=g_reg1, tooltip = tt_linreg, active = inputDisplay1 != DisplayLinReg.Hide)
inputMax1 = input.int(1000, title = 'Length│Max', inline = 'len1b', minval = 2, maxval = max_bars, group = g_reg1, active = inputDisplay1 != DisplayLinReg.Hide)
inputMin1 = input.int(10, title = 'Min', inline = 'len1b', minval = 2, maxval = max_bars, group = g_reg1, active = inputDisplay1 != DisplayLinReg.Hide and inputType1 != AnchorSource.Length)
inputStep1 = input.int(1, title = 'Step', inline = 'len1b', minval = 1, maxval = max_bars, tooltip = tt_length, group = g_reg1, active = inputDisplay1 != DisplayLinReg.Hide and inputType1 != AnchorSource.Length)
inputRegType1 = input.enum(RegressionType.Standard, title = 'Regression│Type', inline = 'len1c', group = g_reg1, tooltip = tt_reg, active = inputDisplay1 != DisplayLinReg.Hide)
inputRegWeight1 = input.float(0, title = 'Bias', inline = 'len1c', minval = -10, maxval = 10, step=0.1, group = g_reg1, active = inputDisplay1 != DisplayLinReg.Hide)
inputDevType1 = input.enum(DeviationType.Reverse, title = 'Deviation│Type', inline = 'len1d', tooltip = tt_dev, group = g_reg1, active = inputDisplay1 != DisplayLinReg.Hide)
inputDevWeight1 = input.float(0, title = 'Bias', inline = 'len1d', minval = -10, maxval = 10, step=0.1, group = g_reg1, active = inputDisplay1 != DisplayLinReg.Hide)
inputDev1 = input.float(2, title = '✕', inline = 'len1d', minval = 0.1, step = 0.1, group = g_reg1, active = inputDisplay1 != DisplayLinReg.Hide)

//INPUTS - #2 Regression
g_reg2 = 'Regression #2 Settings'
inputDisplay2 = input.enum(DisplayLinReg.Hide, title = '#2', inline = 'len2a', group = g_reg2)
showChannel2 = inputDisplay2 == DisplayLinReg.Channel or inputDisplay2 == DisplayLinReg.All ? true : false
showBands2 = inputDisplay2 == DisplayLinReg.Bands or inputDisplay2 == DisplayLinReg.All ? true : false
show2 = showChannel2 or showBands2 ? true : false
inputType2 = input.enum(AnchorSource.BarLowest, title = 'Anchor', inline = 'len2a', group = g_reg2, active = inputDisplay2 != DisplayLinReg.Hide)
inputSource2 = input.source(close, title = 'Source', inline = 'len2a', group=g_reg2, tooltip = tt_linreg, active = inputDisplay2 != DisplayLinReg.Hide)
inputMax2 = input.int(1000, title = 'Length│Max', inline = 'len2b', minval = 2, maxval = max_bars, group = g_reg2, active = inputDisplay2 != DisplayLinReg.Hide)
inputMin2 = input.int(10, title = 'Min', inline = 'len2b', minval = 2, maxval = max_bars, group = g_reg2, active = inputDisplay2 != DisplayLinReg.Hide and inputType2 != AnchorSource.Length)
inputStep2 = input.int(1, title = 'Step', inline = 'len2b', minval = 1, maxval = max_bars, tooltip = tt_length, group = g_reg2, active = inputDisplay2 != DisplayLinReg.Hide and inputType2 != AnchorSource.Length)
inputRegType2 = input.enum(RegressionType.Standard, title = 'Regression│Type', inline = 'len2c', group = g_reg2, tooltip = tt_reg, active = inputDisplay2 != DisplayLinReg.Hide)
inputRegWeight2 = input.float(0, title = 'Bias', inline = 'len2c', minval = -10, maxval = 10, step=0.1, group = g_reg2, active = inputDisplay2 != DisplayLinReg.Hide)
inputDevType2 = input.enum(DeviationType.Reverse, title = 'Deviation│Type', inline = 'len2d', tooltip = tt_dev, group = g_reg2, active = inputDisplay2 != DisplayLinReg.Hide)
inputDevWeight2 = input.float(0, title = 'Bias', inline = 'len2d', minval = -10, maxval = 10, step=0.1, group = g_reg2, active = inputDisplay2 != DisplayLinReg.Hide)
inputDev2 = input.float(2, title = '✕', inline = 'len2d', minval = 0.1, step = 0.1, group = g_reg2, active = inputDisplay2 != DisplayLinReg.Hide)

//INPUTS - #3 Regression
g_reg3 = 'Regression #3 Settings'
inputDisplay3 = input.enum(DisplayLinReg.Hide, title = '#3', inline = 'len3a', group = g_reg3)
showChannel3 = inputDisplay3 == DisplayLinReg.Channel or inputDisplay3 == DisplayLinReg.All ? true : false
showBands3 = inputDisplay3 == DisplayLinReg.Bands or inputDisplay3 == DisplayLinReg.All ? true : false
show3 = showChannel3 or showBands3 ? true : false
inputType3 = input.enum(AnchorSource.SlopeZero, title = 'Anchor', inline = 'len3a', group = g_reg3, active = inputDisplay3 != DisplayLinReg.Hide)
inputSource3 = input.source(close, title = 'Source', inline = 'len3a', group=g_reg3, tooltip = tt_linreg, active = inputDisplay3 != DisplayLinReg.Hide)
inputMax3 = input.int(400, title = 'Length│Max', inline = 'len3b', minval = 2, maxval = max_bars, group = g_reg3, active = inputDisplay3 != DisplayLinReg.Hide)
inputMin3 = input.int(10, title = 'Min', inline = 'len3b', minval = 2, maxval = max_bars, group = g_reg3, active = inputDisplay3 != DisplayLinReg.Hide and inputType3 != AnchorSource.Length)
inputStep3 = input.int(10, title = 'Step', inline = 'len3b', minval = 1, maxval = max_bars, tooltip = tt_length, group = g_reg3, active = inputDisplay3 != DisplayLinReg.Hide and inputType3 != AnchorSource.Length)
inputRegType3 = input.enum(RegressionType.Standard, title = 'Regression│Type', inline = 'len3c', group = g_reg3, tooltip = tt_reg, active = inputDisplay3 != DisplayLinReg.Hide)
inputRegWeight3 = input.float(0, title = 'Bias', inline = 'len3c', minval = -10, maxval = 10, step=0.1, group = g_reg3, active = inputDisplay3 != DisplayLinReg.Hide)
inputDevType3 = input.enum(DeviationType.Reverse, title = 'Deviation│Type', inline = 'len3d', tooltip = tt_dev, group = g_reg3, active = inputDisplay3 != DisplayLinReg.Hide)
inputDevWeight3 = input.float(0, title = 'Bias', inline = 'len3d', minval = -10, maxval = 10, step=0.1, group = g_reg3, active = inputDisplay3 != DisplayLinReg.Hide)
inputDev3 = input.float(2, title = '✕', inline = 'len3d', minval = 0.1, step = 0.1, group = g_reg3, active = inputDisplay3 != DisplayLinReg.Hide)

//INPUTS - Signals (1st Section)
g_signalsGreen = 'Entry Signal'
colUp = input.color(color.lime, title = '  % Direction  |  % Value  | R Direction | R Value', inline = 'col', group = g_signalsGreen)
dirUpPercent1 = input.enum(SignalPercent.Any, title = '#1', inline = '1up1', group = g_signalsGreen, active = inputDisplay1 != DisplayLinReg.Hide)
valUpPercent1 = input(0, title = '', inline = '1up1', group = g_signalsGreen, active = inputDisplay1 != DisplayLinReg.Hide and dirUpPercent1 != SignalPercent.Any)
dirUpR1 = input.enum(SignalR.Any, title = '', inline = '1up1', group = g_signalsGreen, tooltip = tt_signalsCriteria, active = inputDisplay1 != DisplayLinReg.Hide)
valUpR1 = input.float(0, title = '', inline = '1up1', group = g_signalsGreen, minval = -1, maxval = 1, step = 0.1, active = inputDisplay1 != DisplayLinReg.Hide and dirUpR1 != SignalR.Any)
dirUpPercent2 = input.enum(SignalPercent.Any, title = '#2', inline = '2up1', group = g_signalsGreen, active = inputDisplay2 != DisplayLinReg.Hide)
valUpPercent2 = input(0, title = '', inline = '2up1', group = g_signalsGreen, active = inputDisplay2 != DisplayLinReg.Hide and dirUpPercent2 != SignalPercent.Any)
dirUpR2 = input.enum(SignalR.Any, title = '', inline = '2up1', group = g_signalsGreen, active = inputDisplay2 != DisplayLinReg.Hide)
valUpR2 = input.float(0, title = '', inline = '2up1', group = g_signalsGreen, minval = -1, maxval = 1, step = 0.1, active = inputDisplay2 != DisplayLinReg.Hide and dirUpR2 != SignalR.Any)
dirUpPercent3 = input.enum(SignalPercent.Any, title = '#3', inline = '3up1', group = g_signalsGreen, active = inputDisplay3 != DisplayLinReg.Hide)
valUpPercent3 = input(0, title = '', inline = '3up1', group = g_signalsGreen, active = inputDisplay3 != DisplayLinReg.Hide and dirUpPercent3 != SignalPercent.Any)
dirUpR3 = input.enum(SignalR.Any, title = '', inline = '3up1', group = g_signalsGreen, active = inputDisplay3 != DisplayLinReg.Hide)
valUpR3 = input.float(0, title = '', inline = '3up1', group = g_signalsGreen, minval = -1, maxval = 1, step = 0.1, active = inputDisplay3 != DisplayLinReg.Hide and dirUpR3 != SignalR.Any)
dirUpPercentAVG = input.enum(SignalPercent.Any, title = 'ᴬᵛᵍ', inline = 'AVGup1', group = g_signalsGreen, active = inputDisplay1 != DisplayLinReg.Hide or inputDisplay2 != DisplayLinReg.Hide or inputDisplay3 != DisplayLinReg.Hide)
valUpPercentAVG = input(0, title = '', inline = 'AVGup1', group = g_signalsGreen, active = dirUpPercentAVG != SignalPercent.Any and (inputDisplay1 != DisplayLinReg.Hide or inputDisplay2 != DisplayLinReg.Hide or inputDisplay3 != DisplayLinReg.Hide))
dirUpRAVG = input.enum(SignalR.Any, title = '', inline = 'AVGup1', group = g_signalsGreen, active = inputDisplay1 != DisplayLinReg.Hide or inputDisplay2 != DisplayLinReg.Hide or inputDisplay3 != DisplayLinReg.Hide)
valUpRAVG = input.float(0, title = '', inline = 'AVGup1', group = g_signalsGreen, minval = -1, maxval = 1, step = 0.1, active = dirUpRAVG != SignalR.Any and (inputDisplay1 != DisplayLinReg.Hide or inputDisplay2 != DisplayLinReg.Hide or inputDisplay3 != DisplayLinReg.Hide))

//INPUTS - Signals (2nd Section)
g_signalsRed = 'Exit Signals'
colDn = input.color(color.red, title = '  % Direction  |  % Value  | R Direction | R Value', inline = 'col', group = g_signalsRed)
dirDnPercent1 = input.enum(SignalPercent.Any, title = '#1', inline = '1down1', group = g_signalsRed, active = inputDisplay1 != DisplayLinReg.Hide)
valDnPercent1 = input(100, title = '', inline = '1down1', group = g_signalsRed, active = inputDisplay1 != DisplayLinReg.Hide and dirDnPercent1 != SignalPercent.Any)
dirDnR1 = input.enum(SignalR.Any, title = '', inline = '1down1', group = g_signalsRed, active = inputDisplay1 != DisplayLinReg.Hide)
valDnR1 = input.float(0, title = '', inline = '1down1', group = g_signalsRed, minval = -1, maxval = 1, step = 0.1, active = inputDisplay1 != DisplayLinReg.Hide and dirDnR1 != SignalR.Any)
dirDnPercent2 = input.enum(SignalPercent.Any, title = '#2', inline = '2down1', group = g_signalsRed, active = inputDisplay2 != DisplayLinReg.Hide)
valDnPercent2 = input(100, title = '', inline = '2down1', group = g_signalsRed, active = inputDisplay2 != DisplayLinReg.Hide and dirDnPercent2 != SignalPercent.Any)
dirDnR2 = input.enum(SignalR.Any, title = '', inline = '2down1', group = g_signalsRed, active = inputDisplay2 != DisplayLinReg.Hide)
valDnR2 = input.float(0, title = '', inline = '2down1', group = g_signalsRed, minval = -1, maxval = 1, step = 0.1, active = inputDisplay2 != DisplayLinReg.Hide and dirDnR2 != SignalR.Any)
dirDnPercent3 = input.enum(SignalPercent.Any, title = '#3', inline = '3down1', group = g_signalsRed, active = inputDisplay3 != DisplayLinReg.Hide)
valDnPercent3 = input(100, title = '', inline = '3down1', group = g_signalsRed, active = inputDisplay3 != DisplayLinReg.Hide and dirDnPercent3 != SignalPercent.Any)
dirDnR3 = input.enum(SignalR.Any, title = '', inline = '3down1', group = g_signalsRed, active = inputDisplay3 != DisplayLinReg.Hide)
valDnR3 = input.float(0, title = '', inline = '3down1', group = g_signalsRed, minval = -1, maxval = 1, step = 0.1, active = inputDisplay3 != DisplayLinReg.Hide and dirDnR3 != SignalR.Any)
dirDnPercentAVG = input.enum(SignalPercent.Any, title = 'ᴬᵛᵍ', inline = '1AVGdown1', group = g_signalsRed, active = inputDisplay1 != DisplayLinReg.Hide or inputDisplay2 != DisplayLinReg.Hide or inputDisplay3 != DisplayLinReg.Hide)
valDnPercentAVG = input(100, title = '', inline = '1AVGdown1', group = g_signalsRed, active = dirDnPercentAVG != SignalPercent.Any and (inputDisplay1 != DisplayLinReg.Hide or inputDisplay2 != DisplayLinReg.Hide or inputDisplay3 != DisplayLinReg.Hide))
dirDnRAVG = input.enum(SignalR.Any, title = '', inline = '1AVGdown1', group = g_signalsRed, active = inputDisplay1 != DisplayLinReg.Hide or inputDisplay2 != DisplayLinReg.Hide or inputDisplay3 != DisplayLinReg.Hide)
valDnRAVG = input.float(0, title = '', inline = '1AVGdown1', group = g_signalsRed, minval = -1, maxval = 1, step = 0.1, active = dirDnRAVG != SignalR.Any and (inputDisplay1 != DisplayLinReg.Hide or inputDisplay2 != DisplayLinReg.Hide or inputDisplay3 != DisplayLinReg.Hide))

//Signals
var int showCount = (show1 ? 1 : 0) + (show2 ? 1 : 0) + (show3 ? 1 : 0)
var bool displayAny = showCount > 0 ? true : false //Identifies if any Channels or Bands are displayed
var bool useAverageUpSignal = (dirUpPercentAVG != SignalPercent.Any or dirUpRAVG != SignalR.Any) and showCount > 0 ? true : false //Used to check signals
var bool useAverageDnSignal = (dirDnPercentAVG != SignalPercent.Any or dirDnRAVG != SignalR.Any) and showCount > 0 ? true : false //Used to check signals
var bool showAVG = (useAverageUpSignal or useAverageDnSignal) and displayAny ? true : false //Used by table
bool bigUp = showCount > 0 ? true : false //Stores signal result
bool bigDown = showCount > 0 ? true : false //Stores signal result

//CHECK - Signal Type
var bool useSignalUpAny = true
var bool useSignalDnAny = true
var bool useSignalUpPercent = show1 and dirUpPercent1 != SignalPercent.Any or show2 and dirUpPercent2 != SignalPercent.Any or show3 and dirUpPercent3 != SignalPercent.Any or useAverageUpSignal and dirUpPercentAVG != SignalPercent.Any
var bool useSignalUpR = show1 and dirUpR1 != SignalR.Any or show2 and dirUpR2 != SignalR.Any or show3 and dirUpR3 != SignalR.Any or useAverageUpSignal and dirUpRAVG != SignalR.Any
var bool useSignalDnPercent = show1 and dirDnPercent1 != SignalPercent.Any or show2 and dirDnPercent2 != SignalPercent.Any or show3 and dirDnPercent3 != SignalPercent.Any or useAverageDnSignal and dirDnPercentAVG != SignalPercent.Any
var bool useSignalDnR = show1 and dirDnR1 != SignalR.Any or show2 and dirDnR2 != SignalR.Any or show3 and dirDnR3 != SignalR.Any or useAverageDnSignal and dirDnRAVG != SignalR.Any
var bool useSignalAny = useSignalUpPercent or useSignalUpR or useSignalDnPercent or useSignalDnR

//INPUTS - Indicator Settings
g_indicatorSettings = 'Regression Anchor Settings'
//INPUTS - External
externalSRC = input.source(close, title = 'External│Source', inline = 'External', group = g_indicatorSettings, tooltip = tt_ext)
//INPUTS - ADX (Average Directional Index)
adxLen = input.int(14, title = 'ADX│Length', minval = 1, maxval = 500, inline = 'ADX', group = g_indicatorSettings, tooltip = tt_adx)
adxSigLen = input.int(14, title = 'Smooth', minval = 1, maxval = 50, inline = 'ADX', group = g_indicatorSettings)
//INPUTS - ATR (Average True Range)
atrLen = input.int(14, title = 'ATR│Length', minval = 1, inline = 'ATR', group = g_indicatorSettings, tooltip = tt_atr)
atrMA = input.string('RMA', title = 'MA Type', inline = 'ATR', group = g_indicatorSettings, options = ['RMA', 'SMA', 'EMA', 'WMA'])
//INPUTS - BBW (Bollinger Bands Width)
bbwLen = input.int(20, title = 'BBW│Length', minval = 1, maxval = 500, inline = 'BBW', group = g_indicatorSettings, tooltip = tt_bbw)
bbwMult = input.float(2.0, title = 'Mult', minval = 1, maxval = 500, inline = 'BBW', group = g_indicatorSettings)
//INPUTS - CCI (Commodity Channel Index)
cciLen = input.int(20, title = 'CCI│Length', minval = 1, inline = 'CCI', group = g_indicatorSettings, tooltip = tt_cci)
cciSRC = input(hlc3, title = 'Source', inline = 'CCI', group = g_indicatorSettings)
//INPUTS - MACD (Moving Average Convergence Divergence)
macdFast = input(12, title = 'MACD│Fast Length', inline = 'macd', group = g_indicatorSettings)
macdSlow = input(26, title = 'Slow Length', inline = 'macd', group = g_indicatorSettings, tooltip = tt_macd)
macdSRC = input(close, title = 'MACD│Source', inline = 'macd2', group = g_indicatorSettings, tooltip = tt_macd)
macdMA = input.string('EMA', title = 'MA Type', options = ['SMA', 'EMA'], inline = 'macd2', group = g_indicatorSettings, display = display.data_window)
//INPUTS - RSI (Relative Strength Index)
rsiLen = input.int(14, title = 'RSI│Length', minval = 1, inline = 'RSI', group = g_indicatorSettings, tooltip = tt_rsi)
rsiSRC = input.source(close, title = 'Source', inline = 'RSI', group = g_indicatorSettings)
//INPUTS - Stochastic
stochLen = input.int(14, title = 'Stoch│%K Length', minval = 1, inline = 'Stoch', group = g_indicatorSettings, tooltip = tt_stoch)
stochSmooth = input.int(1, title = '%K Smooth', minval = 1, inline = 'Stoch', group = g_indicatorSettings)
//INPUTS - Custom Date/Time
TimeCustom = input.time(timestamp('Jan 01 2025 00:00:00'), title = 'Custom', inline = 'ct', group = g_indicatorSettings, tooltip = tt_Sessions)
showCustomLine = input.bool(true, title='Show Line', inline = 'ct', group = g_indicatorSettings)

//CALCULATE - Custom Time Line
bool useCustomTime = inputType1 == AnchorSource.SessionCustom or inputType2 == AnchorSource.SessionCustom or inputType3 == AnchorSource.SessionCustom or 
     inputType1 == AnchorSource.TimeCustom or inputType2 == AnchorSource.TimeCustom or inputType3 == AnchorSource.TimeCustom
var CustomLineHasBeenShown = false
if showCustomLine and useCustomTime
    if TimeCustom <= time and CustomLineHasBeenShown == false
        line.new(bar_index, close+1, bar_index, close-1, extend = extend.both, color = color.new(chart.fg_color, 80))
        CustomLineHasBeenShown := true

//INPUTS - Regression Settings
g_regSettings = 'Regression Type Settings'
regRidgeLambda = input.float(10, title='Ridge│L2 Penalty', inline='L2', group=g_regSettings, tooltip=tt_ridge)
regLassoLambda = input.float(1, title='Lasso│L1 Penalty', inline='L1', group=g_regSettings, tooltip=tt_lasso)
regHuberDelta = input.float(0.5, title='Huber│Delta', inline='Huber', group=g_regSettings)
regHuberIterations = input.int(5, title='Iterations', inline='Huber', group=g_regSettings, tooltip=tt_huber)
regLADIterations = input.int(10, title='LAD│Iterations', inline='LAD', group=g_regSettings, tooltip=tt_LAD)
regBayesianPriorMean = input.float(0.0, title='Bayesian│Mean', inline='Bayesian', group=g_regSettings)
regBayesianPriorSpan = input.float(1.0, title='Span', inline='Bayesian', group=g_regSettings)
regBayesianSigma = input.float(1.0, title='Σ', inline='Bayesian', group=g_regSettings, tooltip=tt_bayesian)

//INPUTS - Table Display
g_table = 'Table Display Settings'
tt_displayTable = '█ Display Table\n\n█ Table Location\n\n█ Table Size'
displayTable = input(true, title = 'Display Table', group = g_table, inline = 'Table', tooltip = tt_displayTable)
tablePos = str.replace(str.lower(str.tostring(input.enum(TableLocation.BottomRight, title = '', inline = 'Table', group = g_table, active = displayTable))), ' ', '_')
tableSize = str.lower(str.tostring(input.enum(TableSizes.Normal, title = '', inline = 'Table', group = g_table, active = displayTable)))
displaySelected = input(true, title = 'Input - Displayed (#1,#2,#3,Average)', group = g_table, active = displayTable, tooltip = '█ Displayed (#1,#2,#3,Average)\nDisplayed linear regressions.')
displayInputAnchor = input(true, title = 'Input - Anchor', group = g_table, active = displayTable, tooltip = '█ Anchor\nStarting point type (anchor) for regression.')
displayInputLength = input(true, title = 'Input - Length (Max,Min,Step)', group = g_table, active = displayTable, tooltip = '█ Length (Max,Min,Step)\nLength criteria for regression.')
displayInputRegType = input(true, title = 'Input - Regression Type', group = g_table, active = displayTable, tooltip = '█ Regression Type\nFormula type for Linear Regression.')
displayInputRegBias = input(true, title = 'Input - Regression Bias', group = g_table, active = displayTable, tooltip = '█ Regression Bias\nEMA-Styled Emphasis Weighting.')
displayInputDevType = input(true, title = 'Input - Deviation Type', group = g_table, active = displayTable, tooltip = '█ Deviation Type\nFormula type for Deviations.')
displayInputDevBias = input(true, title = 'Input - Deviation Bias', group = g_table, active = displayTable, tooltip = '█ Deviation Bias\nEMA-Styled Emphasis Weighting.')
displayInputDev = input(true, title = 'Input - Deviation Multiplier', group = g_table, active = displayTable, tooltip = '█ Deviation Multiplier\nStandard deviation multiplier of linear regression.')
displayInputSignal = input(true, title = 'Input - Signal Criteria (Percent and R)', group = g_table, active = displayTable, tooltip = '█ Signal Criteria\nPercent and R criteria for signals. Shown if signal criteria selected.')
displayLength = input(true, title = 'Calculated - Length (LinReg)', group = g_table, active = displayTable, tooltip = '█ Length\nLength of LinReg calculated from the specified anchor and length inputs.')
displayPercent = input(true, title = 'Calculated - Percent (Price vs Deviations)', group = g_table, active = displayTable, tooltip = '█ Percent\n│ ̄100% (Top [+]Deviation)\n│- 50% (Regression Line)\n│_ 0% (Lower [-]Deviation)')
displayCloseDev = input(true, title = 'Calculated - Deviation of Close (ⓒ)', group = g_table, active = displayTable, tooltip = '█ Deviation value of current (close) price).')
displayR = input(true, title = 'Calculated - R (Pearson Correlation Coefficient)', group = g_table, active = displayTable, tooltip = '█ R (Pearson Correlation Coefficient)\nIndicating the strength and direction of the linear relationship between the data points.')
displayR2 = input(false, title = 'Calculated - R² (Determination Coefficient)', group = g_table, active = displayTable, tooltip = '█ R² (Determination Coefficient)\nIndicaties how well the regression predictions approximate the real data points.')
displayAverageAbsR = input(false, title = 'Calculated - │R│ Average (Pearson Correlation Coefficient)', group = g_table, active = displayTable, tooltip = '█ │R│ Average (Pearson Correlation Coefficient)\nAverages all │R│ values, finding average correlation strength of historical regressions.')
displaySlope = input(false, title = 'Calculated - Slope', group = g_table, active = displayTable, tooltip = '█ Slope\nValue of slope.')
displayTrend = input(false, title = 'Calculated - Trend', group = g_table, active = displayTable, tooltip = '█ Trend\nTrend direction.')
displayBarsSide = input(false, title = 'Calculated - Above/Below Regression (↑/↓)', group = g_table, active = displayTable, tooltip = '█ Above/Below Regression (↑/↓)\nCounts closes (or other data source) above and below the regression since the first plot, relative to the current bar\'s position on the line.\n(Counts last bar of each regression only)')
roundPercentType = input.enum(RoundingValue.Decimals, title = 'Format Percent', inline = 'roundPercent', group = g_table, active = displayTable)
roundPercentValue = input.int(1, title = '', minval = 0, maxval = 30, inline = 'roundPercent', group = g_table, active = displayTable, tooltip = "█ Format percent type\n● 'Sig Figs' (significant figures)\n● 'Decimal' points.\n\n█ Format percent value\nValue applied to format.")
roundValueType = input.enum(RoundingValue.SigFigs, title = 'Format Value', inline = 'roundValue', active = displayTable, group = g_table)
roundValueValue = input.int(5, title = '', minval = 1, maxval = 30, inline = 'roundValue', group = g_table, active = displayTable, tooltip = "█ Format values type\n● 'Sig Figs' (significant figures)\n● 'Decimal' points.\n\n█ Format value\nValue applied to format.")

// CHECK - 'ready' is true when calculations can begin (delays until final bar if enabled for efficiency)
bool ready = useSignalAny or (not useSignalAny and barstate.islast)
bool ready1 = useSignalAny or showBands1 or displayBarsSide or displayAverageAbsR or (not useSignalAny and barstate.islast)
bool ready2 = useSignalAny or showBands2 or displayBarsSide or displayAverageAbsR or (not useSignalAny and barstate.islast)
bool ready3 = useSignalAny or showBands3 or displayBarsSide or displayAverageAbsR or (not useSignalAny and barstate.islast)

//FORMAT - Decimal Points
roundFloatToDecimalThenString(_value, _decimals) =>
    scale = math.pow(10, _decimals)
    roundedValue = math.round(_value * scale) / scale
    formatString = '0.' + str.repeat('0', _decimals)
    str.tostring(nz(roundedValue), formatString)

//FORMAT - Significant Figures
roundFloatSigFigsThenString(_value, _sigFigs) =>
    scale = math.pow(10, math.floor(math.log(math.abs(_value)) / math.log(10)) - (_sigFigs - 1))
    roundedValue = math.round(_value / scale) * scale
    magnitude = math.floor(math.log(math.abs(roundedValue)) / math.log(10))
    decimals = _sigFigs - (magnitude + 1)
    formatString = decimals > 0 ? '0.' + str.repeat('0', decimals) : '#'
    str.tostring(nz(roundedValue), formatString)

//FORMAT - Value to String (to either Decimal Points or Significant Figures)
roundValue(_value) => roundValueType == RoundingValue.Decimals ? roundFloatToDecimalThenString(_value, roundValueValue) : roundFloatSigFigsThenString(_value, roundValueValue)

//FORMAT - Percent to String (to either Decimal Points or Significant Figures)
roundPercent(_value) => str.format("{0,number,#,##0.##}%", str.tonumber(roundPercentType == RoundingValue.Decimals ? roundFloatToDecimalThenString(_value, roundPercentValue) : roundFloatSigFigsThenString(_value, math.max(roundPercentValue,1))))

//GET - Converts input strings to usable strings for plotting linear regression channel
getExtendString(_extendLines) => _extendLines == ExtensionType.ExtendNo ? extend.none : _extendLines == ExtensionType.ExtendRight ? extend.right : _extendLines == ExtensionType.ExtendLeft ? extend.left : extend.both
getStyleString(_channelStyle) => _channelStyle == LineStyle.Dashed ? line.style_dashed : _channelStyle == LineStyle.Dotted ? line.style_dotted : line.style_solid

//INPUTS - Regression Display Options
g_regStyle = '🎨Linear Regression Color Options'

//INPUTS - Colors
//-----#1-----
g_colorOptions = '🎨Linear Regression Color Options'
col_channelUp1 = input.color(#78ff7a, title = '#1 Channel', inline = '#1', group = g_colorOptions)
col_channelDn1 = input.color(#ff7878, title = '', inline = '#1', group = g_colorOptions)
col_channelUpFill1 = input.color(color.new(color.yellow, 90), title = '', inline = '#1', group = g_colorOptions)
col_channelDnFill1 = input.color(color.new(color.yellow, 90), title = '', inline = '#1', group = g_colorOptions, tooltip = tt_styling)
channelExtend1 = getExtendString(input.enum(ExtensionType.ExtendNo, title = '', inline = '#1', group = g_colorOptions))
channelStyle1 = getStyleString(input.enum(LineStyle.Dashed, title = '', inline = '#1', group = g_colorOptions))
col_showBands1 = input.color(color.orange, title = '  #1 Bands', inline = '#1', group = g_colorOptions)
col_showMid1 = input.color(color.orange, title = '', inline = '#1', group = g_colorOptions)
col_bandsFill1 = input.color(color.new(color.orange, 85), title = '', inline = '#1', group = g_colorOptions)
lineWidth1 = input.int(1, title = 'Line Width', inline = '#1', group = g_colorOptions, minval = 1, maxval = 10)
//-----#2-----
col_channelUp2 = input.color(#00db04, title = '#2 Channel', inline = '#2', group = g_colorOptions)
col_channelDn2 = input.color(#db0000, title = '', inline = '#2', group = g_colorOptions)
col_channelUpFill2 = input.color(color.new(color.orange, 90), title = '', inline = '#2', group = g_colorOptions)
col_channelDnFill2 = input.color(color.new(color.orange, 90), title = '', inline = '#2', group = g_colorOptions)
channelExtend2 = getExtendString(input.enum(ExtensionType.ExtendNo, title = '', inline = '#2', group = g_colorOptions))
channelStyle2 = getStyleString(input.enum(LineStyle.Dotted, title = '', inline = '#2', group = g_colorOptions))
col_showBands2 = input.color(color.purple, title = '  #2 Bands', inline = '#2', group = g_colorOptions)
col_showMid2 = input.color(color.purple, title = '', inline = '#2', group = g_colorOptions)
col_bandsFill2 = input.color(color.new(color.purple, 85), title = '', inline = '#2', group = g_colorOptions)
lineWidth2 = input.int(1, title = 'Line Width', inline = '#2', group = g_colorOptions, minval = 1, maxval = 10)
//-----#3-----
col_channelUp3 = input.color(#00630a, title = '#3 Channel', inline = '#3', group = g_colorOptions)
col_channelDn3 = input.color(#630008, title = '', inline = '#3', group = g_colorOptions)
col_channelUpFill3 = input.color(color.new(#F2D2BD, 90), title = '', inline = '#3', group = g_colorOptions)
col_channelDnFill3 = input.color(color.new(#F2D2BD, 90), title = '', inline = '#3', group = g_colorOptions)
channelExtend3 = getExtendString(input.enum(ExtensionType.ExtendNo, title = '', inline = '#3', group = g_colorOptions))
channelStyle3 = getStyleString(input.enum(LineStyle.Solid, title = '', inline = '#3', group = g_colorOptions))
col_showBands3 = input.color(color.aqua, title = '  #3 Bands', inline = '#3', group = g_colorOptions)
col_showMid3 = input.color(color.aqua, title = '', inline = '#3', group = g_colorOptions)
col_bandsFill3 = input.color(color.new(color.aqua, 85), title = '', inline = '#3', group = g_colorOptions)
lineWidth3 = input.int(1, title = 'Line Width', inline = '#3', group = g_colorOptions, minval = 1, maxval = 10)

//INPUTS - MISC. SETTINGS
g_misc = 'MISC. Options'
adaptiveLength = input.bool(true, title = 'Adaptive Lookback', inline = 'adaptive', group = g_misc, tooltip=tt_adapative)
stepWarning = input.bool(true, title = 'Warning if Step greator than 1 used', inline = 'warning', group = g_misc, tooltip=tt_stepWarning)
displayExternalUse = input.bool(false, title = 'Display Values For External Use', inline = 'type', group = g_misc, tooltip = tt_displayForExternal)
signalLocation = input.enum(SignalLabelStyle.Top, title = 'Signals Location (Entry/Exit)', inline = 'Sig', group = g_misc, tooltip = tt_signalsTypes)

//CALCULATE - Deviations
calcDev(series string _inputDevOption, float _src, int _len, float _slope, float _y1, _inputDev, _condition, _emphasis) =>
    switch _inputDevOption
        str.tostring(DeviationType.Reverse)  => LR.calcDevReverse(_src, _len, _slope, _y1, _inputDev, _emphasis, _condition)  //Reverse Linear Deviation
        str.tostring(DeviationType.Forward)  => LR.calcDevForward(_src, _len, _slope, _y1, _inputDev, _emphasis, _condition)  //Forward Linear Deviation
        str.tostring(DeviationType.Balanced) => LR.calcDevBalanced(_src, _len, _slope, _y1, _inputDev, _emphasis, _condition) //Balanced Linear Deviation
        str.tostring(DeviationType.Mean)     => LR.calcDevMean(_src, _len, _slope, _y1, _inputDev, _emphasis, _condition)     //Mean Absolute Deviation
        str.tostring(DeviationType.Median)   => LR.calcDevMedian(_src, _len, _slope, _y1, _inputDev, _emphasis, _condition)   //Median Absolute Deviation
        str.tostring(DeviationType.Percent)  => LR.calcDevPercent(_y1, _inputDev, _condition)                                 //Percent Deviation
        str.tostring(DeviationType.ATR)      => LR.calcDevATR(_src, _len, _slope, _y1, _inputDev, _emphasis, _condition)      //Average True Range Deviation
        str.tostring(DeviationType.Fitted)   => LR.calcDevFitted(_len, _slope, _y1, _emphasis, _condition)                    //Fitted Deviation
        => [float(na), float(na)] //Default

//CALCULATE - Earnings, Dividends, Splits (Functions are used as cannot call 'request.*()' function inside 'switch')
new_earnings() => request.earnings(syminfo.tickerid, earnings.actual, barmerge.gaps_on, barmerge.lookahead_on, ignore_invalid_symbol = true)
new_dividends() => request.dividends(syminfo.tickerid, dividends.gross, barmerge.gaps_on, barmerge.lookahead_on, ignore_invalid_symbol = true)
new_split() => request.splits(syminfo.tickerid, splits.denominator, barmerge.gaps_on, barmerge.lookahead_on, ignore_invalid_symbol = true)

//CALCULATE - ADX
calcADX(_len, _adxSigLen) =>
    up = ta.change(high)
    down = -ta.change(low)
    trur = ta.rma(ta.tr, _len)
    plus = fixnan(100 * ta.rma(up > down and up > 0 ? up : 0, _len) / trur)
    minus = fixnan(100 * ta.rma(down > up and down > 0 ? down : 0, _len) / trur)
    sum = plus + minus
    adx = 100 * ta.rma(math.abs(plus - minus) / (sum == 0 ? 1 : sum), _adxSigLen)
    adx

//CHECK - Give an error if volume volume is require in the calculation, but not available
checkVolume(_calc) =>
    var cumVol = 0.
    cumVol := cumVol + nz(volume)
    int val = 0
    if barstate.islast and cumVol == 0
        runtime.error('Please select a non-Volume source. No volume is provided by the data vendor.')
    else
        val := _calc
    val

//CALCULATE - Lowest check (Finds highest value in range - checks all each bar to allow repainting external indicator)
checkHighest(float _src, int _len, int _minLen, int _step, int _barIndex) =>
    float highestValue = -999999999999999999999.9
    int highestBar = 0
    for i = _minLen > _len ? 2 : _minLen - 1 to _len < _barIndex ? math.min(_len - 1, highestBar[1] + 1) : _len by _step
        if _src[i] > highestValue
            highestValue := _src[i]
            highestBar := i
            highestBar
    highestBar + 1

//CALCULATE - Lowest check (Finds lowest value in range - checks all each bar to allow repainting external indicator)
checkLowest(float _src, int _len, int _minLen, int _step, int _barIndex) =>
    float lowestValue = 999999999999999999999.9
    int lowestBar = 0
    for i = _minLen > _len ? 2 : _minLen - 1 to _len < _barIndex ? math.min(_len - 1, lowestBar[1] + 1) : _len by _step
        if _src[i] < lowestValue
            lowestValue := _src[i]
            lowestBar := i
            lowestBar
    lowestBar + 1

//CALCULATE - Highest check efficiently (Finds highest value in range, efficiently avoids using for loop unless 1st check or highest expired)
checkHighestEfficiently(float _src, int _len, int _minLen, int _step) =>
    var float cachedValue = na
    var int cachedIndex = na
    if na(cachedValue) or cachedIndex >= _len - 1
        cachedValue := -999999999999
        cachedIndex := _len - 1
        for i = _minLen - 1 to _len - 1 by _step
            if _src[i] > cachedValue
                cachedValue := _src[i]
                cachedIndex := i
    else
        cachedIndex += 1
        if _src[_minLen-1] >= cachedValue
            cachedValue := _src[_minLen-1]
            cachedIndex := _minLen-1
    barsSince = cachedIndex + 1
    barsSince < _minLen ? _minLen : barsSince

//CALCULATE - Lowest check efficiently (Finds lowest value in range, efficiently avoids using for loop unless 1st check or lowest expired)
checkLowestEfficiently(float _src, int _len, int _minLen, int _step) =>
    var float cachedValue = na
    var int cachedIndex = na
    if na(cachedValue) or cachedIndex >= _len - 1
        cachedValue := 999999999999
        cachedIndex := _len - 1
        for i = _minLen - 1 to _len - 1 by _step
            if _src[i] < cachedValue
                cachedValue := _src[i]
                cachedIndex := i
    else
        cachedIndex += 1
        if _src[_minLen-1] <= cachedValue
            cachedValue := _src[_minLen-1]
            cachedIndex := _minLen-1
    barsSince = cachedIndex + 1
    barsSince < _minLen ? _minLen : barsSince

//CALCULATE - Time check
dailyTimeCheck(start_hour,start_min) =>
    t = time
    tz = 'UTC'
    t >= timestamp(tz, year(t, tz), month(t, tz), dayofmonth(t, tz), start_hour, start_min) and t[1] < timestamp(tz, year(t, tz), month(t, tz), dayofmonth(t, tz), start_hour, start_min)

//CALCULATE - Length from Anchor Source
calcLength(_inputTypeLength, _maxLengthInput, _minLengthInput, _step, _inputSource, _lengthOld, _barIndex, _condition) =>

    _maxLength = math.max(_maxLengthInput, 2) //LinReg requires at least 2 data points and minimum must be lower than
    _minLength = _minLengthInput > _maxLength ? 2 : _minLengthInput //Calculations cannot have a min length greator than max length
    _maxLength := adaptiveLength ? (_maxLength > _barIndex+1 ? _barIndex+1 : _maxLength) : _maxLength //Adaptive length, sets length to max available bars if less than length input

    switch _inputTypeLength
        //PRICE
        AnchorSource.BarHighest => checkHighestEfficiently(high, _maxLength, _minLength, _step)
        AnchorSource.BarLowest => checkLowestEfficiently(low, _maxLength, _minLength, _step)
        //INDICATORS
        AnchorSource.VolHighest => checkVolume(checkHighestEfficiently(volume, _maxLength, _minLength, _step))
        AnchorSource.VolLowest => checkVolume(checkLowestEfficiently(volume, _maxLength, _minLength, _step))
        AnchorSource.AdxHighest => checkHighestEfficiently(calcADX(adxLen, adxSigLen), _maxLength, _minLength, _step)
        AnchorSource.AdxLowest => checkLowestEfficiently(calcADX(adxLen, adxSigLen), _maxLength, _minLength, _step)
        AnchorSource.AtrHighest => checkHighestEfficiently(atrMA == 'RMA' ? ta.rma(ta.tr(true), atrLen) : atrMA == 'SMA' ? ta.sma(ta.tr(true), atrLen) : atrMA == 'EMA' ? ta.ema(ta.tr(true), atrLen) : ta.wma(ta.tr(true), atrLen), _maxLength, _minLength, _step)
        AnchorSource.AtrLowest => checkLowestEfficiently(atrMA == 'RMA' ? ta.rma(ta.tr(true), atrLen) : atrMA == 'SMA' ? ta.sma(ta.tr(true), atrLen) : atrMA == 'EMA' ? ta.ema(ta.tr(true), atrLen) : ta.wma(ta.tr(true), atrLen), _maxLength, _minLength, _step)
        AnchorSource.BbwHighest => checkHighestEfficiently(ta.bbw(close, bbwLen, bbwMult), _maxLength, _minLength, _step)
        AnchorSource.BbwLowest => checkLowestEfficiently(ta.bbw(close, bbwLen, bbwMult), _maxLength, _minLength, _step)
        AnchorSource.CciHighest => checkHighestEfficiently((cciSRC - ta.sma(cciSRC, cciLen)) / (0.015 * ta.dev(cciSRC, cciLen)), _maxLength, _minLength, _step)
        AnchorSource.CciLowest => checkLowestEfficiently((cciSRC - ta.sma(cciSRC, cciLen)) / (0.015 * ta.dev(cciSRC, cciLen)), _maxLength, _minLength, _step)
        AnchorSource.MacdHighest => checkHighestEfficiently((macdMA == 'SMA' ? ta.sma(macdSRC, macdFast) : ta.ema(macdSRC, macdFast)) - (macdMA == 'SMA' ? ta.sma(macdSRC, macdSlow) : ta.ema(macdSRC, macdSlow)), _maxLength, _minLength, _step)
        AnchorSource.MacdLowest => checkLowestEfficiently((macdMA == 'SMA' ? ta.sma(macdSRC, macdFast) : ta.ema(macdSRC, macdFast)) - (macdMA == 'SMA' ? ta.sma(macdSRC, macdSlow) : ta.ema(macdSRC, macdSlow)), _maxLength, _minLength, _step)
        AnchorSource.RsiHighest => checkHighestEfficiently(ta.rsi(rsiSRC, rsiLen), _maxLength, _minLength, _step)
        AnchorSource.RsiLowest => checkLowestEfficiently(ta.rsi(rsiSRC, rsiLen), _maxLength, _minLength, _step)
        AnchorSource.StochHighest => checkHighestEfficiently(ta.sma(ta.stoch(close, high, low, stochLen), stochSmooth), _maxLength, _minLength, _step)
        AnchorSource.StochLowest => checkLowestEfficiently(ta.sma(ta.stoch(close, high, low, stochLen), stochSmooth), _maxLength, _minLength, _step)
        AnchorSource.SpreadHighest => checkHighestEfficiently(high - low, _maxLength, _minLength, _step)
        AnchorSource.SpreadLowest => checkLowestEfficiently(high - low, _maxLength, _minLength, _step)
        //SLOPE
        AnchorSource.SlopeZero => LR.calcSlopeLengthZero(_inputSource, _maxLength, _minLength, _step, _condition)
        AnchorSource.SlopeHighest => LR.calcSlopeLengthHighest(_inputSource, _maxLength, _minLength, _step, _condition)
        AnchorSource.SlopeLowest => LR.calcSlopeLengthLowest(_inputSource, _maxLength, _minLength, _step, _condition)
        AnchorSource.SlopeAbsolute => LR.calcSlopeLengthAbsolute(_inputSource, _maxLength, _minLength, _step, _condition)
        //R
        AnchorSource.RZero => LR.calcRLengthZero(_inputSource, _maxLength, _minLength, _step, _condition)
        AnchorSource.RHighest => LR.calcRLengthHighest(_inputSource, _maxLength, _minLength, _step, _condition)
        AnchorSource.RLowest => LR.calcRLengthLowest(_inputSource, _maxLength, _minLength, _step, _condition)
        AnchorSource.RAbsolute => LR.calcRLengthAbsolute(_inputSource, _maxLength, _minLength, _step, _condition)
        //TIME
        AnchorSource.TimeDay => math.min(_maxLength, timeframe.in_seconds(timeframe.period) < 86400 ? timeframe.change('D')[1] ? 2 : _lengthOld + 1 : 1)
        AnchorSource.TimeWeek => math.min(_maxLength, timeframe.in_seconds(timeframe.period) < timeframe.in_seconds('W') ? timeframe.change('W')[1] ? 2 : _lengthOld + 1 : 1)
        AnchorSource.TimeMonth => math.min(_maxLength, timeframe.in_seconds(timeframe.period) < timeframe.in_seconds('M') ? timeframe.change('M')[1] ? 2 : _lengthOld + 1 : 1)
        AnchorSource.TimeQuarter => math.min(_maxLength, timeframe.in_seconds(timeframe.period) < timeframe.in_seconds('3M') ? timeframe.change('3M')[1] ? 2 : _lengthOld + 1 : 1)
        AnchorSource.TimeYear => math.min(_maxLength, timeframe.in_seconds(timeframe.period) < timeframe.in_seconds('12M') ? timeframe.change('12M')[1] ? 2 : _lengthOld + 1 : 1)
        AnchorSource.TimeDecade => math.min(_maxLength, timeframe.change('12M')[1] and year % 10 == 0 ? 2 : _lengthOld + 1)
        AnchorSource.TimeCustom => math.min(_maxLength, TimeCustom == time[1] or (TimeCustom < time[1] and _lengthOld < 2) ? 2 : _lengthOld > 1 ? _lengthOld + 1 : 1)
        //EVENTS
        AnchorSource.Earnings => math.min(_maxLength, not na(new_earnings())[1] ? 2 : _lengthOld > 1 ? _lengthOld + 1 : _lengthOld)
        AnchorSource.Dividends => math.min(_maxLength, not na(new_dividends())[1] ? 2 : _lengthOld > 1 ? _lengthOld + 1 : _lengthOld)
        AnchorSource.Splits => math.min(_maxLength, not na(new_split())[1] ? 2 : _lengthOld > 1 ? _lengthOld < 4000 ? _lengthOld + 1 : 1 : _lengthOld)
        //SESSIONS
        AnchorSource.SessionTokyo => math.min(_maxLength, dailyTimeCheck(timeTokyo.hour,timeTokyo.minute) ? 1 : _lengthOld + 1)
        AnchorSource.SessionLondon => math.min(_maxLength, dailyTimeCheck(timeLondon.hour,timeLondon.minute) ? 1 : _lengthOld + 1)
        AnchorSource.SessionNewYork => math.min(_maxLength, dailyTimeCheck(timeNewYork.hour,timeNewYork.minute) ? 1 : _lengthOld + 1)
        AnchorSource.SessionSydney => math.min(_maxLength, dailyTimeCheck(timeSydney.hour,timeSydney.minute) ? 1 : _lengthOld + 1)
        AnchorSource.SessionChart => math.min(_maxLength, session.isfirstbar[1] ? 2 : _lengthOld > 1 ? _lengthOld + 1 : 1)
        AnchorSource.SessionCustom => math.min(_maxLength, dailyTimeCheck(hour(TimeCustom), minute(TimeCustom)) ? 1 : _lengthOld + 1)
        //EXTERNAL
        AnchorSource.ExternalHighest => checkHighest(externalSRC, _maxLength, _minLength, _step, _barIndex)
        AnchorSource.ExternalLowest => checkLowest(externalSRC, _maxLength, _minLength, _step, _barIndex)
        //SOURCE
        AnchorSource.SourceHighest => checkHighest(_inputSource, _maxLength, _minLength, _step, _barIndex)
        AnchorSource.SourceLowest => checkLowest(_inputSource, _maxLength, _minLength, _step, _barIndex)
        //DEFAULT
        => _maxLength

//CALCULATE - Function to transform source data based on scale
transformSource(source) => scaleTypeLog ? math.log10(source) : source

//CALCULATE - Function to reverse transform for plotting
reverseTransform(value) => scaleTypeLog ? math.pow(10, value) : value

//CALCULATE - Transform input sources based on scale
src1_transformed = transformSource(inputSource1)
src2_transformed = transformSource(inputSource2)
src3_transformed = transformSource(inputSource3)

//INITIALIZE - First bar length is set to 1 as LinReg calculations require at least 2 data points. (if length is 1, it can't be displayed)
var len1 = 1
var len2 = 1
var len3 = 1

//INITIALIZE - Bar Index, tracked for a data source that doesn't match the index of the chart's price
var barIndex1 = 0
var barIndex2 = 0
var barIndex3 = 0
barIndex1 := na(src1_transformed[1]) ? barIndex1 : barIndex1+1
barIndex2 := na(src2_transformed[1]) ? barIndex2 : barIndex2+1
barIndex3 := na(src3_transformed[1]) ? barIndex3 : barIndex3+1

//CALCULATE - Lengths for each LinReg (must be at a minimum 1 and at a maximum max_bars)
len1 := show1 ? math.max(1, math.min(max_bars, calcLength(inputType1, inputMax1, inputMin1, inputStep1, src1_transformed, len1, barIndex1, ready1))) : 1
len2 := show2 ? math.max(1, math.min(max_bars, calcLength(inputType2, inputMax2, inputMin2, inputStep2, src2_transformed, len2, barIndex2, ready2))) : 1
len3 := show3 ? math.max(1, math.min(max_bars, calcLength(inputType3, inputMax3, inputMin3, inputStep3, src3_transformed, len3, barIndex3, ready3))) : 1

//CALCULATE - Linear Regression
calcRegression(float _src, int _len, RegressionType _type, bool _condition, float _emphasis = 0) =>
    switch _type
        RegressionType.Standard   => LR.calcRegStandard(_src, _len, _emphasis, _condition)
        RegressionType.Ridge      => LR.calcRegRidge(_src, _len, regRidgeLambda, _emphasis, _condition)
        RegressionType.Lasso      => LR.calcRegLasso(_src, _len, regLassoLambda, _emphasis, _condition)
        RegressionType.ElasticNet => LR.calcElasticNetLinReg(_src, _len, regLassoLambda, regRidgeLambda, _emphasis, _condition)
        RegressionType.Huber      => LR.calcRegHuber(_src, _len, regHuberDelta, regHuberIterations, _emphasis, _condition)
        RegressionType.Bayesian   => LR.calcRegBayesian(_src, _len, regBayesianPriorMean, regBayesianPriorSpan, regBayesianSigma, _emphasis, _condition)
        RegressionType.LAD        => LR.calcRegLAD(_src, _len, regLADIterations, _emphasis, _condition)
        => [float(na), float(na), float(na), float(na)] // Default
[y1_1, y2_1, slope1, average1] = calcRegression(src1_transformed, len1, inputRegType1, ready1, inputRegWeight1)
[y1_2, y2_2, slope2, average2] = calcRegression(src2_transformed, len2, inputRegType2, ready2, inputRegWeight2)
[y1_3, y2_3, slope3, average3] = calcRegression(src3_transformed, len3, inputRegType3, ready3, inputRegWeight3)

//CALCULATE - Reverse transform of y1 and y2
y1_1_plot = reverseTransform(y1_1)
y2_1_plot = reverseTransform(y2_1)
y1_2_plot = reverseTransform(y1_2)
y2_2_plot = reverseTransform(y2_2)
y1_3_plot = reverseTransform(y1_3)
y2_3_plot = reverseTransform(y2_3)

//CALCULATE - Deviations
[topDev1, botDev1] = calcDev(show1 ? str.tostring(inputDevType1) : '', src1_transformed, len1, slope1, y1_1, inputDev1, ready1, inputDevWeight1)
[topDev2, botDev2] = calcDev(show2 ? str.tostring(inputDevType2) : '', src2_transformed, len2, slope2, y1_2, inputDev2, ready2, inputDevWeight2)
[topDev3, botDev3] = calcDev(show3 ? str.tostring(inputDevType3) : '', src3_transformed, len3, slope3, y1_3, inputDev3, ready3, inputDevWeight3)

//CALCULATE - Reverse transform for deviations plotting
topDev1_plot = reverseTransform(topDev1)
botDev1_plot = reverseTransform(botDev1)
topDev2_plot = reverseTransform(topDev2)
botDev2_plot = reverseTransform(botDev2)
topDev3_plot = reverseTransform(topDev3)
botDev3_plot = reverseTransform(botDev3)

//CALCULATE - Prices for plotting with scale-aware deviations
topPrice1 = scaleTypeLog ? y2_1_plot * math.pow(10, topDev1) : y2_1_plot + topDev1
botPrice1 = scaleTypeLog ? y2_1_plot * math.pow(10, botDev1) : y2_1_plot + botDev1
topPrice2 = scaleTypeLog ? y2_2_plot * math.pow(10, topDev2) : y2_2_plot + topDev2
botPrice2 = scaleTypeLog ? y2_2_plot * math.pow(10, botDev2) : y2_2_plot + botDev2
topPrice3 = scaleTypeLog ? y2_3_plot * math.pow(10, topDev3) : y2_3_plot + topDev3
botPrice3 = scaleTypeLog ? y2_3_plot * math.pow(10, botDev3) : y2_3_plot + botDev3

//CALCULATE - R (Pearson Correlation Coefficient)
pearsonR_1 = float(na)
pearsonR_2 = float(na)
pearsonR_3 = float(na)
if displayR or displayR2 or displayAverageAbsR or useSignalUpR or useSignalDnR
    pearsonR_1 := show1 ? LR.calcRFromLinReg(src1_transformed, len1, slope1, average1, y1_1, ready1) : float(na)
    pearsonR_2 := show2 ? LR.calcRFromLinReg(src2_transformed, len2, slope2, average2, y1_2, ready2) : float(na)
    pearsonR_3 := show3 ? LR.calcRFromLinReg(src3_transformed, len3, slope3, average3, y1_3, ready3) : float(na)

//CALCULATE - Percent position of price vs deviations
calcPricePositionPercent(float top, float bot, float price) =>
    scaleTypeLog ?
         100 * (price - math.log10(bot)) / (math.log10(top) - math.log10(bot)) :
         100 * (price - bot) / (top - bot)
percent1 = calcPricePositionPercent(topPrice1, botPrice1, src1_transformed)
percent2 = calcPricePositionPercent(topPrice2, botPrice2, src2_transformed)
percent3 = calcPricePositionPercent(topPrice3, botPrice3, src3_transformed)

//CALCULATE - Averages (Percent, Slope, R)
float percentAVG = ((show1 ? percent1 : 0) + (show2 ? percent2 : 0) + (show3 ? percent3 : 0)) / showCount
float slopeAVG = ((show1 ? slope1 : 0) + (show2 ? slope2 : 0) + (show3 ? slope3 : 0)) / showCount
float pearsonR_AVG = ((show1 ? pearsonR_1 : 0) + (show2 ? pearsonR_2 : 0) + (show3 ? pearsonR_3 : 0)) / showCount

//CALCULATE - Average Absolute Pearson's R, for info table
var pearsonR_count = 0
var pearsonR_total_1 = 0.0
var pearsonR_total_2 = 0.0
var pearsonR_total_3 = 0.0
var pearsonR_total_AVG = 0.0
if displayAverageAbsR
    pearsonR_count := not na(pearsonR_1) ? pearsonR_count+1 : pearsonR_count
    pearsonR_total_1 := not na(pearsonR_1) ? pearsonR_total_1 + math.abs(pearsonR_1) : pearsonR_total_1
    pearsonR_total_2 := not na(pearsonR_2) ? pearsonR_total_2 + math.abs(pearsonR_2) : pearsonR_total_2
    pearsonR_total_3 := not na(pearsonR_3) ? pearsonR_total_3 + math.abs(pearsonR_3) : pearsonR_total_3

//CALCULATE - Deviation multiples (×) for close
calcDeviationMultiple(_topPrice, _botPrice, _priceTransformed, _devX) =>
    _pct = calcPricePositionPercent(_topPrice, _botPrice, _priceTransformed)   // 0..100 with log handling
    (_pct - 50.0) / 50.0 * _devX                                               // mid=0, top=+✕, bot=−✕
devClose1 = show1 and len1 > 1 ? calcDeviationMultiple(topPrice1, botPrice1, src1_transformed, inputDev1) : na
devClose2 = show2 and len2 > 1 ? calcDeviationMultiple(topPrice2, botPrice2, src2_transformed, inputDev2) : na
devClose3 = show3 and len3 > 1 ? calcDeviationMultiple(topPrice3, botPrice3, src3_transformed, inputDev3) : na
devCloseAVG = showCount > 0 ? ((show1 ? nz(devClose1) : 0) + (show2 ? nz(devClose2) : 0) + (show3 ? nz(devClose3) : 0)) / showCount : na
devXAvg = showCount > 0 ? ((show1 ? inputDev1 : 0) + (show2 ? inputDev2 : 0) + (show3 ? inputDev3 : 0)) / showCount : na

//CALCULATE - Check for signals
checkSignal(_currentSignal, _len, _dirUpPercent, _valUpPercent, _triggerPercent, _dirUpR, _valUpR, _triggerR, _isAverage = false) =>
    sig = _currentSignal
    if _isAverage or (1 < _len)
        // Check Percent Signals
        if _dirUpPercent == SignalPercent.Above and _valUpPercent > _triggerPercent
            sig := false
        else if _dirUpPercent == SignalPercent.Below and _valUpPercent < _triggerPercent
            sig := false
        // Check Pearson's R Signals
        if _dirUpR == SignalR.Above and _triggerR < _valUpR
            sig := false
        else if _dirUpR == SignalR.Below and _triggerR > _valUpR
            sig := false
        else if _dirUpR == SignalR.AbsAbove and math.abs(_triggerR) < math.abs(_valUpR)
            sig := false
        else if _dirUpR == SignalR.AbsBelow and math.abs(_triggerR) > math.abs(_valUpR)
            sig := false
        else if _dirUpR == SignalR.Mid and math.abs(_triggerR) > math.abs(_valUpR)
            sig := false
    else
        sig := false
    sig

//CALCULATE - Calls function to check signals
if useSignalUpAny and (useSignalUpPercent or useSignalUpR)
    bigUp := show1 and bigUp ? checkSignal(bigUp, len1, dirUpPercent1, valUpPercent1, percent1, dirUpR1, valUpR1, pearsonR_1) : bigUp
    bigUp := show2 and bigUp ? checkSignal(bigUp, len2, dirUpPercent2, valUpPercent2, percent2, dirUpR2, valUpR2, pearsonR_2) : bigUp
    bigUp := show3 and bigUp ? checkSignal(bigUp, len3, dirUpPercent3, valUpPercent3, percent3, dirUpR3, valUpR3, pearsonR_3) : bigUp
    bigUp := useAverageUpSignal and bigUp ? checkSignal(bigUp, 0, dirUpPercentAVG, valUpPercentAVG, percentAVG, dirUpRAVG, valUpRAVG, pearsonR_AVG, true) : bigUp
else
    bigUp := false
if useSignalDnAny and (useSignalDnPercent or useSignalDnR)
    bigDown := show1 and bigDown ? checkSignal(bigDown, len1, dirDnPercent1, valDnPercent1, percent1, dirDnR1, valDnR1, pearsonR_1) : bigDown
    bigDown := show2 and bigDown ? checkSignal(bigDown, len2, dirDnPercent2, valDnPercent2, percent2, dirDnR2, valDnR2, pearsonR_2) : bigDown
    bigDown := show3 and bigDown ? checkSignal(bigDown, len3, dirDnPercent3, valDnPercent3, percent3, dirDnR3, valDnR3, pearsonR_3) : bigDown
    bigDown := useAverageDnSignal and bigDown ? checkSignal(bigDown, 0, dirDnPercentAVG, valDnPercentAVG, percentAVG, dirDnRAVG, valDnRAVG, pearsonR_AVG, true) : bigDown
else
    bigDown := false

//PLOT - Bands of LinReg and Deviations
//bgcolor(color = not na(topPrice1) ? color.blue : na)
plotBandTopPrice1 = plot(showBands1 ? topPrice1 : na, color = col_showBands1, title = 'Band #1 - Positive Deviation (Top)', editable = false)
plotBandMidPrice1 = plot(showBands1 ? y2_1_plot : na, color = col_showMid1, title = 'Band #1 - Linear Regression (Mid)', editable = false)
plotBandBotPrice1 = plot(showBands1 ? botPrice1 : na, color = col_showBands1, title = 'Band #1 - Negative Deviation (Bottom)', editable = false)
plotBandTopPrice2 = plot(showBands2 ? topPrice2 : na, color = col_showBands2, title = 'Band #2 - Positive Deviation (Top)', editable = false)
plotBandMidPrice2 = plot(showBands2 ? y2_2_plot : na, color = col_showMid2, title = 'Band #2 - Linear Regression (Mid)', editable = false)
plotBandBotPrice2 = plot(showBands2 ? botPrice2 : na, color = col_showBands2, title = 'Band #2 - Negative Deviation (Bottom)', editable = false)
plotBandTopPrice3 = plot(showBands3 ? topPrice3 : na, color = col_showBands3, title = 'Band #3 - Positive Deviation (Top)', editable = false)
plotBandMidPrice3 = plot(showBands3 ? y2_3_plot : na, color = col_showMid3, title = 'Band #3 - Linear Regression (Mid)', editable = false)
plotBandBotPrice3 = plot(showBands3 ? botPrice3 : na, color = col_showBands3, title = 'Band #3 - Negative Deviation (Bottom)', editable = false)
fill(plotBandTopPrice1, plotBandMidPrice1, topPrice1, y2_1_plot, col_bandsFill1, na)
fill(plotBandTopPrice2, plotBandMidPrice2, topPrice2, y2_2_plot, col_bandsFill2, na)
fill(plotBandTopPrice3, plotBandMidPrice3, topPrice3, y2_3_plot, col_bandsFill3, na)
fill(plotBandBotPrice1, plotBandMidPrice1, botPrice1, y2_1_plot, col_bandsFill1, na)
fill(plotBandBotPrice2, plotBandMidPrice2, botPrice2, y2_2_plot, col_bandsFill2, na)
fill(plotBandBotPrice3, plotBandMidPrice3, botPrice3, y2_3_plot, col_bandsFill3, na)

//CALCULATE - Signal Value for external indicator use (OSCILLATOR)
getSignalValue(_SigUp, _SigDn, _Up, _Dn) => _SigUp and _SigDn ? _Up and _Dn ? 3 : _Dn ? 2 : _Up ? 1 : 0 : _SigUp ? _Up ? 1 : 0 : _SigDn ? _Dn ? 2 : 0 : na

//PLOT - Signals (OSCILLATOR)
plot(displayExternalUse ? getSignalValue(useSignalUpAny, useSignalDnAny, bigUp, bigDown) : na, title = 'Signals (0=none,entry=1,entry=2,entry&exit=3) (External Use)', display = displayExternalUse ? display.all : display.none)

//PLOT - Signals (OVERLAY)
var mixed_color = color.rgb(math.round((color.r(colUp) + color.r(colDn)) / 2), math.round((color.g(colUp) + color.g(colDn)) / 2), math.round((color.b(colUp) + color.b(colDn)) / 2))
bigSignalCol = bigUp and bigDown ? mixed_color : bigUp ? colUp : bigDown ? colDn : na
bgcolor(signalLocation == SignalLabelStyle.BG ? bigSignalCol == mixed_color or bigSignalCol == colUp or bigSignalCol == colDn ? color.new(bigSignalCol, 85) : na : na, title = 'Signals (Background Color)')
plotshape(signalLocation == SignalLabelStyle.Top or signalLocation == SignalLabelStyle.Bottom, style = shape.circle, color = bigSignalCol, location = signalLocation == SignalLabelStyle.Top ? location.top : location.bottom, size = size.tiny, title = 'Signals (Top/Bottom of chart)', display = signalLocation == SignalLabelStyle.Top or signalLocation == SignalLabelStyle.Bottom ? display.all : display.none)
plotshape(signalLocation == SignalLabelStyle.Price and bigDown, style = shape.triangledown, color = bigSignalCol, location = location.abovebar, size = size.normal, title = 'Signals (Above Price)', display = signalLocation == SignalLabelStyle.Price ? display.all : display.none)
plotshape(signalLocation == SignalLabelStyle.Price and bigUp, style = shape.triangleup, color = bigSignalCol, location = location.belowbar, size = size.normal, title = 'Signals (Below Price)', display = signalLocation == SignalLabelStyle.Price ? display.all : display.none)

//COLORS - Table
const color col_tblInputs = color.rgb(94, 182, 255)
const color col_tblCalculations = color.white
const color col_tblHeadingBG = #000000
const color col_tblContentBG = color.black

//TABLE - Create Info Table
var infobox = table.new(tablePos, 20, 20)

//TABLE - Create Warning Table
var stepWarningTable = table.new(str.tostring(tablePos) == str.replace(str.lower(str.tostring(TableLocation.MiddleRight)), " ", "_") ? position.bottom_right : position.middle_right, 1, 1, bgcolor = col_tblContentBG)

//TABLE - Create table cell
createCell(row, col, condition, value, textCol, bgCol, tt) =>
    if condition
        table.cell(infobox, row, col, str.tostring(value), text_color = textCol, bgcolor = bgCol, tooltip = tt, text_size = tableSize)

//TABLE - Get Percent Signal Text
getSignalInputPercent(_dir, _val, _trigger) =>
    directionResult = switch _dir
        SignalPercent.Above => _trigger > _val ? '✓ Above ' + str.tostring(_val) + '%' : '✗ Above ' + str.tostring(_val) + '%'
        SignalPercent.Below => _trigger < _val ? '✓ Below ' + str.tostring(_val) + '%' : '✗ Below ' + str.tostring(_val) + '%'
        => ' ' // Default
    directionResult

//TABLE - R Signal Text
getSignalInputR(_dir, _val, _trigger) =>
    directionResult = switch _dir
        SignalR.Above => _trigger > _val ? '✓ Above ' + str.tostring(_val) : '✗ Above ' + str.tostring(_val)
        SignalR.Below => _trigger < _val ? '✓ Below ' + str.tostring(_val) : '✗ Below ' + str.tostring(_val)
        SignalR.AbsAbove => math.abs(_trigger) > math.abs(_val) ? '✓ Above │' + str.tostring(_val) + '│' : '✗ Above │' + str.tostring(_val) + '│'
        SignalR.AbsBelow => math.abs(_trigger) < math.abs(_val) ? '✓ Below │' + str.tostring(_val) + '│' : '✗ Below │' + str.tostring(_val) + '│'
        SignalR.Mid => math.abs(_trigger) < math.abs(_val) ? '✓ Zero to ' + str.tostring(_val) : '✗ Zero to ' + str.tostring(_val)
        => ' ' // Default
    directionResult

//CHECK - Bars Above/Below Regression (Only calculate if shown in table)
var aboveRegressionCount1 = 0
var belowRegressionCount1 = 0
var aboveRegressionCount2 = 0
var belowRegressionCount2 = 0
var aboveRegressionCount3 = 0
var belowRegressionCount3 = 0
var aboveRegressionCountAvg = 0
var belowRegressionCountAvg = 0
if displayBarsSide
    if src1_transformed >= y2_1_plot
        aboveRegressionCount1 += 1
    else
        belowRegressionCount1 += 1
    if src2_transformed >= y2_2_plot
        aboveRegressionCount2 += 1
    else
        belowRegressionCount2 += 1
    if src3_transformed >= y2_3_plot
        aboveRegressionCount3 += 1
    else
        belowRegressionCount3 += 1
    if ((show1 ? src1_transformed : 0) + (show2 ? src2_transformed : 0) + (show3 ? src3_transformed : 0)) / showCount >= ((show1 ? y2_1_plot : 0) + (show2 ? y2_2_plot : 0) + (show3 ? y2_3_plot : 0)) / showCount
        aboveRegressionCountAvg += 1
    else
        belowRegressionCountAvg += 1

//CHECK - Anchor Type (Session or Date)
isSession(_inputType) => str.contains(str.tostring(_inputType), 'Session')
isDate(_inputType) => _inputType == AnchorSource.TimeDay or _inputType == AnchorSource.TimeDecade or _inputType == AnchorSource.TimeMonth or _inputType == AnchorSource.TimeQuarter or _inputType == AnchorSource.TimeWeek or _inputType == AnchorSource.TimeYear or _inputType == AnchorSource.TimeCustom

//LAST - Last bar calculation (improves efficiency)
if barstate.islast
    //DISPLAY - LinReg Line and Deviations (OVERLAY)
    const bool fillLines = true
    if showChannel1 and len1 > 1
        LR.plotLinReg(len1, y1_1_plot, y2_1_plot, slope1, topDev1, botDev1, scaleTypeLog, lineWidth1, channelExtend1, channelStyle1, fillLines, col_channelUp1, col_channelDn1, col_channelUpFill1, col_channelDnFill1)
    if showChannel2 and len2 > 1
        LR.plotLinReg(len2, y1_2_plot, y2_2_plot, slope2, topDev2, botDev2, scaleTypeLog, lineWidth2, channelExtend2, channelStyle2, fillLines, col_channelUp2, col_channelDn2, col_channelUpFill2, col_channelDnFill2)
    if showChannel3 and len3 > 1
        LR.plotLinReg(len3, y1_3_plot, y2_3_plot, slope3, topDev3, botDev3, scaleTypeLog, lineWidth3, channelExtend3, channelStyle3, fillLines, col_channelUp3, col_channelDn3, col_channelUpFill3, col_channelDnFill3)

    //Display - Warning
    if stepWarning and ((show1 and inputStep1 > 1) or (show2 and inputStep2 > 1) or (show3 and inputStep3 > 1))
        table.cell(stepWarningTable, 0, 0, 'Warning: Step > 1\nPrecision Reduced', text_color = color.red, bgcolor = col_tblContentBG, text_size = tableSize, tooltip = "The step states which bars are checked. If 1, all bars are checked. If 2, every 2nd bar is checked. Etc.")

    // DISPLAY - InfoBox
    if displayTable

        r = 0
        // Input Displayed (Channel or Bands)
        if displaySelected
            createCell(r, 1, displayAny, '', col_tblInputs, col_tblHeadingBG, '')
            createCell(r, 2, show1, '#1', showChannel1 ? (slope1 >= 0 ? col_channelUp1 : col_channelDn1) : showBands1 ? col_showBands1 : col_tblInputs, col_tblHeadingBG, '#1 Regression')
            createCell(r, 3, show2, '#2', showChannel2 ? (slope2 >= 0 ? col_channelUp2 : col_channelDn2) : showBands2 ? col_showBands2 : col_tblInputs, col_tblHeadingBG, '#2 Regression')
            createCell(r, 4, show3, '#3', showChannel3 ? (slope3 >= 0 ? col_channelUp3 : col_channelDn3) : showBands3 ? col_showBands3 : col_tblInputs, col_tblHeadingBG, '#3 Regression')
            createCell(r, 5, showAVG, 'Avg', col_tblInputs, col_tblHeadingBG, 'Average of visible Linear Regression(s)')
            r += 1

        // Input Anchor
        if displayInputAnchor
            createCell(r, 1, displayAny, 'Anchor', col_tblInputs, col_tblHeadingBG, 'Input, Linear Regression Anchor Source')
            createCell(r, 2, show1, inputType1, col_tblInputs, col_tblContentBG, '')
            createCell(r, 3, show2, inputType2, col_tblInputs, col_tblContentBG, '')
            createCell(r, 4, show3, inputType3, col_tblInputs, col_tblContentBG, '')
            createCell(r, 5, showAVG, (show1 ? ' #1 ' : '') + (show2 ? ' #2 ' : '') + (show3 ? ' #3 ' : ''), col_tblInputs, col_tblContentBG, '')
            r += 1

        // Input Length (Min, Max, Step)
        if displayInputLength
            minAndStep1 = (inputMin1 > 2 and inputMin1 <= inputMax1 and inputType1 != AnchorSource.Length ? '-' + str.tostring(inputMin1, '#') : '') + (inputStep1 > 1 and inputType1 != AnchorSource.Length ? ', ' + str.tostring(inputStep1, '#') : '')
            minAndStep2 = (inputMin2 > 2 and inputMin2 <= inputMax2 and inputType2 != AnchorSource.Length ? '-' + str.tostring(inputMin2, '#') : '') + (inputStep2 > 1 and inputType2 != AnchorSource.Length ? ', ' + str.tostring(inputStep2, '#') : '')
            minAndStep3 = (inputMin3 > 2 and inputMin3 <= inputMax3 and inputType3 != AnchorSource.Length ? '-' + str.tostring(inputMin3, '#') : '') + (inputStep3 > 1 and inputType3 != AnchorSource.Length ? ', ' + str.tostring(inputStep3, '#') : '')
            createCell(r, 1, displayAny, 'Length', col_tblInputs, col_tblHeadingBG, 'Input, Max/Min Length and Step Value\nFormat: Max-Min, Step')
            createCell(r, 2, show1, str.tostring(inputMax1, '#') + (isSession(inputType1) or isDate(inputType1) ? '' : minAndStep1), col_tblInputs, col_tblContentBG, '')
            createCell(r, 3, show2, str.tostring(inputMax2, '#') + (isSession(inputType2) or isDate(inputType2) ? '' : minAndStep2), col_tblInputs, col_tblContentBG, '')
            createCell(r, 4, show3, str.tostring(inputMax3, '#') + (isSession(inputType3) or isDate(inputType3) ? '' : minAndStep3), col_tblInputs, col_tblContentBG, '')
            r += 1

        // Input Regression Type
        if displayInputRegType
            createCell(r, 1, displayAny, 'Reg Type', col_tblInputs, col_tblHeadingBG, 'Input, Regression Type')
            createCell(r, 2, show1, inputRegType1, col_tblInputs, col_tblContentBG, '')
            createCell(r, 3, show2, inputRegType2, col_tblInputs, col_tblContentBG, '')
            createCell(r, 4, show3, inputRegType3, col_tblInputs, col_tblContentBG, '')
            r += 1

        // Input Regression Bias
        if displayInputRegBias
            createCell(r, 1, displayAny, 'Reg Bias', col_tblInputs, col_tblHeadingBG, 'Input, Regression Bias (Weighted Emphasis)\n\n>0: Recent prices weighted more. (EMA)\n 0: All prices equally weighted.\n<0: Old prices weighted more. (Inversed EMA)')
            createCell(r, 2, show1, str.tostring(inputRegWeight1, '#.#'), col_tblInputs, col_tblContentBG, '')
            createCell(r, 3, show2, str.tostring(inputRegWeight2, '#.#'), col_tblInputs, col_tblContentBG, '')
            createCell(r, 4, show3, str.tostring(inputRegWeight3, '#.#'), col_tblInputs, col_tblContentBG, '')
            r += 1

        // Input Deviation Type
        if displayInputDevType
            createCell(r, 1, displayAny, 'Dev Type', col_tblInputs, col_tblHeadingBG, 'Input, Deviation Type (Calculation Formula)')
            createCell(r, 2, show1, inputDevType1, col_tblInputs, col_tblContentBG, '')
            createCell(r, 3, show2, inputDevType2, col_tblInputs, col_tblContentBG, '')
            createCell(r, 4, show3, inputDevType3, col_tblInputs, col_tblContentBG, '')
            r += 1

        // Input Deviation Bias
        if displayInputDevBias
            createCell(r, 1, displayAny, 'Dev Bias', col_tblInputs, col_tblHeadingBG, 'Input, Deviation Weight (Weighted Emphasis)\n\n>0: Recent prices weighted more. (EMA)\n 0: All prices equally weighted.\n<0: Old prices weighted more. (Inversed EMA)')
            createCell(r, 2, show1, str.tostring(inputDevWeight1, '#.#'), col_tblInputs, col_tblContentBG, '')
            createCell(r, 3, show2, str.tostring(inputDevWeight2, '#.#'), col_tblInputs, col_tblContentBG, '')
            createCell(r, 4, show3, str.tostring(inputDevWeight3, '#.#'), col_tblInputs, col_tblContentBG, '')
            r += 1

        // Input Deviation Multiplier
        if displayInputDev
            createCell(r, 1, displayAny, 'Dev ✕', col_tblInputs, col_tblHeadingBG, 'Input, Deviation Multiplier')
            createCell(r, 2, show1, str.tostring(inputDev1, '#.#') + 'x', col_tblInputs, col_tblContentBG, '')
            createCell(r, 3, show2, str.tostring(inputDev2, '#.#') + 'x', col_tblInputs, col_tblContentBG, '')
            createCell(r, 4, show3, str.tostring(inputDev3, '#.#') + 'x', col_tblInputs, col_tblContentBG, '')
            r += 1

        // Input Signal
        if displayInputSignal
            // Percent Up Signal
            if useSignalUpPercent
                createCell(r, 1, displayAny, 'Entry %', colUp, col_tblHeadingBG, 'Input, percent requirements for entry signal\n✓=valid for signal\n✗=invalid for signal')
                createCell(r, 2, show1, getSignalInputPercent(dirUpPercent1, valUpPercent1, percent1), col_tblInputs, col_tblContentBG, '')
                createCell(r, 3, show2, getSignalInputPercent(dirUpPercent2, valUpPercent2, percent2), col_tblInputs, col_tblContentBG, '')
                createCell(r, 4, show3, getSignalInputPercent(dirUpPercent3, valUpPercent3, percent3), col_tblInputs, col_tblContentBG, '')
                createCell(r, 5, showAVG, getSignalInputPercent(dirUpPercentAVG, valUpPercentAVG, percentAVG), col_tblInputs, col_tblContentBG, '')
                r += 1

            // R Up Signal
            if useSignalUpR
                createCell(r, 1, displayAny, 'Entry R', colUp, #000000, 'Input, R requirements for entry signal\n✓=valid for signal\n✗=invalid for signal')
                createCell(r, 2, show1, getSignalInputR(dirUpR1, valUpR1, pearsonR_1), col_tblInputs, col_tblContentBG, '')
                createCell(r, 3, show2, getSignalInputR(dirUpR2, valUpR2, pearsonR_2), col_tblInputs, col_tblContentBG, '')
                createCell(r, 4, show3, getSignalInputR(dirUpR3, valUpR3, pearsonR_3), col_tblInputs, col_tblContentBG, '')
                createCell(r, 5, showAVG, getSignalInputR(dirUpRAVG, valUpRAVG, pearsonR_AVG), col_tblInputs, col_tblContentBG, '')
                r += 1

            // Percent Down Signal
            if useSignalDnPercent
                createCell(r, 1, displayAny, 'Exit %', colDn, #000000, 'Input, percent requirements for exit signal\n✓=valid for signal\n✗=invalid for signal')
                createCell(r, 2, show1, getSignalInputPercent(dirDnPercent1, valDnPercent1, percent1), col_tblInputs, col_tblContentBG, '')
                createCell(r, 3, show2, getSignalInputPercent(dirDnPercent2, valDnPercent2, percent2), col_tblInputs, col_tblContentBG, '')
                createCell(r, 4, show3, getSignalInputPercent(dirDnPercent3, valDnPercent3, percent3), col_tblInputs, col_tblContentBG, '')
                createCell(r, 5, showAVG, getSignalInputPercent(dirDnPercentAVG, valDnPercentAVG, percentAVG), col_tblInputs, col_tblContentBG, '')
                r += 1

            // R Down Signal
            if useSignalDnR
                createCell(r, 1, displayAny, 'Exit R', colDn, #000000, 'Input, R requirements for exit signal\n✓=valid for signal\n✗=invalid for signal')
                createCell(r, 2, show1, getSignalInputR(dirDnR1, valDnR1, pearsonR_1), col_tblInputs, col_tblContentBG, '')
                createCell(r, 3, show2, getSignalInputR(dirDnR2, valDnR2, pearsonR_2), col_tblInputs, col_tblContentBG, '')
                createCell(r, 4, show3, getSignalInputR(dirDnR3, valDnR3, pearsonR_3), col_tblInputs, col_tblContentBG, '')
                createCell(r, 5, showAVG, getSignalInputR(dirDnRAVG, valDnRAVG, pearsonR_AVG), col_tblInputs, col_tblContentBG, '')
                r += 1

        // Used Length
        if displayLength
            createCell(r, 1, displayAny, 'Length', col_tblCalculations, col_tblHeadingBG, 'Calculated, Length for Linear Regression')
            createCell(r, 2, show1, len1 == 1 ? '!' : str.tostring(len1, '#.#'), (inputMax1 == len1 and inputType1 != AnchorSource.Length) or len1 == 1 ? color.yellow : col_tblCalculations, col_tblContentBG, inputMax1 == len1 ? 'Max Length' : len1 == 1 ? 'Invalid length calculated' : '')
            createCell(r, 3, show2, len2 == 1 ? '!' : str.tostring(len2, '#.#'), (inputMax2 == len2 and inputType2 != AnchorSource.Length) or len2 == 1 ? color.yellow : col_tblCalculations, col_tblContentBG, inputMax1 == len2 ? 'Max Length' : len2 == 1 ? 'Invalid length calculated' : '')
            createCell(r, 4, show3, len3 == 1 ? '!' : str.tostring(len3, '#.#'), (inputMax3 == len3 and inputType3 != AnchorSource.Length) or len3 == 1 ? color.yellow : col_tblCalculations, col_tblContentBG, inputMax1 == len3 ? 'Max Length' : len3 == 1 ? 'Invalid length calculated' : '')
            r += 1

        // Percent
        if displayPercent
            createCell(r, 1, displayAny, '%', col_tblCalculations, col_tblHeadingBG, 'Calculated, % position within Deviations\n(upper = 100% , midline = 50% , lower = 0%)')
            createCell(r, 2, show1, len1 == 1 ? '' : roundPercent(percent1), (percent1 >= 100 ? colDn : percent1 <= 0 ? colUp : col_tblCalculations), col_tblContentBG, '')
            createCell(r, 3, show2, len2 == 1 ? '' : roundPercent(percent2), (percent2 >= 100 ? colDn : percent2 <= 0 ? colUp : col_tblCalculations), col_tblContentBG, '')
            createCell(r, 4, show3, len3 == 1 ? '' : roundPercent(percent3), (percent3 >= 100 ? colDn : percent3 <= 0 ? colUp : col_tblCalculations), col_tblContentBG, '')
            createCell(r, 5, showAVG, str.tostring(percentAVG, '#') + '%', (percentAVG >= 100 ? colDn : percentAVG <= 0 ? colUp : col_tblCalculations), col_tblContentBG, '')
            r += 1

        // Deviation of Close
        if displayCloseDev
            createCell(r, 1, displayAny, 'Dev ⓒ', col_tblCalculations, col_tblHeadingBG, 'Calculated, Deviation value at close.')
            createCell(r, 2, show1, len1 == 1 ? '' : roundValue(devClose1) + 'x', devClose1 >= inputDev1 ? colDn : devClose1 <= -inputDev1 ? colUp : col_tblCalculations, col_tblContentBG, '')
            createCell(r, 3, show2, len2 == 1 ? '' : roundValue(devClose2) + 'x', devClose2 >= inputDev2 ? colDn : devClose2 <= -inputDev2 ? colUp : col_tblCalculations, col_tblContentBG, '')
            createCell(r, 4, show3, len3 == 1 ? '' : roundValue(devClose3) + 'x', devClose3 >= inputDev3 ? colDn : devClose3 <= -inputDev3 ? colUp : col_tblCalculations, col_tblContentBG, '')
            createCell(r, 5, showAVG, roundValue(devCloseAVG) + 'x', not na(devXAvg) and devCloseAVG >= devXAvg ? colDn : not na(devXAvg) and devCloseAVG <= -devXAvg ? colUp : col_tblCalculations, col_tblContentBG, '')
            r += 1

        // Pearson's R
        if displayR
            createCell(r, 1, displayAny, 'R', col_tblCalculations, col_tblHeadingBG, 'Calculated, R (Pearson Correlation Coefficient)\n(>0 = uptrend , <0 = downtrend) \n(±1 = perfect correlation, 0 = none)')
            createCell(r, 2, show1, len1 == 1 ? '' : roundValue(pearsonR_1), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 3, show2, len2 == 1 ? '' : roundValue(pearsonR_2), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 4, show3, len3 == 1 ? '' : roundValue(pearsonR_3), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 5, showAVG, roundValue(pearsonR_AVG), col_tblCalculations, col_tblContentBG, '')
            r += 1

        // Pearson's R²
        if displayR2
            createCell(r, 1, displayAny, 'R²', col_tblCalculations, col_tblHeadingBG, 'Calculated, R-Squared (Determination Coefficient)')
            createCell(r, 2, show1, len1 == 1 ? '' : roundValue(pearsonR_1 * pearsonR_1), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 3, show2, len2 == 1 ? '' : roundValue(pearsonR_2 * pearsonR_2), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 4, show3, len3 == 1 ? '' : roundValue(pearsonR_3 * pearsonR_3), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 5, showAVG, roundValue(pearsonR_AVG * pearsonR_AVG), col_tblCalculations, col_tblContentBG, '')
            r += 1

        // Average Pearson's R
        if displayAverageAbsR
            createCell(r, 1, displayAny, 'Avg │R│', col_tblCalculations, col_tblHeadingBG, 'Calculated, Average │R│ (Pearson Correlation Coefficient)\n(1 = perfect correlation, 0 = none)')
            createCell(r, 2, show1, len1 == 1 ? '' : roundValue(pearsonR_total_1/pearsonR_count), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 3, show2, len2 == 1 ? '' : roundValue(pearsonR_total_2/pearsonR_count), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 4, show3, len3 == 1 ? '' : roundValue(pearsonR_total_3/pearsonR_count), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 5, showAVG, roundValue(((pearsonR_total_1/pearsonR_count)+(pearsonR_total_2/pearsonR_count)+(pearsonR_total_3/pearsonR_count))/showCount), col_tblCalculations, col_tblContentBG, '')
            r += 1

        // Slope
        if displaySlope
            createCell(r, 1, displayAny, 'Slope', col_tblCalculations, col_tblHeadingBG, 'Calculated, Slope')
            createCell(r, 2, show1, len1 == 1 ? '' : roundValue(slope1), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 3, show2, len2 == 1 ? '' : roundValue(slope2), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 4, show3, len3 == 1 ? '' : roundValue(slope3), col_tblCalculations, col_tblContentBG, '')
            createCell(r, 5, showAVG, roundValue(slopeAVG), col_tblCalculations, col_tblContentBG, '')
            r += 1

        // Trend Direction
        if displayTrend
            createCell(r, 1, displayAny, "Trend", col_tblCalculations, col_tblHeadingBG, "Calculated, trend direction based on slope")
            createCell(r, 2, show1, len1 == 1 ? "" : slope1 > 0 ? "↗" : (slope1 < 0 ? "↘" : "→"), col_tblCalculations, col_tblContentBG, "")
            createCell(r, 3, show2, len2 == 1 ? "" : slope2 > 0 ? "↗" : (slope2 < 0 ? "↘" : "→"), col_tblCalculations, col_tblContentBG, "")
            createCell(r, 4, show3, len3 == 1 ? "" : slope3 > 0 ? "↗" : (slope3 < 0 ? "↘" : "→"), col_tblCalculations, col_tblContentBG, "")
            createCell(r, 5, showAVG, slopeAVG > 0 ? "↗" : (slopeAVG < 0 ? "↘" : "→"), col_tblCalculations, col_tblContentBG, "")
            r += 1

        // Above/Below Regression (↑/↓)
        if displayBarsSide
            createCell(r, 1, displayAny, "↑/↓", col_tblCalculations, col_tblHeadingBG, "Calculated, counts above & below regression\n(Counts last bar of each regression only)")
            createCell(r, 2, show1, str.tostring(aboveRegressionCount1) + ' / ' + str.tostring(belowRegressionCount1), col_tblCalculations, col_tblContentBG, "")
            createCell(r, 3, show2, str.tostring(aboveRegressionCount2) + ' / ' + str.tostring(belowRegressionCount2), col_tblCalculations, col_tblContentBG, "")
            createCell(r, 4, show3, str.tostring(aboveRegressionCount3) + ' / ' + str.tostring(belowRegressionCount3), col_tblCalculations, col_tblContentBG, "")
            createCell(r, 5, showAVG, str.tostring(aboveRegressionCountAvg) + ' / ' + str.tostring(belowRegressionCountAvg), col_tblCalculations, col_tblContentBG, "")
            r += 1

        if scaleTypeLog
            //createCell(0, 0, displayAny, "Log Scale", chart.fg_color, color.new(color.blue, 50), 'Indicator set to log scale, make sure chart is also log scale.')
            if displayAny
                table.cell(infobox, 0, 0, "Log Scale", text_color = chart.fg_color, bgcolor = color.new(color.blue, 100), text_halign = text.align_right, tooltip = 'Indicator set to log scale, make sure chart is also log scale.')
                table.merge_cells(infobox, 0, 0, math.max(0,r-1), 0)

        // Warning if no regressions are selected
        createCell(0, 1, not displayAny, "Regressions all hidden\nChange from " + str.tostring(DisplayLinReg.Hide), color.rgb(243, 33, 33), #000412, '')

//GET - Formatted timeframe text
calcTimeframeText(_src) =>
    if str.contains(_src, 'S')
        str.replace(_src, 'S', 's', 0)
    else if str.contains(_src, 'D') or str.contains(_src, 'W') or str.contains(_src, 'M')
        str.length(_src) == 1 ? '1' + _src : _src
    else
        str.tonumber(_src) < 60 ? _src + 'm' : str.tostring(str.tonumber(_src) / 60) + 'h'

//ALERTS
alert_UpSignal = input(true, title = 'Alert - Entry Signal', group = '🔔Alerts', tooltip = '█ Alert Entry Signal')
alert_DownSignal = input(true, title = 'Alert - Exit Signal', group = '🔔Alerts', tooltip = '█ Alert Exit Signal')
if alert_UpSignal and bigUp
    alert(calcTimeframeText(timeframe.period) + ' ' +  syminfo.tickerid + '\nLinear Regression - Entry Signal' + (scaleTypeLog ? '\nLog Scale' : ''), alert.freq_once_per_bar_close)
if alert_DownSignal and bigDown
    alert(calcTimeframeText(timeframe.period) + ' ' +  syminfo.tickerid + '\nLinear Regression - Exit Signal' + (scaleTypeLog ? '\nLog Scale' : ''), alert.freq_once_per_bar_close)

Overview

Each channel can be hidden or drawn as a channel, bands, or both, and its lookback is anchored to price, volume, oscillator extremes, calendar periods, sessions, or corporate events. Per channel, the user sets the source, length bounds, regression formula, deviation formula, bias, and a deviation multiplier. A log-scale option changes the calculation basis. It does not create strategy entries or exits.

Details

Published by

regalouisei on GitHub

Code credit

TanHef, as written in the script's header

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

Trend, Volatility & bands, Support & resistance, Sessions & time

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
Log ScaleboolfalsescaleTypeLog
#1enumDisplayLinReg.HideinputDisplay1
AnchorenumAnchorSource.BarHighestinputType1
SourcesourcecloseinputSource1
Length│Maxint1000inputMax1
Minint10inputMin1
Stepint1inputStep1
Regression│TypeenumRegressionType.StandardinputRegType1
Biasfloat0inputRegWeight1
Deviation│TypeenumDeviationType.ReverseinputDevType1
Biasfloat0inputDevWeight1
✕float2inputDev1
Show all 40 settings
SettingTypeDefaultVariable
#2enumDisplayLinReg.HideinputDisplay2
AnchorenumAnchorSource.BarLowestinputType2
SourcesourcecloseinputSource2
Length│Maxint1000inputMax2
Minint10inputMin2
Stepint1inputStep2
Regression│TypeenumRegressionType.StandardinputRegType2
Biasfloat0inputRegWeight2
Deviation│TypeenumDeviationType.ReverseinputDevType2
Biasfloat0inputDevWeight2
✕float2inputDev2
#3enumDisplayLinReg.HideinputDisplay3
AnchorenumAnchorSource.SlopeZeroinputType3
SourcesourcecloseinputSource3
Length│Maxint400inputMax3
Minint10inputMin3
Stepint10inputStep3
Regression│TypeenumRegressionType.StandardinputRegType3
Biasfloat0inputRegWeight3
Deviation│TypeenumDeviationType.ReverseinputDevType3
Biasfloat0inputDevWeight3
✕float2inputDev3
  % Direction  |  % Value  | R Direction | R Valuecolorcolor.limecolUp
#1enumSignalPercent.AnydirUpPercent1
valUpPercent1int0valUpPercent1
dirUpR1enumSignalR.AnydirUpR1
valUpR1float0valUpR1
#2enumSignalPercent.AnydirUpPercent2
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

42H Map

by aurorascarlet1102
4 stars

42H Map calculates custom time cycle structures and session ranges directly on the price chart. It partitions market action into forty-two-hour cycles, ten-and-a-half-hour micro-sessions, half-week periods, and quarter-month segments to track highs, lows, and

Indicator v5 Sessions & timeSupport & resistance
Updated 3 months ago · None stated GitHub repository of 42H Map

[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
257 stars

This indicator plots auto trade signals for E-mini S&P 500 futures on the price chart. It computes an EMA200 filter along with day ETH RTH session levels and percentage-based entry zones. Signals trigger CALL or PUT cases when price crosses defined thresholds

Indicator v6 TrendSupport & resistance
Updated 6 weeks ago · None stated GitHub repository of Auto Trade Futures ES

Dynamic Linear Regression

by TradersPost
218 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

More indicators

Trade Your Charts With a Regulated Broker

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

Compare brokers