mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-07-27 17:27:43 +00:00
61 lines
2.6 KiB
Plaintext
61 lines
2.6 KiB
Plaintext
// Licensed under the Apache License, Version 2.0
|
|
// © 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")
|