TradingView Pine Script:显示区间时部分支撑/阻力层级丢失
我不是开发者,靠AI制作了一款TradingView的支撑/阻力及区间可视化脚本。脚本可解析用户输入的支撑阻力层级(含标注major的重要层级、带连字符的区间,支持短写区间格式),以不同样式绘制在图表上,还支持开关区间显示功能。当前遇到的问题是:开启区间可视化时,部分支撑或阻力层级会消失,无法全部正常显示。
输入的支撑/阻力层级
支撑层级
5593-5588 (major), 5582, 5572, 5567 (major), 5560, 5555, 5540-45 (major), 5528 (major), 5519, 5512 (major), 5502, 5498, 5490-58 (major), 5483, 5474 (major), 5464 (major), 5457, 5445-50 (major), 5438 (major), 5434, 5428, 5423 (major), 5414 (major), 5405-10, 5375-5385
阻力层级
5604 (major), 5610, 5623, 5630 (major), 5636, 5643, 5653 (major), 5661 (major), 5668, 5672, 5678, 5685 (major), 5694, 5702, 5705 (major), 5709, 5713, 5720 (major), 5730 (major), 5741 (major), 5753, 5765, 5787, 5796, 5801, 5806 (major), 5816, 5821, 5825 (major), 5831, 5836 (major), 5839, 5845 (major)
问题原因
TradingView对单脚本可创建的绘图对象(线条、标签、箱体)有数量限制,默认上限为500个。你的脚本同时绘制大量层级线条、标签,加上区间箱体和标签,总数量超出限制,导致部分对象被系统丢弃,表现为层级消失。此外,原脚本每次刷新都会重复创建新对象,进一步加速触发数量限制。
修复方案
- 复用绘图对象:用
var声明对象数组,每次刷新先清理旧对象,再创建或更新新对象,避免重复累积。 - 优化数据存储:将层级和区间数据存储为数值/元组,减少字符串解析的冗余操作。
- 调整区间显示逻辑:让区间箱体延伸至图表右侧,避免固定长度的冗余绘制。
修复后的完整代码
//@version=5 indicator("SPX Levels - Fixed Range Display", overlay=true, max_bars_back=500) // 定义颜色 color normalResistanceColor = color.red color majorResistanceColor = color.orange color normalSupportColor = color.green color majorSupportColor = color.blue // 输入字段 var string support_input = input.string(defval="5593-5588 (major), 5582, 5572, 5567 (major), 5560, 5555, 5540-45 (major), 5528 (major), 5519, 5512 (major), 5502, 5498, 5490-58 (major), 5483, 5474 (major), 5464 (major), 5457, 5445-50 (major), 5438 (major), 5434, 5428, 5423 (major), 5414 (major), 5405-10, 5375-5385", title="支撑层级", group="每日层级") var string resistance_input = input.string(defval="5604 (major), 5610, 5623, 5630 (major), 5636, 5643, 5653 (major), 5661 (major), 5668, 5672, 5678, 5685 (major), 5694, 5702, 5705 (major), 5709, 5713, 5720 (major), 5730 (major), 5741 (major), 5753, 5765, 5787, 5796, 5801, 5806 (major), 5816, 5821, 5825 (major), 5831, 5836 (major), 5839, 5845 (major)", title="阻力层级", group="每日层级") var bool show_debug = input.bool(defval=false, title="显示调试信息", group="显示选项") var bool show_ranges = input.bool(defval=true, title="显示区间", group="显示选项") // 扩展短写区间 expand_range(level_string) => is_major = str.contains(level_string, "(major)") clean_str = str.replace(level_string, "(major)", "") range_parts = str.split(clean_str, "-") lower = str.tonumber(str.trim(array.get(range_parts, 0))) upper_str = str.trim(array.get(range_parts, 1)) float upper = na if not na(upper_str) if str.contains(upper_str, ".") upper := str.tonumber(upper_str) else lower_str = str.tostring(lower) prefix = str.substring(lower_str, 0, str.length(lower_str) - str.length(upper_str)) upper := str.tonumber(prefix + upper_str) else upper := lower [lower, upper, is_major] // 解析层级:分离单层级和区间 parse_levels(input_string) => single_levels = array.new_float(0) major_single_levels = array.new_float(0) ranges = array.new_tuple(0) // 存储(lower, upper, is_major) level_strings = str.split(input_string, ",") for i = 0 to array.size(level_strings) - 1 level = str.trim(array.get(level_strings, i)) if str.contains(level, "-") [lower, upper, is_major] = expand_range(level) if not na(lower) and not na(upper) array.push(ranges, tuple.new(lower, upper, is_major)) else price = str.tonumber(str.replace(level, "(major)", "")) if not na(price) array.push(single_levels, price) if str.contains(level, "(major)") array.push(major_single_levels, price) [single_levels, major_single_levels, ranges] // 解析支撑和阻力 [support_levels, major_support_levels, support_ranges] = parse_levels(support_input) [resistance_levels, major_resistance_levels, resistance_ranges] = parse_levels(resistance_input) // 复用线条和标签对象 var array<line> support_lines = array.new_line() var array<label> support_labels = array.new_label() var array<line> resistance_lines = array.new_line() var array<label> resistance_labels = array.new_label() var array<box> range_boxes = array.new_box() var array<label> range_labels = array.new_label() // 清理旧对象 cleanup_objects() => // 清理线条 for i = 0 to array.size(support_lines) - 1 line.delete(array.get(support_lines, i)) array.clear(support_lines) for i = 0 to array.size(resistance_lines) - 1 line.delete(array.get(resistance_lines, i)) array.clear(resistance_lines) // 清理标签 for i = 0 to array.size(support_labels) - 1 label.delete(array.get(support_labels, i)) array.clear(support_labels) for i = 0 to array.size(resistance_labels) - 1 label.delete(array.get(resistance_labels, i)) array.clear(resistance_labels) // 清理区间箱体和标签 for i = 0 to array.size(range_boxes) - 1 box.delete(array.get(range_boxes, i)) array.clear(range_boxes) for i = 0 to array.size(range_labels) - 1 label.delete(array.get(range_labels, i)) array.clear(range_labels) // 绘制单层级 draw_single_levels(levels, major_levels, is_support, lines_array, labels_array) => for i = 0 to array.size(levels) - 1 price = array.get(levels, i) is_major = array.includes(major_levels, price) line_style = is_major ? line.style_solid : line.style_dotted level_color = is_support ? (is_major ? majorSupportColor : normalSupportColor) : (is_major ? majorResistanceColor : normalResistanceColor) // 创建线条 new_line = line.new(x1=bar_index[1], y1=price, x2=bar_index, y2=price, color=level_color, style=line_style, width=1, extend=extend.right) array.push(lines_array, new_line) // 创建标签 new_label = label.new(bar_index, price, text=str.tostring(price) + (is_major ? " (Major)" : ""), style=label.style_label_down, color=color.new(level_color, 0), textcolor=color.white) array.push(labels_array, new_label) // 绘制区间 draw_ranges(ranges_array, is_support, boxes_array, labels_array) => for i = 0 to array.size(ranges_array) - 1 range_tuple = array.get(ranges_array, i) lower = tuple.get(range_tuple, 0) upper = tuple.get(range_tuple, 1) is_major = tuple.get(range_tuple, 2) range_color = is_support ? (is_major ? color.new(majorSupportColor, 80) : color.new(normalSupportColor, 80)) : (is_major ? color.new(majorResistanceColor, 80) : color.new(normalResistanceColor, 80)) // 创建箱体,延伸到右侧 new_box = box.new(left=bar_index, top=upper, right=bar_index + 100, bottom=lower, bgcolor=range_color, border_width=0, extend=extend.right) array.push(boxes_array, new_box) // 创建区间标签 new_label = label.new(bar_index + 5, (lower + upper) / 2, text="区间: " + str.tostring(lower) + "-" + str.tostring(upper) + (is_major ? " (Major)" : ""), style=label.style_label_down, color=color.new(range_color, 0), textcolor=color.white) array.push(labels_array, new_label) // 仅在最后一根K线更新绘图 if barstate.islast cleanup_objects() // 先清理旧对象 // 绘制单层级 draw_single_levels(support_levels, major_support_levels, true, support_lines, support_labels) draw_single_levels(resistance_levels, major_resistance_levels, false, resistance_lines, resistance_labels) // 绘制区间 if show_ranges draw_ranges(support_ranges, true, range_boxes, range_labels) draw_ranges(resistance_ranges, false, range_boxes, range_labels) // 调试信息 if show_debug and barstate.islast debug_text = "支撑层级数量: " + str.tostring(array.size(support_levels)) + "\n" + "重要支撑层级数量: " + str.tostring(array.size(major_support_levels)) + "\n" + "阻力层级数量: " + str.tostring(array.size(resistance_levels)) + "\n" + "重要阻力层级数量: " + str.tostring(array.size(major_resistance_levels)) + "\n" + "支撑区间数量: " + str.tostring(array.size(support_ranges)) + "\n" + "阻力区间数量: " + str.tostring(array.size(resistance_ranges)) label.new(bar_index, high, debug_text, color=color.white, textcolor=color.black, size=size.normal)
内容的提问来源于stack exchange,提问作者skyraider66

