如何为Pine Script多项式回归线添加标准差通道?
多项式回归脚本添加标准差回归通道的实现方案
核心实现逻辑
- 计算回归残差的标准差:用原始价格与多项式回归值的差值构建数组,通过
array.stdev()计算样本无偏标准差 - 生成通道上下轨:基于回归值 ± 「带宽倍数 × 残差标准差」得到上下轨数值
- 复用线条数组机制:新增两组线条数组分别存储通道上轨、下轨的绘图对象,与主回归线同步更新
修改后的完整脚本
//@version=5 indicator("(--) Polynomial Regression + Forecast with Channels", overlay = true, max_lines_count = 1500) //---------------- //--- Settings --- //---------------- length = input.int(defval = 90) length := timeframe.isweekly ? length/4 : timeframe.period == "D" ? length : timeframe.period == "2D" ? length/2 : timeframe.period == "240" ? length/2*3 : timeframe.isintraday ? length : na extrapolate = 12 // Forecast length degree = 3 // polynomial degree src = close // source lock = false // lock forecast up_css = color.green // color up dn_css = color.red // color down ex_css = color.gray // color forecast width = 3 // lines width // 新增通道配置参数 bandwidth = input.float(defval = 2.0, title = "通道带宽倍数", minval = 0.1) channel_up_css = input.color(color.new(color.green, 80), title = "上轨颜色") channel_dn_css = input.color(color.new(color.red, 80), title = "下轨颜色") channel_width = input.int(defval = 1, title = "通道线宽度") //-------------------------- //--- 创建线条存储数组 --- //-------------------------- var lines_reg = array.new_line(0) // 主回归线数组 var lines_up = array.new_line(0) // 通道上轨数组 var lines_dn = array.new_line(0) // 通道下轨数组 if barstate.isfirst for i = -extrapolate to length-1 array.push(lines_reg, line.new(na, na, na, na)) array.push(lines_up, line.new(na, na, na, na)) array.push(lines_dn, line.new(na, na, na, na)) //--------------------------------------- //--- 矩阵运算预处理 --- //--------------------------------------- n = bar_index var design = matrix.new<float>(0, 0) var response = matrix.new<float>(0, 0) if barstate.isfirst for i = 0 to degree column = array.new_float(0) for j = 0 to length-1 array.push(column, math.pow(j,i)) matrix.add_col(design, i, column) var a = matrix.inv(matrix.mult(matrix.transpose(design), design)) var b = matrix.mult(a, matrix.transpose(design)) //--------------------------------------------------------------------- //--- 滚动多项式回归计算 + 通道生成 --- //--------------------------------------------------------------------- var pass = 1 var matrix<float> coefficients = na var x = -extrapolate var float forecast = na var float reg_std = na if barstate.islast if pass prices = array.new_float(0) for i = 0 to length-1 array.push(prices, src[i]) matrix.add_col(response, 0, prices) coefficients := matrix.mult(b, response) float y1_reg = na float y1_up = na float y1_dn = na idx = 0 // 计算历史残差的标准差 var temp_residuals = array.new_float(0) for i = 0 to length-1 y_reg = 0. for j = 0 to degree y_reg += math.pow(i, j)*matrix.get(coefficients, j, 0) array.push(temp_residuals, src[i] - y_reg) reg_std := array.stdev(temp_residuals, false) // 无偏标准差 // 绘制主回归线与通道线 for i = -extrapolate to length-1 y_reg = 0. for j = 0 to degree y_reg += math.pow(i, j)*matrix.get(coefficients, j, 0) y_up = y_reg + bandwidth * reg_std y_dn = y_reg - bandwidth * reg_std if idx == 0 forecast := y_reg // 设置主回归线 css_reg = y_reg < y1_reg ? up_css : dn_css line_reg = array.get(lines_reg, idx) line.set_xy1(line_reg, n - i + 1, y1_reg) line.set_xy2(line_reg, n - i, y_reg) line.set_color(line_reg, i <= 0 ? ex_css : css_reg) line.set_width(line_reg, width) // 设置通道上轨 line_up = array.get(lines_up, idx) line.set_xy1(line_up, n - i + 1, y1_up) line.set_xy2(line_up, n - i, y_up) line.set_color(line_up, i <= 0 ? color.new(ex_css, 80) : channel_up_css) line.set_width(line_up, channel_width) // 设置通道下轨 line_dn = array.get(lines_dn, idx) line.set_xy1(line_dn, n - i + 1, y1_dn) line.set_xy2(line_dn, n - i, y_dn) line.set_color(line_dn, i <= 0 ? color.new(ex_css, 80) : channel_dn_css) line.set_width(line_dn, channel_width) y1_reg := y_reg y1_up := y_up y1_dn := y_dn idx += 1 if lock pass := 0 else y_reg = 0. x -= 1 for j = 0 to degree y_reg += math.pow(x, j)*matrix.get(coefficients, j, 0) y_up = y_reg + bandwidth * reg_std y_dn = y_reg - bandwidth * reg_std forecast := y_reg // 锁定模式下更新最新线条 idx = array.size(lines_reg) - 1 line_reg = array.get(lines_reg, idx) line_up = array.get(lines_up, idx) line_dn = array.get(lines_dn, idx) line.set_xy1(line_reg, n + 1, line.get_y2(line_reg)) line.set_xy2(line_reg, n, y_reg) line.set_color(line_reg, ex_css) line.set_xy1(line_up, n + 1, line.get_y2(line_up)) line.set_xy2(line_up, n, y_up) line.set_color(line_up, color.new(ex_css, 80)) line.set_xy1(line_dn, n + 1, line.get_y2(line_dn)) line.set_xy2(line_dn, n, y_dn) line.set_color(line_dn, color.new(ex_css, 80)) // 移除最旧线条并添加新线条 array.shift(lines_reg) array.push(lines_reg, line.new(n, y_reg, na, na)) array.shift(lines_up) array.push(lines_up, line.new(n, y_up, na, na)) array.shift(lines_dn) array.push(lines_dn, line.new(n, y_dn, na, na)) plot(pass == 0 ? forecast : na, 'Forecast' , color = ex_css , offset = extrapolate , linewidth = width)
关键修改说明
- 新增通道参数:可自定义带宽倍数、通道颜色和线条宽度
- 残差标准差计算:遍历历史bar计算原始价格与回归值的差值,通过
array.stdev()得到无偏标准差 - 通道绘制逻辑:与主回归线同步生成上下轨线条,预测段通道使用半透明灰色,历史段使用自定义颜色
- 锁定模式适配:保持原脚本锁定逻辑的同时,同步更新通道线条的滚动显示
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

