Pine Script line.new线段条件终止/删除方法咨询
Pine Script 月度价位线突破处理实现方案
核心问题出在两个点:一是没有对生成的线段做统一的引用管理,二是错误使用了extend.right固定延伸属性,导致无法控制线段截断位置。以下是两种需求的可落地实现逻辑:
方案1:线段精准截断在突破点位(优先选用)
这个方案完全实现“未突破时无限右延,触碰突破时在突破K线位置终止”的效果,不需要调用line.delete()处理未失效的线,核心逻辑是动态更新线段端点,而不是依赖原生延伸属性:
- 用
ta.change(time("M"))检测月度K线切换节点,触发时计算当月开盘价上下5%、10%共4个价位,为每个价位创建线段:起点x1设为当月开盘K线索引,初始终点x2设为当前bar_index,将线段ID、对应价位、上下轨类型、突破状态打包存入自定义结构体数组统一管理。 - 每根K线从后往前遍历数组中所有未标记为突破的线段:
- 对上轨线(+5%、+10%),判断当前K线最高价是否大于线段对应价位,若触发突破,将线段x2端点固定为当前
bar_index,标记为已突破,后续不再更新 - 对下轨线(-5%、-10%),判断当前K线最低价是否小于线段对应价位,若触发突破,同样将x2固定在当前K线,标记为已突破
- 对未触发突破的线段,每根K线将x2更新为当前
bar_index,实现随行情动态右延的效果,和extend.right的视觉表现完全一致
- 对上轨线(+5%、+10%),判断当前K线最高价是否大于线段对应价位,若触发突破,将线段x2端点固定为当前
- 数量上限控制:当数组内线段总数超过450(预留50个冗余量避免触发500条上限报错)时,优先删除数组中最早生成、且已经被突破的线段,释放配额。
核心实现代码:
//@version=5 indicator("月度价位突破截断线", overlay=true, max_lines_count=500) // 定义线段存储结构体 type TrackedLine line ref float level bool isUpper bool isBroken // 全局数组存储所有活动线段 var array<TrackedLine> linePool = array.new<TrackedLine>() // 检测新月度开盘 isNewMonth = ta.change(time("M")) monthOpenPrice = ta.valuewhen(isNewMonth, open, 0) // 新月度生成4条对应价位线 if isNewMonth // +10%上轨 line u10 = line.new(bar_index, monthOpenPrice*1.1, bar_index, monthOpenPrice*1.1, color=color.new(color.red, 0), width=2) array.push(linePool, TrackedLine.new(u10, monthOpenPrice*1.1, true, false)) // +5%上轨 line u5 = line.new(bar_index, monthOpenPrice*1.05, bar_index, monthOpenPrice*1.05, color=color.new(color.orange, 0), width=2) array.push(linePool, TrackedLine.new(u5, monthOpenPrice*1.05, true, false)) // -5%下轨 line d5 = line.new(bar_index, monthOpenPrice*0.95, bar_index, monthOpenPrice*0.95, color=color.new(color.lime, 0), width=2) array.push(linePool, TrackedLine.new(d5, monthOpenPrice*0.95, false, false)) // -10%下轨 line d10 = line.new(bar_index, monthOpenPrice*0.9, bar_index, monthOpenPrice*0.9, color=color.new(color.green, 0), width=2) array.push(linePool, TrackedLine.new(d10, monthOpenPrice*0.9, false, false)) // 遍历更新所有线段状态 for i = array.size(linePool) - 1 to 0 by -1 TrackedLine item = array.get(linePool, i) if not item.isBroken // 判断突破逻辑 bool hit = item.isUpper ? high > item.level : low < item.level if hit // 截断在突破K线 line.set_x2(item.ref, bar_index) item.isBroken := true else // 未突破则向右延伸 line.set_x2(item.ref, bar_index) // 清理多余的已突破旧线,避免触发数量上限 if array.size(linePool) > 450 and item.isBroken line.delete(item.ref) array.remove(linePool, i)
方案2:突破时删除整条线段(备选简化方案)
如果不需要保留突破前的线段,只要突破就移除整条线,逻辑更简单:
- 生成线段时直接添加
extend=extend.right属性,不需要每根K线更新x2坐标 - 遍历线段时只要检测到突破,直接调用
line.delete(线段ID)删除对应线,同时从数组中移除该元素即可 - 同样从后往前遍历数组,避免索引错位,因为生成线段时已经自带右延伸属性,不需要额外更新位置,运行性能更好。
核心修改片段:
// 生成线时直接设置无限右延 line u10 = line.new(bar_index, monthOpenPrice*1.1, bar_index, monthOpenPrice*1.1, color=color.red, width=2, extend=extend.right) // 遍历时突破即删除 for i = array.size(linePool) - 1 to 0 by -1 TrackedLine item = array.get(linePool, i) bool hit = item.isUpper ? high > item.level : low < item.level if hit line.delete(item.ref) array.remove(linePool, i)
注意事项
- 不要使用
plot()函数实现该需求,plot的40个绘图对象上限无法满足多周期线段的存储需求,使用line.new()走500条线段的配额,配合动态清理逻辑可以长期稳定运行。 - 截断方案中不要给线段加
extend.right属性,该属性会强制线段延伸到图表最右侧,无法通过修改x2坐标实现截断效果。 - 数组遍历必须从最后一个元素倒序向前遍历,否则删除元素时会导致索引错位,出现漏判线段的问题。
内容的提问来源于stack exchange,提问作者Oxelo
相关产品推荐
相关产品推荐

