// The MIT License (MIT) // © mihakralj //@version=6 indicator("Standard Deviation Channel (SDCHANNEL)", "SDCHANNEL", overlay=true) //@function Calculates Standard Deviation Channel with lines N standard deviations above and below a linear regression line //@param period Lookback period for regression and standard deviation calculation (period > 1) //@param source Source series for analysis (usually close) //@param multiplier Standard deviation multiplier for channel distance (multiplier > 0) //@returns Tuple containing [upper_channel, regression_line, lower_channel] //@optimized Uses linear regression with O(n) complexity per bar sdchannel(simple int period, series float source = close, simple float multiplier = 2.0) => if period <= 1 runtime.error("Period must be > 1") if multiplier <= 0.0 runtime.error("Multiplier must be > 0") float sumX = 0.0 float sumY = 0.0 float sumXY = 0.0 float sumX2 = 0.0 for i = 0 to period - 1 float x = float(i) float y = source[period - 1 - i] sumX := sumX + x sumY := sumY + y sumXY := sumXY + x * y sumX2 := sumX2 + x * x float n = float(period) float slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX) float intercept = (sumY - slope * sumX) / n float currentX = float(period - 1) float regressionLine = slope * currentX + intercept float sumSquaredResiduals = 0.0 for i = 0 to period - 1 float x = float(i) float y = source[period - 1 - i] float predicted = slope * x + intercept float residual = y - predicted sumSquaredResiduals := sumSquaredResiduals + residual * residual float stdDev = math.sqrt(sumSquaredResiduals / n) float upperChannel = regressionLine + multiplier * stdDev float lowerChannel = regressionLine - multiplier * stdDev [upperChannel, regressionLine, lowerChannel] // ---------- Main loop ---------- // Inputs i_period = input.int(20, "Period", minval=2) i_source = input.source(close, "Source") i_multiplier = input.float(2.0, "Standard Deviation Multiplier", minval=0.1, step=0.1) // Calculation [upperLine, midLine, lowerLine] = sdchannel(i_period, i_source, i_multiplier) // Plot p1 = plot(upperLine, "Upper Channel", color=color.yellow, linewidth=2) p2 = plot(midLine, "Regression Line", color=color.yellow, linewidth=2) p3 = plot(lowerLine, "Lower Channel", color=color.yellow, linewidth=2) fill(p1, p2, color=color.new(color.red, 90), title="Upper Fill") fill(p2, p3, color=color.new(color.green, 90), title="Lower Fill")