Pine Script循环生成横向box时位置偏移问题求助
Pine Script长周期Box偏移问题排查与解决思路
问题描述
脚本基于锚定日期计算多组未来日期范围,支持两种周期波长(如120/50日历日),用box组件可视化每个时间段,通过xloc=xloc.bar_time定位横向位置,不同阶段用不同颜色区分:
- 正常情况:选择1-4次重复时,所有box显示正常
- 异常情况:选择5次及以上重复时,长波长(120天)对应的box会向右偏移,早期日期范围被省略,仅后期box显示正常
- 疑问:是否与回溯期(lookback period)有关?
脚本代码
//@version=5 indicator('Calendar Days 2', max_labels_count = 500, overlay = true) // Inputs anchor_date_DC = input.time(timestamp("01 Jan 2023 05:00"), "Anchor Date Bottom DC") anchor_date_SC = input.time(timestamp("01 Jan 2023 05:00"), "Anchor Date Bottom SC") cycle_period_DC = input.int(120, 'Cycle Period DC(Calendar Days)') cycle_period_SC = input.int(50, 'Cycle Period SC (Calendar Days)') number_dates = input.int(5, 'Number of Future Dates' ) // Conversions UNIX time cycle_period_DC_unix = cycle_period_DC * 86400000 cycle_period_SC_unix = cycle_period_SC * 86400000 bottom_date_DC = anchor_date_DC - cycle_period_DC_unix bottom_date_SC = anchor_date_SC - cycle_period_SC_unix for i = 1 to number_dates // Draw Dominant Cycle (DC) bottom_date_DC := bottom_date_DC + cycle_period_DC_unix DC_bottom_up_mid = int(bottom_date_DC + (cycle_period_DC_unix/100*12.5)) DC_bottom_up_end = int(bottom_date_DC + (cycle_period_DC_unix/100*37.5)) DC_top_down_start = bottom_date_DC + (cycle_period_DC_unix/100*50) DC_top_down_mid = int(bottom_date_DC + (cycle_period_DC_unix/100*62.5)) DC_top_down_end = int(bottom_date_DC + (cycle_period_DC_unix/100*87.5)) bottom_date_next_DC = bottom_date_DC + cycle_period_DC_unix box.new(bottom_date_DC, 10, DC_bottom_up_mid, 19, xloc=xloc.bar_time, border_color=color.new(color.rgb(0,255,8),70), border_width=0,bgcolor= color.new(color.rgb(0, 255, 8),70)) box.new(DC_bottom_up_mid, 10, DC_bottom_up_end, 19, xloc=xloc.bar_time, text=str.tostring(cycle_period_DC), border_color=color.new(#a1fbc1, 0), border_width=0, bgcolor=color.new(#a1fbc1, 70)) box.new(DC_bottom_up_end, 10, DC_top_down_start, 19, xloc=xloc.bar_time, border_color=color.new(color.rgb(0,255,8),70), border_width=0, bgcolor=color.new(color.rgb(0,255,8),70)) box.new(DC_top_down_start, 10, DC_top_down_mid, 19, xloc=xloc.bar_time, border_color=color.new(color.rgb(255,0,0),70), border_width=0, bgcolor=color.new(color.rgb(255,0,0),70)) box.new(DC_top_down_mid, 10, DC_top_down_end, 19, xloc=xloc.bar_time, border_color=color.new(#ff7d7d, 70), border_width=0, bgcolor=color.new(#ff7d7d, 70)) box.new(DC_top_down_end, 10, bottom_date_next_DC, 19, xloc=xloc.bar_time, border_color=color.new(color.rgb(255,0,0),70), border_width=0, bgcolor=color.new(color.rgb(255,0,0),70)) // Draw Secondary Cycle (SC) bottom_date_SC := bottom_date_SC + cycle_period_SC_unix SC_bottom_up_start = bottom_date_SC SC_bottom_up_mid = int(SC_bottom_up_start + (cycle_period_SC_unix/100*12.5)) SC_bottom_up_end = int(SC_bottom_up_start + (cycle_period_SC_unix/100*37.5)) SC_top_down_start = SC_bottom_up_start + (cycle_period_SC_unix/100*50) SC_top_down_mid = int(SC_bottom_up_start + (cycle_period_SC_unix/100*62.5)) SC_top_down_end = int(SC_bottom_up_start + (cycle_period_SC_unix/100*87.5)) bottom_date_next_SC = SC_bottom_up_start + cycle_period_SC_unix box.new(SC_bottom_up_start, 0, SC_bottom_up_mid, 9, xloc=xloc.bar_time, border_color=color.new(color.rgb(0,255,8),70), border_width=0,bgcolor= color.new(color.rgb(0, 255, 8),70)) box.new(SC_bottom_up_mid, 0, SC_bottom_up_end, 9, xloc=xloc.bar_time, text=str.tostring(cycle_period_SC), border_color=color.new(#a1fbc1, 0), border_width=0, bgcolor=color.new(#a1fbc1, 70)) box.new(SC_bottom_up_end, 0, SC_top_down_start, 9, xloc=xloc.bar_time, border_color=color.new(color.rgb(0,255,8),70), border_width=0, bgcolor=color.new(color.rgb(0,255,8),70)) box.new(SC_top_down_start, 0, SC_top_down_mid, 9, xloc=xloc.bar_time, border_color=color.new(color.rgb(255,0,0),70), border_width=0, bgcolor=color.new(color.rgb(255,0,0),70)) box.new(SC_top_down_mid, 0, SC_top_down_end, 9, xloc=xloc.bar_time, border_color=color.new(#ff7d7d,70), border_width=0, bgcolor=color.new(#ff7d7d, 70)) box.new(SC_top_down_end, 0, bottom_date_next_SC, 9, xloc=xloc.bar_time, border_color=color.new(color.rgb(255,0,0),70), border_width=0, bgcolor=color.new(color.rgb(255,0,0),70))
问题根源分析
- Box数量超限被自动清理:TradingView对
box组件有默认数量限制(默认50个),脚本未设置max_boxes_count参数。当重复次数≥5时,创建的box总数为5*(6+6)=60,超过默认上限,系统会自动删除最早创建的box。长周期的box时间更早,被优先删除,导致早期范围消失,看起来像是向右偏移。 - 重复创建Box加剧问题:脚本在每个bar都会执行循环并重新创建所有box,导致box数量翻倍增长,进一步触发数量限制。
解决思路
1. 提高Box数量上限
在indicator()函数中添加max_boxes_count参数,设置足够大的值以容纳所有需要创建的box:
indicator('Calendar Days 2', max_labels_count = 500, max_boxes_count = 500, overlay = true)
2. 避免重复创建Box
仅在最后一个bar创建所有box,避免每个bar重复执行创建逻辑,减少不必要的box数量:
修改脚本,将循环逻辑包裹在if barstate.islast条件中:
//@version=5 indicator('Calendar Days 2', max_labels_count = 500, max_boxes_count = 500, overlay = true) // Inputs anchor_date_DC = input.time(timestamp("01 Jan 2023 05:00"), "Anchor Date Bottom DC") anchor_date_SC = input.time(timestamp("01 Jan 2023 05:00"), "Anchor Date Bottom SC") cycle_period_DC = input.int(120, 'Cycle Period DC(Calendar Days)') cycle_period_SC = input.int(50, 'Cycle Period SC (Calendar Days)') number_dates = input.int(5, 'Number of Future Dates' ) // Conversions UNIX time cycle_period_DC_unix = cycle_period_DC * 86400000 cycle_period_SC_unix = cycle_period_SC * 86400000 // 仅在最后一个bar执行创建逻辑 if barstate.islast bottom_date_DC = anchor_date_DC - cycle_period_DC_unix bottom_date_SC = anchor_date_SC - cycle_period_SC_unix for i = 1 to number_dates // Draw Dominant Cycle (DC) bottom_date_DC := bottom_date_DC + cycle_period_DC_unix DC_bottom_up_mid = int(bottom_date_DC + (cycle_period_DC_unix/100*12.5)) DC_bottom_up_end = int(bottom_date_DC + (cycle_period_DC_unix/100*37.5)) DC_top_down_start = bottom_date_DC + (cycle_period_DC_unix/100*50) DC_top_down_mid = int(bottom_date_DC + (cycle_period_DC_unix/100*62.5)) DC_top_down_end = int(bottom_date_DC + (cycle_period_DC_unix/100*87.5)) bottom_date_next_DC = bottom_date_DC + cycle_period_DC_unix box.new(bottom_date_DC, 10, DC_bottom_up_mid, 19, xloc=xloc.bar_time, border_color=color.new(color.rgb(0,255,8),70), border_width=0,bgcolor= color.new(color.rgb(0, 255, 8),70)) box.new(DC_bottom_up_mid, 10, DC_bottom_up_end, 19, xloc=xloc.bar_time, text=str.tostring(cycle_period_DC), border_color=color.new(#a1fbc1, 0), border_width=0, bgcolor=color.new(#a1fbc1, 70)) box.new(DC_bottom_up_end, 10, DC_top_down_start, 19, xloc=xloc.bar_time, border_color=color.new(color.rgb(0,255,8),70), border_width=0, bgcolor=color.new(color.rgb(0,255,8),70)) box.new(DC_top_down_start, 10, DC_top_down_mid, 19, xloc=xloc.bar_time, border_color=color.new(color.rgb(255,0,0),70), border_width=0, bgcolor=color.new(color.rgb(255,0,0),70)) box.new(DC_top_down_mid, 10, DC_top_down_end, 19, xloc=xloc.bar_time, border_color=color.new(#ff7d7d, 70), border_width=0, bgcolor=color.new(#ff7d7d, 70)) box.new(DC_top_down_end, 10, bottom_date_next_DC, 19, xloc=xloc.bar_time, border_color=color.new(color.rgb(255,0,0),70), border_width=0, bgcolor=color.new(color.rgb(255,0,0),70)) // Draw Secondary Cycle (SC) bottom_date_SC := bottom_date_SC + cycle_period_SC_unix SC_bottom_up_start = bottom_date_SC SC_bottom_up_mid = int(SC_bottom_up_start + (cycle_period_SC_unix/100*12.5)) SC_bottom_up_end = int(SC_bottom_up_start + (cycle_period_SC_unix/100*37.5)) SC_top_down_start = SC_bottom_up_start + (cycle_period_SC_unix/100*50) SC_top_down_mid = int(SC_bottom_up_start + (cycle_period_SC_unix/100*62.5)) SC_top_down_end = int(SC_bottom_up_start + (cycle_period_SC_unix/100*87.5)) bottom_date_next_SC = SC_bottom_up_start + cycle_period_SC_unix box.new(SC_bottom_up_start, 0, SC_bottom_up_mid, 9, xloc=xloc.bar_time, border_color=color.new(color.rgb(0,255,8),70), border_width=0,bgcolor= color.new(color.rgb(0, 255, 8),70)) box.new(SC_bottom_up_mid, 0, SC_bottom_up_end, 9, xloc=xloc.bar_time, text=str.tostring(cycle_period_SC), border_color=color.new(#a1fbc1, 0), border_width=0, bgcolor=color.new(#a1fbc1, 70)) box.new(SC_bottom_up_end, 0, SC_top_down_start, 9, xloc=xloc.bar_time, border_color=color.new(color.rgb(0,255,8),70), border_width=0, bgcolor=color.new(color.rgb(0,255,8),70)) box.new(SC_top_down_start, 0, SC_top_down_mid, 9, xloc=xloc.bar_time, border_color=color.new(color.rgb(255,0,0),70), border_width=0, bgcolor=color.new(color.rgb(255,0,0),70)) box.new(SC_top_down_mid, 0, SC_top_down_end, 9, xloc=xloc.bar_time, border_color=color.new(#ff7d7d,70), border_width=0, bgcolor=color.new(#ff7d7d, 70)) box.new(SC_top_down_end, 0, bottom_date_next_SC, 9, xloc=xloc.bar_time, border_color=color.new(color.rgb(255,0,0),70), border_width=0, bgcolor=color.new(color.rgb(255,0,0),70))
3. 验证历史数据范围
如果调整后仍有问题,检查图表加载的历史数据是否覆盖了所有box的时间范围。可以手动在TradingView图表设置中增加历史数据加载天数,确保最早的box时间在加载范围内。
内容的提问来源于stack exchange,提问作者Adrian Stangell
相关产品推荐
相关产品推荐

