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

Pine Script牛/熊旗形线延伸异常问题求助

Pine Script v5 牛/熊旗形线延伸问题修复思路

需求与问题

  • 需求:绘制牛/熊旗形线,价格处于旗形上下线区间内时线条持续延伸;价格离开区间后,后续再回到区间时线条不再延伸。
  • 当前问题:原代码在价格后续返回区间时会错误延伸线条;添加closed变量控制后,线条完全无法延伸。

原代码

//@version=5
indicator("Line Extension", overlay=true, max_lines_count=20)

ph = ta.pivothigh(high,5,5)
pl = ta.pivotlow(low,5,5)

plotshape(ph, color=#FF0000, location=location.abovebar, offset=-5)
plotshape(pl, color=#00E600, location=location.belowbar, offset=-5)

var line [] flag_array = array.new_line()

var flag_price      = array.new_float()
var flag_index      = array.new_int()
var flag_price2      = array.new_float()
var flag_index2      = array.new_int()

var lastIn = 0


arraySize = input.int(20, title="Array Size")

add_to_array(_price,_index,_val) =>
    array.unshift(_price,_val)
    array.unshift(_index,bar_index)
    if array.size(_index)>arraySize
        array.pop(_price)
        array.pop(_index)

if ph 
    add_to_array(flag_price,flag_index,ph)

if pl 
    add_to_array(flag_price2,flag_index2,pl)


draw_lines(_price, _index, _lineArray)=>
    if array.size(_index)>=4
        x1      = array.get(_index,1)-5
        y1      = array.get(_price,1)
        x2      = array.get(_index,0)-5
        y2      = array.get(_price,0)
        array.push(_lineArray, line.new(x1,y1,x2,y2, color=color.white))

    array.clear(_price) 
    array.clear(_index)


extend_lines(lineArray,_close,_index)=>
    if array.size(lineArray)>1
        recentLine  = array.get(lineArray,0)
        olderLine   =  array.get(lineArray,1)
        x1       = line.get_x1(recentLine) 
        y1       = line.get_y1(recentLine)
        x2       = line.get_x2(recentLine)
        y2       = line.get_y2(recentLine)
        
        x11       = line.get_x1(olderLine)
        y11       = line.get_y1(olderLine)
        x22       = line.get_x2(olderLine)
        y22       = line.get_y2(olderLine)
        
        slope       = (y2-y1)/(x2-x1)
        slope2      = (y22-y11)/(x22-x11)
        
        currentDistance = _index - x2
        currentDistance2 = _index - x22

        currentY2 = y2 + (currentDistance*slope)
        currentY22 = y22 + (currentDistance2*slope2)

        var closed = false
        if _close<=currentY2 and _close>=currentY22 and closed==false
            //Price within the Flags slope, extend to current price/bar
            line.set_x2(recentLine,_index)
            line.set_y2(recentLine,currentY2)
            line.set_x2(olderLine,_index)
            line.set_y2(olderLine,currentY22)
            //If price exits flag area cancel extension posibility 
        if _close>currentY2 or _close<currentY22
            closed := true


//plot(close)
if array.size(flag_index)>4
    draw_lines(flag_price, flag_index, flag_array)
if array.size(flag_index2)>4
    draw_lines(flag_price2, flag_index2, flag_array)

if array.size(flag_array)>2
    extend_lines(flag_array, close, bar_index)

问题根源分析

  1. 变量作用域错误:extend_lines函数内的var closed = false是全局共享变量,一旦价格第一次离开区间,closed被设为true后永远不会重置,导致所有线条后续都无法延伸。
  2. 状态未分组管理:所有旗形线共用同一个closed状态,无法单独控制每组线条的延伸权限。

修复方案

1. 添加分组状态数组

创建与flag_array对应的布尔数组,单独记录每组旗形线是否停止延伸:

var bool[] flag_closed = array.new_bool()

2. 修改draw_lines函数,同步初始化状态

在创建新线条时,向flag_closed添加初始状态false:

draw_lines(_price, _index, _lineArray, closedArray)=>
    if array.size(_index)>=4
        x1      = array.get(_index,1)-5
        y1      = array.get(_price,1)
        x2      = array.get(_index,0)-5
        y2      = array.get(_price,0)
        array.push(_lineArray, line.new(x1,y1,x2,y2, color=color.white))
        array.push(closedArray, false)  // 初始化该组线条为允许延伸

    array.clear(_price) 
    array.clear(_index)

3. 重构extend_lines函数,使用分组状态

遍历每组旗形线,根据对应状态判断是否允许延伸:

extend_lines(lineArray,_close,_index, closedArray)=>
    // 遍历所有成对的旗形线(每组2条线)
    for i from 0 to array.size(lineArray)-1 step 2
        if i+1 >= array.size(lineArray)
            break
        // 获取当前组的两条线和对应的关闭状态
        line1 = array.get(lineArray, i)
        line2 = array.get(lineArray, i+1)
        isClosed = array.get(closedArray, i/2)
        
        if not isClosed
            // 计算第一条线的延伸Y值
            x1_line1 = line.get_x1(line1)
            y1_line1 = line.get_y1(line1)
            x2_line1 = line.get_x2(line1)
            y2_line1 = line.get_y2(line1)
            slope_line1 = (y2_line1 - y1_line1)/(x2_line1 - x1_line1)
            dist_line1 = _index - x2_line1
            currentY_line1 = y2_line1 + (dist_line1 * slope_line1)
            
            // 计算第二条线的延伸Y值
            x1_line2 = line.get_x1(line2)
            y1_line2 = line.get_y1(line2)
            x2_line2 = line.get_x2(line2)
            y2_line2 = line.get_y2(line2)
            slope_line2 = (y2_line2 - y1_line2)/(x2_line2 - x1_line2)
            dist_line2 = _index - x2_line2
            currentY_line2 = y2_line2 + (dist_line2 * slope_line2)
            
            // 确定区间上下限(避免斜率导致的顺序颠倒)
            upperY = math.max(currentY_line1, currentY_line2)
            lowerY = math.min(currentY_line1, currentY_line2)
            
            if _close >= lowerY and _close <= upperY
                // 价格在区间内,延伸线条
                line.set_x2(line1, _index)
                line.set_y2(line1, currentY_line1)
                line.set_x2(line2, _index)
                line.set_y2(line2, currentY_line2)
            else
                // 价格离开区间,标记该组为已关闭
                array.set(closedArray, i/2, true)

4. 更新调用逻辑

在调用draw_lines和extend_lines时传入状态数组:

if array.size(flag_index)>4
    draw_lines(flag_price, flag_index, flag_array, flag_closed)
if array.size(flag_index2)>4
    draw_lines(flag_price2, flag_index2, flag_array, flag_closed)

if array.size(flag_array)>=2
    extend_lines(flag_array, close, bar_index, flag_closed)

完整修复后代码

//@version=5
indicator("Line Extension Fixed", overlay=true, max_lines_count=20)

ph = ta.pivothigh(high,5,5)
pl = ta.pivotlow(low,5,5)

plotshape(ph, color=#FF0000, location=location.abovebar, offset=-5)
plotshape(pl, color=#00E600, location=location.belowbar, offset=-5)

var line[] flag_array = array.new_line()
var bool[] flag_closed = array.new_bool()  // 记录每组旗形线是否停止延伸

var flag_price = array.new_float()
var flag_index = array.new_int()
var flag_price2 = array.new_float()
var flag_index2 = array.new_int()

arraySize = input.int(20, title="Array Size")

add_to_array(_price,_index,_val) =>
    array.unshift(_price,_val)
    array.unshift(_index,bar_index)
    if array.size(_index)>arraySize
        array.pop(_price)
        array.pop(_index)

if ph 
    add_to_array(flag_price,flag_index,ph)

if pl 
    add_to_array(flag_price2,flag_index2,pl)

draw_lines(_price, _index, _lineArray, closedArray)=>
    if array.size(_index)>=4
        x1 = array.get(_index,1)-5
        y1 = array.get(_price,1)
        x2 = array.get(_index,0)-5
        y2 = array.get(_price,0)
        array.push(_lineArray, line.new(x1,y1,x2,y2, color=color.white))
        array.push(closedArray, false)  // 初始化该组为允许延伸

    array.clear(_price) 
    array.clear(_index)

extend_lines(lineArray,_close,_index, closedArray)=>
    // 按每组2条线遍历
    for i from 0 to array.size(lineArray)-1 step 2
        if i+1 >= array.size(lineArray)
            break
        line1 = array.get(lineArray, i)
        line2 = array.get(lineArray, i+1)
        groupIdx = i/2
        isClosed = array.get(closedArray, groupIdx)
        
        if not isClosed
            // 计算第一条线的延伸参数
            x1_line1 = line.get_x1(line1)
            y1_line1 = line.get_y1(line1)
            x2_line1 = line.get_x2(line1)
            y2_line1 = line.get_y2(line1)
            slope_line1 = (y2_line1 - y1_line1)/(x2_line1 - x1_line1)
            dist_line1 = _index - x2_line1
            currentY_line1 = y2_line1 + (dist_line1 * slope_line1)
            
            // 计算第二条线的延伸参数
            x1_line2 = line.get_x1(line2)
            y1_line2 = line.get_y1(line2)
            x2_line2 = line.get_x2(line2)
            y2_line2 = line.get_y2(line2)
            slope_line2 = (y2_line2 - y1_line2)/(x2_line2 - x1_line2)
            dist_line2 = _index - x2_line2
            currentY_line2 = y2_line2 + (dist_line2 * slope_line2)
            
            // 确定区间上下限
            upperY = math.max(currentY_line1, currentY_line2)
            lowerY = math.min(currentY_line1, currentY_line2)
            
            if _close >= lowerY and _close <= upperY
                // 价格在区间内,延伸线条
                line.set_x2(line1, _index)
                line.set_y2(line1, currentY_line1)
                line.set_x2(line2, _index)
                line.set_y2(line2, currentY_line2)
            else
                // 价格离开,标记该组关闭
                array.set(closedArray, groupIdx, true)

// 调用逻辑
if array.size(flag_index)>4
    draw_lines(flag_price, flag_index, flag_array, flag_closed)
if array.size(flag_index2)>4
    draw_lines(flag_price2, flag_index2, flag_array, flag_closed)

if array.size(flag_array)>=2
    extend_lines(flag_array, close, bar_index, flag_closed)

内容的提问来源于stack exchange,提问作者Acta Non Verba

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 18:16:04