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

