如何限制Pine Script中plotshape数量?或转用label数组实现
解决Pine Script中星期标签数量过多的问题
核心问题说明
plotshape属于绘图类函数,只要条件满足就会在对应K线上绘制,无法像line那样用数组单独管理每个实例,所以没法直接通过数组限制显示数量。要实现回溯限制,最直接的方案是替换成label对象——label是可创建、删除的独立元素,能和line一样用数组控制数量。
具体实现步骤
- 创建存储label的数组:用于管理所有生成的星期标签,控制数量上限。
- 定义生成标签的函数:封装label的创建、数组添加和旧标签删除逻辑,和你之前处理line的逻辑一致。
- 替换plotshape为统一的触发逻辑:用switch判断星期几,生成对应文本,满足条件时调用函数创建标签。
修改后的完整代码(替换原"Display the days of week"部分)
//@version=5 indicator("Show Week and Day Seperator", overlay=true, max_lines_count=500, max_boxes_count=500) // Constants and One-Time-Init Vars { transpLine = 0 // } // Inputs { grpWeekLine = "================== Week Seperator Lines ==================" i_user_week_start = input.string(title='Week Separator on Day', defval='Sunday', options=['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], group=grpWeekLine) i_user_week_toggle = input(title='Show Week Separator Line', defval=true, inline="Weekly Line", group=grpWeekLine) i_WeekSepLookBack = input.int(title="Lookback", defval=5, minval=0, maxval=400, group=grpWeekLine) i_weeklyLineCl =input.color(color.new(color.blue, transpLine), "", inline="Weekly Line", group=grpWeekLine) i_weekLineWidth = input.int(title='Week Line Width', defval=4, minval=0, maxval=20, step=1, group=grpWeekLine) i_user_week_line_style = input.string(title='Week Line Style', defval='dashed', options=['solid', 'dashed', 'dotted'], group=grpWeekLine) grpDaykLine = "=================== Day Seperator Lines ===================" i_user_day_toggle = input(title='Show Day Separator Line', defval=true, inline="Day Line", group=grpDaykLine) i_daylyLineCl =input.color(color.new(color.blue, transpLine), "", inline="Day Line", group=grpDaykLine) i_DaySepLookBack = input.int(title="Lookback", defval=5, minval=0, maxval=400, group=grpDaykLine) i_dayLineWidth = input.int(title='Day Line Width', defval=4, minval=0, maxval=20, step=1, group=grpDaykLine) i_user_day_line_style = input.string(title='Day Line Style', defval='dashed', options=['solid', 'dashed', 'dotted'], group=grpDaykLine) // Alternative Lines using backcolours grpWeekDayLineAdditional = "================== Additional Settings ==================" i_user_show_on_1hour = input(title='Show Day Separator and Days of Week on 1 hour Chart', defval=false, group=grpWeekDayLineAdditional) i_user_show_on_updaily = input(title='Show Week Separator up to the Daily Chart', defval=false, group=grpWeekDayLineAdditional) i_showDOW = input.bool(true, title='Show days of week', inline="i_ShowDow", group=grpWeekDayLineAdditional) i_user_dow_color = input.color(color.new(color.blue, transpLine), "", inline="i_ShowDow", group=grpWeekDayLineAdditional) i_isShortDayLabel = input.bool(false, "Use short names for days of week (Mon, Tue...)", group=grpWeekDayLineAdditional) i_EndlessLines = input.bool(true, title="Reduce length of horizontal Seperators", group=grpWeekDayLineAdditional) i_Seplength = input.int(title="Seperator Length", defval=800, group=grpWeekDayLineAdditional) // } week_line_style = i_user_week_line_style == 'solid' ? line.style_solid : i_user_week_line_style == 'dashed' ? line.style_dashed : i_user_week_line_style == 'dotted' ? line.style_dotted : line.style_solid day_line_style = i_user_day_line_style == 'solid' ? line.style_solid : i_user_day_line_style == 'dashed' ? line.style_dashed : i_user_day_line_style == 'dotted' ? line.style_dotted : line.style_solid tickerExchangeOffset = 5 int new_day_start_time = 17 int dayLabelStartTime = 1 week_start_day = i_user_week_start == 'Sunday' ? dayofweek.sunday : i_user_week_start == 'Monday' ? dayofweek.monday : i_user_week_start == 'Tuesday' ? dayofweek.tuesday : i_user_week_start == 'Wednesday' ? dayofweek.wednesday : i_user_week_start == 'Thursday' ? dayofweek.thursday : i_user_week_start == 'Friday' ? dayofweek.friday : i_user_week_start == 'Saturday' ? dayofweek.saturday : dayofweek.sunday // Functions { f_vline(Lookback, BarIndex, Color, LineStyle, LineWidth, LookBack) => low_ = hl2 - (syminfo.mintick) * i_Seplength high_ = hl2 + (syminfo.mintick) * i_Seplength var createLines = array.new_line() array.push(createLines, line.new(time, low_, time, high_, xloc.bar_time, extend=extend.none, color=Color, style=LineStyle, width=LineWidth)) if array.size(createLines) > Lookback ln = array.shift(createLines) line.delete(ln) f_vlineEndless(Lookback, BarIndex, Color, LineStyle, LineWidth, LookBack) => var createLines = array.new_line() array.push(createLines, line.new(BarIndex, 0, BarIndex, 1, extend=extend.both, color=Color, style=LineStyle, width=LineWidth)) if array.size(createLines) > Lookback ln = array.shift(createLines) line.delete(ln) // 新增:生成星期标签的函数和存储数组 var label_array = array.new_label() f_create_dow_label(lookback, day_text, x_time, y_loc) => // 创建标签,style设为none对应原来的circle透明点,只显示文本 new_label = label.new(x=x_time, y=y_loc, text=day_text, color=dot_color, textcolor=i_user_dow_color, style=label.style_none, size=size.tiny) array.push(label_array, new_label) // 超过回溯数量时删除最旧的标签 if array.size(label_array) > lookback old_label = array.shift(label_array) label.delete(old_label) // } // Calcutations { if syminfo.timezone == 'Etc/UTC' new_day_start_time += tickerExchangeOffset dayLabelStartTime += tickerExchangeOffset dayLabelStartTime // Add the start of week line isNewWeek() => dayofweek == week_start_day ? 1 : 0 isStartTime() => hour == new_day_start_time and minute == 0 ? 1 : 0 isValidDaySeparatorResolution() => timeframe.isdwm == true or timeframe.period == '60' and not i_user_show_on_1hour or timeframe.in_seconds() >= timeframe.in_seconds("120") ? 0 : 1 isValidWeekSeparatorResolution() => i_user_show_on_updaily and timeframe.isdwm == false ? 1 : not i_user_show_on_updaily and timeframe.in_seconds() <= timeframe.in_seconds("59") ? 1 : 0 isValidDaySeparator = isValidDaySeparatorResolution() isValidDayTextSeparator = isValidDaySeparatorResolution() isValidWeekSeparator = isValidWeekSeparatorResolution() if isValidWeekSeparator and i_user_week_toggle and isNewWeek() == 1 and isStartTime() == 1 and i_EndlessLines == true f_vline(i_WeekSepLookBack, bar_index, i_weeklyLineCl, week_line_style, i_weekLineWidth, i_WeekSepLookBack) if isValidWeekSeparator and i_user_week_toggle and isNewWeek() == 1 and isStartTime() == 1 and not i_EndlessLines == true f_vlineEndless(i_WeekSepLookBack, bar_index, i_weeklyLineCl, week_line_style, i_weekLineWidth, i_WeekSepLookBack) // Add daily separator isNewDay() => dayofweek != week_start_day ? 1 : 0 if isValidDaySeparator and i_user_day_toggle and isNewDay() == 1 and isStartTime() == 1 and i_EndlessLines == true f_vline(i_DaySepLookBack, bar_index, i_daylyLineCl, day_line_style, i_dayLineWidth, i_DaySepLookBack) if isValidDaySeparator and i_user_day_toggle and isNewDay() == 1 and isStartTime() == 1 and not i_EndlessLines == true f_vlineEndless(i_DaySepLookBack, bar_index, i_daylyLineCl, day_line_style, i_dayLineWidth, i_DaySepLookBack) // Display the days of week - 替换原来的plotshape逻辑 dot_color = color.new(color.silver, 100) dowtext_color = color.new(color.silver, 0) // 统一触发条件 dow_label_condition = i_showDOW and isValidDayTextSeparator and hour == dayLabelStartTime and minute == 0 if dow_label_condition // 根据星期几和短名称设置生成文本 day_text = na if not i_isShortDayLabel day_text := switch dayofweek dayofweek.monday => "Monday" dayofweek.tuesday => "Tuesday" dayofweek.wednesday => "Wednesday" dayofweek.thursday => "Thursday" dayofweek.friday => "Friday" else day_text := switch dayofweek dayofweek.monday => "Mon" dayofweek.tuesday => "Tue" dayofweek.wednesday => "Wed" dayofweek.thursday => "Thu" dayofweek.friday => "Fri" // 只在工作日生成标签 if not na(day_text) // 计算标签位置:x轴偏移8个bar(对应原来的offset=8),y轴在最低价下方 x_pos = time + 8 * timeframe.multiplier * timeframe.seconds y_pos = low - syminfo.mintick * 10 // 调用函数创建标签,使用日分隔线的回溯值控制数量 f_create_dow_label(i_DaySepLookBack, day_text, x_pos, y_pos) // } // Plots { // }
关键改动说明
- 用
array.new_label存储所有星期标签,和你管理line的逻辑完全一致,超过回溯值就删除最旧的标签。 - 用
switch替代原来10个重复的plotshape,代码更简洁易维护。 - label的位置、样式完全匹配原来的plotshape效果,
style=label.style_none对应原来的透明circle,只显示文本。 - 标签数量由
i_DaySepLookBack控制,和日分隔线的回溯值保持一致,也可以改成单独的输入参数。
内容的提问来源于stack exchange,提问作者Luca
相关产品推荐
相关产品推荐

