如何在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
相关产品推荐
相关产品推荐

