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

如何在Pine Script中编写Zig Zag水平线(HH/HL/LL/LH)及穿越提示

Pine Script实现高低点水平线绘制与穿越信号方案

核心功能说明

  • 识别并标记**顶部(HH/HL)和底部(LL/LH)**极值点
  • 从高低点绘制延伸至当前K线的水平线
  • 检测价格对水平线的向上/向下穿越并触发信号
  • 存储高低点的X(K线索引)、Y(价格)坐标,支持后续调用

完整代码实现

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © tgh
//@version=5
indicator('高低点水平线与穿越信号', 'LevelSignal', overlay=true, precision=2, max_bars_back = 1000)

// 基础输入参数
showHHLL = input(defval=true, title="显示高低点标记")
showHHw = input(defval=true, title="显示高低点线条与标签")
prd1 = input.int(10, title="ZigZag周期", minval = 2, maxval = 20)

// ZigZag样式参数
showzz = input.string("显示ZigZag 1", title = "ZigZag显示选项", options = ["显示ZigZag 1", "显示ZigZag 2", "显示全部", "隐藏全部"])
showhhll = input.string("显示高低点 1", title = "高低点显示选项", options = ["显示高低点 1", "显示高低点 2", "显示全部", "隐藏全部"])
upcol1 = input(defval = color.lime, title="上升ZigZag颜色")
dncol1 = input(defval = color.red, title="下降ZigZag颜色")
txtcol = input(defval = color.black, title="标签文字颜色")
zz1style = input.string("虚线", title = "ZigZag线条样式", options = ["虚线", "点线"])
zz1width = input.int(2, title = "ZigZag线条宽度", minval = 1, maxval = 4)

// 识别高低点极值
float ph1 = ta.highestbars(high, prd1) == 0 ? high : na
float pl1 = ta.lowestbars(low, prd1) == 0 ? low : na
var dir1 = 0
dir1 := (ph1 and na(pl1)) ? 1 : (pl1 and na(ph1)) ? -1 : dir1

// ZigZag数据存储数组
var max_array_size = 22
var zigzag1 = array.new_float(0)
oldzigzag1 = array.copy(zigzag1)

// ZigZag数组操作函数
add_to_zigzag(pointer, value, bindex)=>
    array.unshift(pointer, bindex)
    array.unshift(pointer, value)
    if array.size(pointer) > max_array_size
        array.pop(pointer)
        array.pop(pointer)

update_zigzag(pointer, value, bindex, dir)=>
    if array.size(pointer) == 0
        add_to_zigzag(pointer, value, bindex)
    else
        if (dir == 1 and value > array.get(pointer, 0)) or (dir == -1 and value < array.get(pointer, 0))
            array.set(pointer, 0, value)
            array.set(pointer, 1, bindex)
        0.

// 更新ZigZag数据
dir1changed = ta.change(dir1)
if ph1 or pl1
    if dir1changed 
        add_to_zigzag(zigzag1, dir1 == 1 ? ph1 : pl1, bar_index)
    else
        update_zigzag(zigzag1, dir1 == 1 ? ph1 : pl1, bar_index, dir1)

// 高低点类型存储(HH=22, HL=21, LH=12, LL=11)
var MacierzNr = array.new_int()
// 存储高低点坐标与类型的数组(格式:(bar_index, price, type))
var levelCoords = array.new_tuple()

// 绘制线条、标签并存储坐标
if array.size(zigzag1) >= 6 and showHHLL      
    var line zzline1 = na
    var label zzlabel1 = na
    if array.get(zigzag1, 0) != array.get(oldzigzag1, 0) or array.get(zigzag1, 1) != array.get(oldzigzag1, 1)
        if array.get(zigzag1, 2) == array.get(oldzigzag1, 2) and array.get(zigzag1, 3) == array.get(oldzigzag1, 3)
            line.delete(zzline1)
            label.delete(zzlabel1)
            array.remove(MacierzNr,0)                        
        // 绘制ZigZag连接线条
        if (showzz == "显示ZigZag 1" or showzz == "显示全部") and showHHw
            zzline1 := line.new( x1 = math.round(array.get(zigzag1, 1)), y1 = array.get(zigzag1, 0), 
                                 x2 = math.round(array.get(zigzag1, 3)), y2 = array.get(zigzag1, 2), 
                                 color = dir1 == 1 ? upcol1 : dncol1, 
                                 width = zz1width, 
                                 style = zz1style == "虚线" ? line.style_dashed : line.style_dotted)
        // 标记高低点并存储坐标
        if (showhhll == "显示高低点 1" or showhhll == "显示全部")
            hhlltxt1 = dir1 == 1 ? array.get(zigzag1, 4) < array.get(zigzag1, 0) ? "HH" : "LH" : array.get(zigzag1, 4) > array.get(zigzag1, 0) ? "LL" : "HL"            
            labelcol = dir1 == 1 ? array.get(zigzag1, 0) > array.get(zigzag1, 4) ? upcol1 : dncol1 : array.get(zigzag1, 0) < array.get(zigzag1, 4) ? dncol1 : upcol1
            hhllNr1 = dir1 == 1 ? array.get(zigzag1, 4) < array.get(zigzag1, 0) ? 22 : 12 : array.get(zigzag1, 4) > array.get(zigzag1, 0) ? 11 : 21
            array.unshift(id=MacierzNr,value=hhllNr1)
            
            // 存储高低点坐标与类型
            currentX = math.round(array.get(zigzag1, 1))
            currentY = array.get(zigzag1, 0)
            array.unshift(levelCoords, tuple.new(currentX, currentY, hhlltxt1))
            
            // 绘制从高低点延伸至当前K线的水平线
            line.new(x1=currentX, y1=currentY, x2=bar_index, y2=currentY, 
                     color=labelcol, width=1, style=line.style_solid)
            
            zzlabel1 := showHHw ? label.new(x = currentX, y = currentY, text = hhlltxt1, 
                                           color = labelcol, textcolor = txtcol, 
                                           style = dir1 == 1 ? label.style_label_down : label.style_label_up, 
                                           size= size.small) : na          
// 价格穿越信号检测
if array.size(levelCoords) > 0
    // 获取最近的高低点数据
    latestCoord = array.get(levelCoords, 0)
    latestY = tuple.get(latestCoord, 1)
    latestType = tuple.get(latestCoord, 2)
    
    // 向上穿越底部水平位信号
    bullishCross = ta.crossover(close, latestY) and (latestType == "LL" or latestType == "LH")
    // 向下穿越顶部水平位信号
    bearishCross = ta.crossunder(close, latestY) and (latestType == "HH" or latestType == "HL")
    
    // 触发信号时显示标记
    if bullishCross
        label.new(bar_index, low, "向上穿越\n" + latestType, color=color.green, textcolor=color.white, style=label.style_label_up)
    if bearishCross
        label.new(bar_index, high, "向下穿越\n" + latestType, color=color.red, textcolor=color.white, style=label.style_label_down)

关键功能细节

  • 高低点识别:通过周期内极值点+ZigZag方向逻辑,精准判断HH(更高高点)、HL(更高低点)、LH(更低高点)、LL(更低低点)类型
  • 坐标存储:使用tuple结构将高低点的K线索引、价格、类型存入数组levelCoords,后续可通过array.get和tuple.get调用任意历史高低点数据
  • 水平线绘制:从每个极值点K线位置绘制水平线,延伸至当前K线,直观展示关键支撑/阻力位
  • 穿越信号:通过ta.crossover和ta.crossunder检测收盘价与水平线的交叉,触发时显示对应方向的信号标签

内容的提问来源于stack exchange,提问作者Tomasz Nadwor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 10:37:33