Pine Script:无数组实现符合条件的枢轴点连线 解决现有问题
问题描述
我已成功编写Pine Script脚本,可基于特定条件在两个枢轴点之间绘制连线,条件如下:
- 后续(或再下一个)枢轴点的高点必须低于原枢轴点高点;
- 后续枢轴点的影线需“触碰”原枢轴点的影线;
- 原枢轴高点影线与当前枢轴高点影线之间的区间内若存在更高高点,则禁止绘制连线;满足多条件时可从原枢轴高点生成“连线扇”。
目前通过数组实现了功能,但存在3个问题:
- 新K线生成时脚本因数组越界报错,源于数组初始化时使用
last_bar_index,1分钟周期问题突出;删除var则无法正常编译; - 脚本运行缓慢,即便加入终止回溯的逻辑仍需数秒计算;
- 怀疑存在无需数组的更优实现方式,但尚未找到。
附上原代码:
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © sincereStork12718 //@version=5 indicator("Pivot lines", overlay=true, max_boxes_count=500, max_lines_count=500) //--------------------------------------- //Variable declaration //--------------------------------------- nbrBars = bar_index plot (nbrBars, title = "nbrBars", display = display.data_window) plot(last_bar_index, title = "last_bar_index", display = display.data_window) //--------------------------------------- // Pivot to downside with ARRAYS working 99.9% //--------------------------------------- //Declare arrays var index_array_bear = array.new<int>(last_bar_index) var high_array = array.new<float>(last_bar_index) var upwick_array = array.new<float>(last_bar_index) var shadow_high = array.new<float>(last_bar_index+1) isAttFUBear = ta.pivothigh(1,1) // For this example ta.pivothigh(1,1) will produce the same result isFUBear = ta.pivothigh(1,1) //For this example ta.pivothigh(1,1) will produce the same result //Get bar_index, the high and the start of the upper wick for all AttFU/FU to the downside in the series from first to last bar var i_dn = 0 if (isAttFUBear or isFUBear) == 1 array.set(index_array_bear, i_dn, bar_index[1]) array.set(high_array, i_dn, high[1]) array.set(upwick_array, i_dn, math.max(open[1], close[1])) i_dn += 1 var j_dn = 0 array.set(shadow_high, j_dn, high) j_dn += 1 //Draw line from index n to all index n++ that satisfies the condition below //1. n++ index must be lower than the n:th index, i.e. high[n++] < high[n] //2. n++ index must have it's high above upwick of the n:th, i.e. high[n++] > upwick[n] //3. There must be a filter that removes any high higher than high[n] and high[n++] to not draw any unneccesary lines, i.e. if a "top" is found is not longer neccecary to look backwards cnt1 = 1 top_found = false while i_dn >= 2 and i_dn-1-cnt1 >= 0 and top_found == false if array.get(high_array, i_dn-1-cnt1) > array.get(high_array, i_dn-1) //Checking if previous FU is higher than the current, if NOT, check the next previous etc. if array.get(high_array, i_dn-1) >= array.get(upwick_array, i_dn-1-cnt1) //Check if current high is retesting the wick of the previous //testing filter high in between high_in_range = array.new<float>(nbrBars) //Create temporary array that stores all high values between the first and last endpoints of the line for cnt2 = array.get(index_array_bear, i_dn-1-cnt1) to array.get(index_array_bear, i_dn-1) array.set(high_in_range, cnt2, array.get(shadow_high, cnt2)) max_high_in_range = array.max(high_in_range, 2) //Return the second highest high within the range (excluding the i-1-cnt1 which is the higest) if array.get(high_array, i_dn-1) > max_high_in_range line.new(array.get(index_array_bear, i_dn-1-cnt1), array.get(high_array, i_dn-1-cnt1), array.get(index_array_bear, i_dn-1), array.get(high_array, i_dn-1), color = color.white, style = line.style_dashed, width = 1) if i_dn-1-cnt1-1 > 0 //Checking if current lookback FU is higher than previous and next. If true then stop the search if array.get(high_array, i_dn-1-cnt1) > array.get(high_array, i_dn-1-cnt1+1) and array.get(high_array, i_dn-1-cnt1) > array.get(high_array, i_dn-1-cnt1-1) top_found := true cnt1 := cnt1 +1
无需数组的优化实现
可以通过回溯历史K线+内置函数替代数组存储的方式解决所有问题,核心思路是:
- 每次检测到新的枢轴高点时,直接回溯历史枢轴点,无需提前存储所有枢轴数据;
- 用
ta.highest()替代临时数组计算区间最高值,大幅提升效率; - 避免固定长度数组,彻底解决越界问题。
优化后的代码:
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © sincereStork12718 //@version=5 indicator("Pivot Lines (No Arrays)", overlay=true, max_lines_count=500) // 定义枢轴高点条件(与原脚本一致) is_pivot_high = ta.pivothigh(1, 1) // 仅用动态数组存储必要的枢轴数据,避免固定长度越界 var pivot_data = array.new<float>(0) // 当检测到新枢轴高点时,记录数据并回溯验证条件 if is_pivot_high current_pivot_idx = bar_index[1] current_pivot_high = high[1] current_pivot_upwick = math.max(open[1], close[1]) // 将当前枢轴数据加入数组(动态扩容,无越界问题) array.push(pivot_data, current_pivot_idx) array.push(pivot_data, current_pivot_high) array.push(pivot_data, current_pivot_upwick) // 回溯历史枢轴点,验证条件并绘制连线 pivot_count = array.size(pivot_data) / 3 top_found = false // 从倒数第二个枢轴开始向前遍历 for i = pivot_count - 2 downto 0 if top_found break // 取出历史枢轴数据 hist_pivot_idx = array.get(pivot_data, i*3) hist_pivot_high = array.get(pivot_data, i*3+1) hist_pivot_upwick = array.get(pivot_data, i*3+2) // 条件1:当前枢轴高点 < 历史枢轴高点 if current_pivot_high >= hist_pivot_high continue // 条件2:当前枢轴高点触碰历史枢轴的上影线 if current_pivot_high < hist_pivot_upwick continue // 条件3:区间内无更高高点(排除两个枢轴自身) bar_distance = current_pivot_idx - hist_pivot_idx if bar_distance <= 1 continue // 计算区间内的最高值(跳过两个枢轴点) range_high = ta.highest(high, bar_distance)[1] if range_high > hist_pivot_high // 发现更高顶部,停止回溯 top_found := true continue // 所有条件满足,绘制连线 line.new(hist_pivot_idx, hist_pivot_high, current_pivot_idx, current_pivot_high, color=color.white, style=line.style_dashed, width=1)
优化说明
- 解决数组越界:使用动态数组
array.new<float>(0),每次新增枢轴时array.push()自动扩容,彻底避免固定长度数组的越界问题; - 提升运行速度:
- 移除了临时数组和嵌套循环,改用
ta.highest()直接计算区间最高值,效率提升显著; - 一旦发现更高顶部立即终止回溯,减少不必要的计算;
- 移除了临时数组和嵌套循环,改用
- 简化逻辑:无需提前存储所有K线的高点,仅在检测到新枢轴时才回溯验证,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Dennis Nilsson
相关产品推荐
相关产品推荐

