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

Pine Script谐波形态指标报错:历史引用操作符无效回溯值[-1]

谐波形态指标Pine Script v7报错修复

问题描述

开发谐波形态指标时触发以下错误:

Invalid number of bars back [-1] within history-referencing operator. The value must >=0 when the study is added to the chart

无论如何调整参数,起始索引始终小于0,原代码如下:

//@version=7
study(title="Harmonic Patterns", overlay=true)

// Define inputs
lookback_bars = input(title="Lookback Bars", type=input.integer, defval=200)
min_ratio = input(title="Minimum Ratio", type=input.float, defval=0.618)
max_ratio = input(title="Maximum Ratio", type=input.float, defval=0.786)
show_bat = input(title="Show Bat Pattern", type=input.bool, defval=true)
show_gartley = input(title="Show Gartley Pattern", type=input.bool, defval=true)
show_butterfly = input(title="Show Butterfly Pattern", type=input.bool, defval=true)
show_crab = input(title="Show Crab Pattern", type=input.bool, defval=true)
show_cypher = input(title="Show Cypher Pattern", type=input.bool, defval=true)

// Define ratios
a_b = 0.382
a_c = 0.382
b_c = 0.618
c_d = 0.786
x_a = 0.382
d_x = 1.272

// Define variables
num_patterns = 0

// Define colors
bat_color = color.red
gartley_color = color.orange
butterfly_color = color.yellow
crab_color = color.green
cypher_color = color.blue

// Define arrays
ratios = array.new_float()
patterns = array.new_string()
indexes = array.new_int()
prices = array.new_float()

// Additional function to check for patterns
// Modified fib function
fib(n) =>
    var float a = 1
    var float b = 1
    if n < 2
        a
    else
        for i = 2 to n
            a := a + b
            a, b := b, a
        a

// Additional function to check for patterns
pattern_found(_pattern, _ab, _ad, _cd, _xd, _bc) =>
    if _pattern == "BAT"
        _ad > min_ratio and _ad < max_ratio and _xd > 0.886 and _xd < 1.13
    else
        if _pattern == "GARTLEY"
            _ab > min_ratio and _ab < max_ratio and _cd > 1.27 and _cd < 1.618
        else
            if _pattern == "BUTTERFLY"
                _ab > min_ratio and _ab < max_ratio and _cd > 1.618 and _cd < 2.24
            else
                if _pattern == "CRAB"
                    _ad > min_ratio and _ad < max_ratio and _xd > 1.618 and _xd < 2.618
                else
                    if _pattern == "CYPHER"
                        _ab > min_ratio and _ab < max_ratio and _cd > 0.786 and _cd < 0.886 and _bc < 0.382
                    else
                        false

// Calculate ratios and patterns
for i = max(bar_index - lookback_bars, 0) to bar_index - 2
    high_price = high[i]
    low_price = low[i]
    a_price = high[i+1]
    b_price = fib(1) * (a_price - low_price) + low_price
    c_price = fib(2) * (a_price - low_price) + low_price
    d_price = fib(3) * (a_price - low_price) + low_price
    x_price = a_price - x_a * (a_price - d_price)
    
    ab = abs(a_price - b_price) / abs(a_price - c_price)
    bc = abs(b_price - c_price) / abs(a_price - c_price)
    cd = abs(c_price - d_price) / abs(a_price - c_price)
    ad = abs(a_price - d_price) / abs(a_price - c_price)
    xd = abs(x_price - d_price) / abs(a_price - d_price)
    
    if pattern_found("BAT", ab, ad, cd, xd, bc)
        array.push(ratios, ad)
        array.push(patterns, "BAT")
    else
        if pattern_found("GARTLEY", ab, ad, cd, xd, bc)
            array.push(ratios, ab)
            array.push(patterns, "GARTLEY")
        else
            if pattern_found("BUTTERFLY", ab, ad, cd, xd, bc)
                array.push(ratios, ab)
                array.push(patterns, "BUTTERFLY")
            else
                if pattern_found("CRAB", ab, ad, cd, xd, bc)
                    array.push(ratios, ad)
                    array.push(patterns, "CRAB")
                else
                    if pattern_found("CYPHER", ab, ad, cd, xd, bc)
                        array.push(ratios, ab)
                        array.push(patterns, "CYPHER")

    array.push(indexes, i)
    array.push(prices, high[i])


// Plot patterns
for i = 0 to array.size(ratios) - 1
    var color line_color = na
    pattern = array.get(patterns, i)
    if pattern == "BAT"
        line_color := bat_color
    else if pattern == "GARTLEY"
        line_color := gartley_color
    else if pattern == "BUTTERFLY"
        line_color := butterfly_color
    else if pattern == "CRAB"
        line_color := crab_color
    else if pattern == "CYPHER"
        line_color := cypher_color
    line.new(x1=bar_index - array.get(indexes, i), y1=array.get(prices, i), x2=bar_index - array.get(indexes, i), y2=array.get(prices, i) + tr, color=line_color, width=2)

// Label patterns
for i = 0 to array.size(ratios) - 1
    pattern = array.get(patterns, i)
    ratio = array.get(ratios, i)
    label_text = pattern + "\n" + tostring(ratio, "#.##")
    var color label_color = na
    if pattern == "BAT"
        label_color := bat_color
    else if pattern == "GARTLEY"
        label_color := gartley_color
    else if pattern == "BUTTERFLY"
        label_color := butterfly_color
    else if pattern == "CRAB"
        label_color := crab_color
    else if pattern == "CYPHER"
        label_color := cypher_color
    label.new(x=bar_index - array.get(indexes, i), y=array.get(prices, i), text=label_text, color=label_color, textcolor=color.white, style=label.style_label_down)

错误根源

  1. 历史索引越界:循环中a_price = high[i+1]的写法,当i取到bar_index - 2时,i+1等于bar_index -1,图表加载初期(前2根K线)bar_index数值过小,会导致i+1变成负数,触发历史引用错误。
  2. 数组不同步:无论是否识别到形态,都向indexes和prices数组插入数据,但仅在识别到形态时更新ratios和patterns,导致四个数组长度不一致,后续计算坐标时出现负数。
  3. 循环范围逻辑混乱:初始循环的结束值为bar_index -2,当图表K线数量不足时,该值可能小于起始值,循环执行逻辑出错。

修复方案

  • 限制循环边界:将循环结束值改为bar_index -3,确保i+1不会超出有效索引范围;同时添加bar_index >= lookback_bars判断,等K线数量足够再执行形态识别。
  • 同步数组更新:仅在识别到形态时,才向四个数组同时插入数据,保证数组长度一致。
  • 用var声明数组:避免每次刷新K线都重建数组,防止数据重复或丢失。
  • 修正坐标计算:直接用indexes数组存储的bar_index值作为线条和标签的X坐标,无需用当前bar_index做减法,避免负数。

修复后的完整代码

//@version=7
study(title="Harmonic Patterns", overlay=true)

// Define inputs
lookback_bars = input(title="Lookback Bars", type=input.integer, defval=200)
min_ratio = input(title="Minimum Ratio", type=input.float, defval=0.618)
max_ratio = input(title="Maximum Ratio", type=input.float, defval=0.786)
show_bat = input(title="Show Bat Pattern", type=input.bool, defval=true)
show_gartley = input(title="Show Gartley Pattern", type=input.bool, defval=true)
show_butterfly = input(title="Show Butterfly Pattern", type=input.bool, defval=true)
show_crab = input(title="Show Crab Pattern", type=input.bool, defval=true)
show_cypher = input(title="Show Cypher Pattern", type=input.bool, defval=true)

// Define ratios
a_b = 0.382
a_c = 0.382
b_c = 0.618
c_d = 0.786
x_a = 0.382
d_x = 1.272

// Define colors
bat_color = color.red
gartley_color = color.orange
butterfly_color = color.yellow
crab_color = color.green
cypher_color = color.blue

// Define persistent arrays using var
var ratios = array.new_float()
var patterns = array.new_string()
var indexes = array.new_int()
var prices = array.new_float()

// Modified fib function
fib(n) =>
    var float a = 1
    var float b = 1
    if n < 2
        a
    else
        for i = 2 to n
            a := a + b
            a, b := b, a
        a

// Pattern check function
pattern_found(_pattern, _ab, _ad, _cd, _xd, _bc) =>
    if _pattern == "BAT"
        _ad > min_ratio and _ad < max_ratio and _xd > 0.886 and _xd < 1.13
    elif _pattern == "GARTLEY"
        _ab > min_ratio and _ab < max_ratio and _cd > 1.27 and _cd < 1.618
    elif _pattern == "BUTTERFLY"
        _ab > min_ratio and _ab < max_ratio and _cd > 1.618 and _cd < 2.24
    elif _pattern == "CRAB"
        _ad > min_ratio and _ad < max_ratio and _xd > 1.618 and _xd < 2.618
    elif _pattern == "CYPHER"
        _ab > min_ratio and _ab < max_ratio and _cd > 0.786 and _cd < 0.886 and _bc < 0.382
    else
        false

// Calculate ratios and patterns only when enough bars are available
if bar_index >= lookback_bars
    // Clear arrays on each new bar to avoid duplicate entries
    array.clear(ratios)
    array.clear(patterns)
    array.clear(indexes)
    array.clear(prices)
    
    for i = bar_index - lookback_bars to bar_index - 3
        high_price = high[i]
        low_price = low[i]
        a_price = high[i+1]
        b_price = fib(1) * (a_price - low_price) + low_price
        c_price = fib(2) * (a_price - low_price) + low_price
        d_price = fib(3) * (a_price - low_price) + low_price
        x_price = a_price - x_a * (a_price - d_price)
        
        ab = abs(a_price - b_price) / abs(a_price - c_price)
        bc = abs(b_price - c_price) / abs(a_price - c_price)
        cd = abs(c_price - d_price) / abs(a_price - c_price)
        ad = abs(a_price - d_price) / abs(a_price - c_price)
        xd = abs(x_price - d_price) / abs(a_price - d_price)
        
        pattern_detected = false
        if show_bat and pattern_found("BAT", ab, ad, cd, xd, bc)
            array.push(ratios, ad)
            array.push(patterns, "BAT")
            pattern_detected := true
        elif show_gartley and pattern_found("GARTLEY", ab, ad, cd, xd, bc)
            array.push(ratios, ab)
            array.push(patterns, "GARTLEY")
            pattern_detected := true
        elif show_butterfly and pattern_found("BUTTERFLY", ab, ad, cd, xd, bc)
            array.push(ratios, ab)
            array.push(patterns, "BUTTERFLY")
            pattern_detected := true
        elif show_crab and pattern_found("CRAB", ab, ad, cd, xd, bc)
            array.push(ratios, ad)
            array.push(patterns, "CRAB")
            pattern_detected := true
        elif show_cypher and pattern_found("CYPHER", ab, ad, cd, xd, bc)
            array.push(ratios, ab)
            array.push(patterns, "CYPHER")
            pattern_detected := true
        
        // Only push to indexes and prices if a pattern was detected
        if pattern_detected
            array.push(indexes, i)
            array.push(prices, high_price)

// Plot patterns
for i = 0 to array.size(ratios) - 1
    pattern = array.get(patterns, i)
    line_color = switch pattern
        "BAT" => bat_color
        "GARTLEY" => gartley_color
        "BUTTERFLY" => butterfly_color
        "CRAB" => crab_color
        "CYPHER" => cypher_color
        => na
    if not na(line_color)
        line.new(x1=array.get(indexes, i), y1=array.get(prices, i), 
                 x2=array.get(indexes, i), y2=array.get(prices, i) + tr, 
                 color=line_color, width=2)

// Label patterns
for i = 0 to array.size(ratios) - 1
    pattern = array.get(patterns, i)
    ratio = array.get(ratios, i)
    label_text = pattern + "\n" + tostring(ratio, "#.##")
    label_color = switch pattern
        "BAT" => bat_color
        "GARTLEY" => gartley_color
        "BUTTERFLY" => butterfly_color
        "CRAB" => crab_color
        "CYPHER" => cypher_color
        => na
    if not na(label_color)
        label.new(x=array.get(indexes, i), y=array.get(prices, i), 
                  text=label_text, color=label_color, textcolor=color.white, 
                  style=label.style_label_down)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 16:04:58