用box.get_top()获取方框的上边界值
在我们用代码创建了一个方框绘图后,可以使用Pine Script的box.get_top()函数来获取该方框上边界在价格轴上的值。
该函数的标准语法是:
box.get_top(id)
id是我们想要查询的方框的标识符。这个ID是我们在调用box.new()创建方框时获得的,Pine Script正是依靠它来精确定位目标方框。
box.get_top()函数会返回一个代表方框上边界坐标的浮点数值。
快速范例
要获取方框的上边界,首先我们需要一个方框。我们使用box.new()来创建一个:
// 创建一个新的方框绘图
myBox = box.new(left=bar_index[50], top=100,
right=bar_index, bottom=0,
bgcolor=color.new(color.orange, 60),
border_width=2, border_color=color.fuchsia)
这段代码创建了一个纵向范围从价格100到0的方框。其ID被存储在myBox变量中。现在,我们可以使用这个ID来获取该方框的上边界坐标:
// 获取方框上边界的坐标
topBorder = box.get_top(id=myBox) // 返回 100
下图中的箭头直观地展示了box.get_top()函数返回的是哪个方框边界的坐标值:

顺便一提,此函数的关键字参数是可选的,可以省略以简化代码:
// 获取方框上边界的坐标
box.get_top(myBox) // 省略了 'id='
返回设定坐标与视觉坐标的区别
需要特别注意的是,box.get_top()函数返回的是你在创建或设置方框时为top参数赋予的数据值,而不是你在图表上肉眼看到的、最上方的边界。通常情况下,我们绘制的方框top值大于bottom值。在这种情况下,box.get_top()的返回值确实是视觉上的上边界。但是,Pine Script允许反向操作,即top的坐标值小于bottom的坐标值。在这种非典型情况下,box.get_top()返回的将是在图表上看起来像是下边界的值。
如果我们总是希望获取图表上最上方那个边界的坐标,无论方框是如何绘制的,可以使用下面这个自定义函数:
// GetTopBorderBox() 返回在图表上视觉呈现为上边界的价格轴坐标值。
// (无论方框是从上到下还是从下到上绘制,都有效。)
GetTopBorderBox(boxId) =>
math.max(box.get_top(boxId), box.get_bottom(boxId))
这个函数同时获取方框的上下边界数据值,然后使用math.max()返回两者中较大的一个,从而确保得到的总是视觉上的最上方坐标。我们可以这样使用它:
// 获取方框的视觉上边界
chartTopBorder = GetTopBorderBox(myBox)
box.get_top()的使用方式
获取到方框的上边界值后,有多种应用场景,例如:把一个方框的上边界作为另一个新方框的下边界,实现方框堆叠;在初始值的基础上,按比例移动上边界(例如,上移5%);在方框顶部创建一个文本标签,显示相关信息;在方框顶部附近绘制形状或字符,以作强调。
脚本范例
本指标旨在根据近期的价格范围,在图表上绘制一个向未来延伸的预测区域,并使用box.get_top()来精确地标记出这个区域的上边界价格。该脚本的完整代码如下:
//@version=5
indicator(title="获取上边界范例", overlay=true)
// 通过偏移tick来获取交易范围的最高高点和最低低点
highestHigh = ta.highest(high, 20) + (10 * syminfo.mintick)
lowestLow = ta.lowest(low, 20) - (10 * syminfo.mintick)
// 在图表的最后一个历史K线上创建方框和标签
if barstate.islastconfirmedhistory
// 绘制一个向未来延伸15根K线的方框,其上下边界为区间的极值
myBox = box.new(left=bar_index[5], top=highestHigh,
right=bar_index + 15, bottom=lowestLow,
bgcolor=color.new(color.lime, 90),
border_color=color.black, border_width=2)
// 使用标签显示方框的上边界价格
label.new(x=bar_index + 15, y=box.get_top(id=myBox),
style=label.style_label_left,
color=#6082B6, textcolor=color.white,
size=size.large, text="方框高点:\n" +
str.tostring(box.get_top(id=myBox)))
脚本首先计算出过去20根K线的最高高点和最低低点,并略微向外偏移,形成一个价格通道。核心逻辑在if barstate.islastconfirmedhistory块中,这确保了绘图代码只在最后一个历史K线上执行一次,以提高效率。
第一步是创建方框:box.new()创建一个从5根K线前延伸至未来15根K线的方框,其上下边界由我们计算的价格通道决定。
第二步是创建标签:label.new()在方框的右侧创建一个标签。我们调用box.get_top(myBox)来获取方框上边界的精确价格,并把它同时用于标签的y坐标和text内容,从而在标签上清晰地显示出方框的上边界价格。
最终,图表上会显示一个从历史延伸至未来的预测方框,并在其上边界附近有一个标签,精确地标明了其价格水平:

box.get_top()的重要特性
- 设定值与视觉值:
box.get_top()返回的是设定的数据值,不一定是视觉上的最高点。 - 禁用边框:即使方框的边框被禁用(不可见),
box.get_top()仍然能正常返回其上边界的逻辑坐标值。 - 边框宽度:
box.get_top()的返回值与边框的宽度无关。
总结
box.get_top()函数返回指定方框上边界的Y轴坐标值。- 这个坐标值是你在创建或设置方框时所设定的值,它可能不总是图表上视觉最上方的边界。
用box.get_bottom()获取方框的下边框值
在我们绘制一个方框后,Pine Script的box.get_bottom()函数可以返回该方框下边框的价格轴值。
该函数的标准语法格式如下:
box.get_bottom(id)
id参数是我们想要获取其下边框值的方框的标识符。这个ID是我们在使用box.new()创建方框时返回的值,Pine Script正是通过它来识别我们指的是哪个方框。没有它,Pine Script将无从知晓。
box.get_bottom()以一个浮点值的形式返回方框的下边框。
快速示例
要获取一个方框的下边框,我们首先需要一个方框。我们可以使用box.new()来创建一个:
// 创建一个新的方框绘图
myBox = box.new(left=bar_index[50], top=100,
right=bar_index, bottom=0,
bgcolor=color.new(color.orange, 60),
border_width=2, border_color=color.fuchsia)
这个代码片段创建了一个价格轴范围在100和0之间的方框。我们把box.new()返回的标识符保存在myBox变量中。
然后box.get_bottom()函数就可以使用这个变量来获取该方框的下边框了:
// 获取方框下边框坐标的价格值
bottomBorder = box.get_bottom(id=myBox) // 返回 0
下图中的箭头显示了box.get_bottom()返回的是哪个方框边框:

顺便一提,box.get_bottom()并不要求使用关键字参数。代码中使用它们只是为了让示例更清晰。但你可以省略它们以减少输入量,像这样也完全有效:
// 获取方框下边框坐标的价格值
box.get_bottom(myBox) // 省略了可选的 'id=' 部分
返回的是设置坐标,而非视觉坐标
上图看起来似乎理所当然;box.get_bottom()当然是返回方框的下边框!
但实际上,情况并非总是如此。box.get_bottom()函数返回的是我们先前为方框下边框设定的值。
当我们创建或更新一个方框的位置时,通常会把下边框设置为比上边框更低的价格值。在这种情况下,box.get_bottom()确实返回了图表上视觉意义上的下边框坐标。
但如果我们以相反的方向绘制方框,情况就不同了。当我们把一个方框的bottom参数设置为比其top参数更高的值时,box.get_bottom()仍然返回我们为bottom设定的那个值。但在这种情况下,这个值对应的其实是图表上视觉意义上的上边框。
如果我们只想简单地获取方框视觉上的下边框,而不管该方框是如何创建的,可以使用下面这个自定义函数:
// GetBottomBorderBox() 函数返回图表上显示为方框下边框的价格轴值。
// (对于从上到下绘制和从下到上创建的方框都有效。)
GetBottomBorderBox(boxId) =>
math.min(box.get_top(boxId), box.get_bottom(boxId))
这个函数首先获取方框的上边框(box.get_top())和其设定的下边框(box.get_bottom())的坐标。然后math.min()函数返回这两者中的较小值。这个最小值就是图表上视觉意义上的下边框。
如果我们已把方框标识符存储在名为myBox的变量中,那么就可以通过这个自定义函数来获取该方框的视觉下边框:
// 获取方框的视觉下边框
chartBottomBorder = GetBottomBorderBox(myBox)
box.get_bottom()的应用方式
方框的下边框值有多种应用方式,例如:在方框的下边框处放置一个文本标签,以提供关于该方框的信息;使用一个方框的下边框作为另一个方框的上边框坐标,从而把一个方框置于另一个之下;基于其初始值把下边框移动到其他位置,例如,把下边框下移20个最小变动单位;在方框的底部定位文本字符或形状。
示例脚本
让我们通过一个完整的脚本来探讨如何使用box.get_bottom()函数。下面的指标会围绕近期的高点和低点创建一个方框,以此来直观地高亮显示交易品种近期的交易范围。
通过box.get_bottom()函数,我们将获取方框的下边框,并把其值放入一个文本标签中。
该指标的完整代码如下:
//@version=5
indicator(title="获取下边框示例", overlay=true)
// 用极值价格和最小变动单位偏移来确定交易范围
highestHigh = ta.highest(high, 40) + (15 * syminfo.mintick)
lowestLow = ta.lowest(low, 40) - (15 * syminfo.mintick)
// 在图表的最后一根历史K线上创建方框和标签
if barstate.islastconfirmedhistory
// 用极值高低点方框来捕捉近期和未来的价格
myBox = box.new(left=bar_index[10], top=highestHigh,
right=bar_index + 30, bottom=lowestLow,
bgcolor=color.new(color.silver, 60),
border_color=color.navy, border_width=2)
// 用方框的底部价格标签来标注图表
label.new(x=bar_index + 30, y=box.get_bottom(id=myBox),
style=label.style_label_left,
color=#D70040, textcolor=color.white,
size=size.large, text="Box low:\n" +
str.tostring(box.get_bottom(id=myBox)))
首先,我们用indicator()函数来设置指标的属性,它为脚本命名并使其叠加显示在主图表上。
然后,我们计算近期的高点和低点:
// 用极值价格和最小变动单位偏移来确定交易范围
highestHigh = ta.highest(high, 40) + (15 * syminfo.mintick)
lowestLow = ta.lowest(low, 40) - (15 * syminfo.mintick)
为了得到最高高点,ta.highest()函数处理high变量的数据;对于最低低点,ta.lowest()函数则结合low变量。两个函数都考虑最近的40根K线(包括当前K线)。
我们把这两个极值分别用15倍的交易品种最小变动价格(syminfo.mintick)进行偏移,从而得到一个略微超出市场噪音范围的价格区间。
我们把这些极值高低点存储在highestHigh和lowestLow变量中以供后续使用。
接着,我们绘制一个方框:
// 在图表的最后一根历史K线上创建方框和标签
if barstate.islastconfirmedhistory
// 用极值高低点方框来捕捉近期和未来的价格
myBox = box.new(left=bar_index[10], top=highestHigh,
right=bar_index + 30, bottom=lowestLow,
bgcolor=color.new(color.silver, 60),
border_color=color.navy, border_width=2)
这个if语句测试barstate.islastconfirmedhistory变量,该变量仅在图表的最后一根已确认的历史K线上为true。当脚本运行到该K线时,我们做两件事。
首先,我们用box.new()绘制一个方框。这个方框显示在10根K线前(bar_index[10])和未来30根K线处(bar_index + 30)之间,其上下边框是我们之前计算的高点和低点。
我们把方框的背景设为银色(color.silver),并通过color.new()函数把其透明度设为60%。边框是海军蓝(color.navy),宽度为2像素。
我们把box.new()返回的标识符存储在myBox变量中,以备后用。
我们在if语句中做的另一件事是绘制一个标签:
// 用方框的底部价格标签来标注图表
label.new(x=bar_index + 30, y=box.get_bottom(id=myBox),
style=label.style_label_left,
color=#D70040, textcolor=color.white,
size=size.large, text="Box low:\n" +
str.tostring(box.get_bottom(id=myBox)))
这段代码调用label.new()函数来创建一个新标签。这个标签显示在当前K线右侧30根K线处(bar_index + 30)。其价格值被设为方框的下边框。为了得到这个值,我们调用box.get_bottom()函数,并使用myBox变量来识别目标方框。
标签本身指向左侧(label.style_label_left),背景为#D70040(一种红色调的十六进制颜色)。其文字为白色(color.white),并以大号字体(size.large)显示。
为了创建标签的文本,我们把一个字符串字面量与str.tostring()函数的返回值连接起来。该函数把方框的下边框——这是一个数值——转换为文本。这样做使得价格值能与标签的其他文本兼容。为了获取这个边框值,我们再次使用box.get_bottom()函数并通过myBox变量来识别方框。
在图表上,该方框捕捉了近期的最高价和最低价。该绘图向未来延伸了数根K线,而标签就出现在那里,并显示了方框下边框的值:

box.get_bottom()的特性
box.get_bottom()返回的是我们先前赋予方框bottom参数的值。这并不总是图表上视觉意义上的下边框。当我们给bottom一个比top更高的值时,box.get_bottom()返回的将是图表上视觉意义上的上边框坐标。- 当我们禁用一个方框的边框时,
box.get_bottom()仍然会返回方框的底部值,其行为就好像边框被启用一样。 - 一个方框的边框宽度不会改变
box.get_bottom()返回的值。因此,无论我们把边框设置得多粗,box.get_bottom()的返回值都保持不变。
总结
box.get_bottom()函数返回方框下边框的价格轴值。- 这个Y轴位置是我们先前赋予方框下边框的值。多数情况下,这个位置也就是图表上显示的下边框。
判断方框使用K线编号还是时间值
Pine Script允许我们通过两种方式在图表上定位一个方框:使用K线编号或时间值。然而,Pine Script原生并不支持直接查询一个已存在的方框究竟使用的是哪种定位方式。但在某些场景下(例如,动态修改方框位置时),明确这一点至关重要,因为后续的修改必须使用与创建时相同的坐标类型。幸运的是,我们可以通过一小段自定义代码来解决此问题。思路基于一个经验法则:K线编号通常是介于0到1,000,000之间的小正整数,而时间戳则是非常大的数值。因此,我们假设当方框的左右边界坐标都在这个范围内时,它使用的是K线编号,否则使用的就是时间值。
通用解决方案:自定义函数GetBoxXLoc()
下面的自定义函数可以判断一个方框的X轴坐标类型。如果方框使用K线编号,函数返回xloc.bar_index;如果使用时间值,则返回xloc.bar_time。函数代码如下:
// GetBoxXLoc() 函数用于获取指定方框的X轴坐标类型。
// 返回以下两个常量之一:
// - xloc.bar_index (方框使用K线编号定位)
// - xloc.bar_time (方框使用时间值定位)
// 注意:对于1970年1月1日 UTC 时间 0:00:00 至 0:16:40
// 之间的K线,此函数的判断可能不准确。
GetBoxXLoc(boxId) =>
boxLeftCoordinate = math.min(box.get_left(boxId), box.get_right(boxId))
boxRightCoordinate = math.max(box.get_left(boxId), box.get_right(boxId))
if boxLeftCoordinate >= 0 and boxRightCoordinate <= 1000000
xloc.bar_index
else
xloc.bar_time
GetBoxXLoc()函数接收一个boxId参数,即方框的ID。函数内部首先通过math.min()和math.max()结合box.get_left()和box.get_right(),来健壮地获取方框在视觉上的左右边界坐标,无论其绘制方向如何。然后,一个if/else语句检查这两个坐标是否都落在我们为K线编号假设的[0, 1000000]区间内。如果满足,函数返回xloc.bar_index;否则,返回xloc.bar_time。
使用这个函数非常简单,我们只需把其返回值与xloc.bar_index或xloc.bar_time进行比较即可。假设我们已创建一个方框,其ID存储在myBox变量中。要判断它是否使用K线编号,可以这样写:
// 判断方框是否使用K线编号
usesBars = GetBoxXLoc(myBox) == xloc.bar_index
同理,要判断它是否使用时间值:
// 判断方框是否使用时间值
if GetBoxXLoc(myBox) == xloc.bar_time
// 如果是,则执行相应操作...
完整脚本范例
下面的指标将演示如何使用GetBoxXLoc()函数。该脚本允许用户通过输入选项来选择创建的方框是使用K线编号还是时间值。随后,脚本会根据方框的坐标类型,动态地改变其边框的颜色和样式。指标的完整代码如下:
//@version=5
indicator(title="判断方框使用K线编号还是时间值", overlay=true)
// ... 此处插入上面定义的 GetBoxXLoc() 函数代码 ...
GetBoxXLoc(boxId) =>
boxLeftCoordinate = math.min(box.get_left(boxId), box.get_right(boxId))
boxRightCoordinate = math.max(box.get_left(boxId), box.get_right(boxId))
if boxLeftCoordinate >= 0 and boxRightCoordinate <= 1000000
xloc.bar_index
else
xloc.bar_time
// 1. 创建一个输入选项,用于在K线编号和时间值之间切换
boxCoordinateStyle = input.string("bar numbers",
title="方框坐标样式", options=["bar numbers", "time values"])
// 2. 将输入值转换为方框可用的坐标值和样式常量
xAxisValue = boxCoordinateStyle == "bar numbers" ? bar_index : time
xAxisStyle = boxCoordinateStyle == "bar numbers" ?
xloc.bar_index : xloc.bar_time
// 3. 在最后一个历史K线上,创建一个示例方框并根据坐标类型设置其样式
if barstate.islastconfirmedhistory
// 创建一个新方框
myBox = box.new(left=xAxisValue[40], top=high * 1.05,
right=xAxisValue, bottom=low * 0.95, bgcolor=na,
border_width=5, xloc=xAxisStyle)
// 如果方框使用时间值,则边框为红色;否则为蓝色
borderColor = GetBoxXLoc(myBox) == xloc.bar_time ?
color.red : color.blue
box.set_border_color(id=myBox, color=borderColor)
// 如果方框使用K线编号,则边框为虚线;否则为实线
if GetBoxXLoc(myBox) == xloc.bar_index
box.set_border_style(id=myBox, style=line.style_dashed)
else
box.set_border_style(id=myBox, style=line.style_solid)
脚本的逻辑分为三部分。第一部分是用户输入:通过input.string()创建一个下拉菜单,让用户选择坐标样式。第二部分是变量准备:使用条件运算符(?:)把用户的文本选择转换为Pine Script可用的实际坐标值(bar_index或time)和定位模式(xloc.bar_index或xloc.bar_time)。第三部分是绘图与样式设置:在最后一个历史K线上,使用准备好的变量创建一个方框。然后,调用我们自定义的GetBoxXLoc()函数来判断这个新创建方框的坐标类型,并据此设置其边框的颜色和线型。
当使用默认的bar numbers设置时,指标会创建一个蓝色的虚线边框方框:

如果我们把输入选项更改为time values,方框的坐标类型会随之改变,脚本检测到这一变化后,会把其边框变为红色的实线:

更具针对性的解决方案
虽然GetBoxXLoc()函数功能通用,但如果我们只需要一个简单的布尔值判断(是或否),以下两个函数会是更直接的选择。
第一个函数检查方框是否使用K线编号,在方框使用K线编号时返回true,否则返回false:
// BoxUsesBarNumbers() ...
BoxUsesBarNumbers(boxId) =>
boxLeftCoordinate = math.min(box.get_left(boxId), box.get_right(boxId))
boxRightCoordinate = math.max(box.get_left(boxId), box.get_right(boxId))
boxLeftCoordinate >= 0 and boxRightCoordinate <= 1000000
使用方法:
// 判断 'myBox' 是否使用K线编号
if BoxUsesBarNumbers(myBox)
// 执行相关操作...
第二个函数检查方框是否使用时间值,在方框使用时间值时返回true,否则返回false:
// BoxUsesTimeValues() ...
BoxUsesTimeValues(boxId) =>
boxLeftCoordinate = math.min(box.get_left(boxId), box.get_right(boxId))
boxRightCoordinate = math.max(box.get_left(boxId), box.get_right(boxId))
boxLeftCoordinate < 0 or boxRightCoordinate > 1000000
使用方法:
// 判断 'myBox' 是否使用时间值
if BoxUsesTimeValues(myBox)
// 执行相关操作...


