multi-anchored-linear-regression-channels-tanhef.pine
Copy
// 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)
Show all 1,145 lines