You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Pine Script多项式回归线添加标准差通道?

多项式回归脚本添加标准差回归通道的实现方案

核心实现逻辑

  1. 计算回归残差的标准差:用原始价格与多项式回归值的差值构建数组,通过array.stdev()计算样本无偏标准差
  2. 生成通道上下轨:基于回归值 ± 「带宽倍数 × 残差标准差」得到上下轨数值
  3. 复用线条数组机制:新增两组线条数组分别存储通道上轨、下轨的绘图对象,与主回归线同步更新

修改后的完整脚本

//@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:43:13