用label.set_xloc()更改标签的时间坐标类型
在我们的Pine Script代码绘制出标签后,可以使用label.set_xloc()函数来更改该标签时间轴坐标的类型。
每个TradingView标签都需要一个X轴坐标。Pine Script可以通过两种方式来设定这个坐标:使用K线编号或时间值。label.set_xloc()的作用,正是更改一个已存在的标签所使用的坐标类型。
这样,一个最初使用K线编号的标签就可以转而使用时间值,反之亦然。
要实现时间坐标类型的更改,label.set_xloc()需要三个信息:要修改的是哪个标签、新的时间坐标,以及要使用哪种坐标类型。我们来深入探讨。
函数语法格式
该函数的标准语法格式如下:
label.set_xloc(id, x, xloc)
id参数用于定义我们想要更改的标签的标识符。Pine Script正是通过这个标识符来识别要修改的具体标签,如果没有它,Pine Script将无从知晓我们想修改哪个标签。这个标识符由label.new()函数在创建标签时返回。如果我们(不小心)为该参数传入了na值,label.set_xloc()将无法更改标签的时间坐标类型。函数在这种情况下不会报错,而是会静默地不执行任何操作。x参数是一个数值,代表标签新的时间坐标。这个坐标既可以是K线编号,也可以是时间值。具体应提供哪种值,取决于xloc参数的设定。xloc是一个常量,用于设定标签新的坐标类型。我们有两个选项:xloc.bar_index使标签使用K线编号作为其X轴坐标(这也是标签的默认行为);xloc.bar_time让标签使用时间值作为其X轴坐标。
快速示例
我们可以从两个方向使用label.set_xloc():把标签从使用K线编号切换到使用时间值,或者反过来。我们来分别快速了解一下。
先看切换到时间值。要让一个标签改用时间值而非K线编号,我们首先需要一个标签。因此,我们先用label.new()创建一个:
// 在当前K线的收盘价处创建一个基于K线编号的标签
myLabel = label.new(x=bar_index, y=close, style=label.style_label_left,
color=color.fuchsia, size=size.large)
这段代码在当前K线的收盘价(由bar_index和close确定)处绘制了一个标签。其样式为指向左侧的箭头(label.style_label_left),颜色为紫红色(color.fuchsia),并且尺寸设置为大号(size.large)。
我们没有指定label.new()使用哪种时间坐标类型,这意味着标签将采用默认的K线编号模式。
label.new()返回的标识符被我们存入myLabel变量,以便后续通过此变量来访问该标签。
接着,我们更改该标签的时间轴坐标类型:
// 让标签改用时间值,并将其移动到当前K线
// 右侧6小时的位置
label.set_xloc(id=myLabel, x=time + 6 * 3600000, xloc=xloc.bar_time)
这里我们向label.set_xloc()传递了三个值。首先是myLabel变量,它告诉函数需要修改的是哪个标签。
然后,我们设置标签新的X轴坐标。由于我们想把标签切换到时间值模式,这里提供了一个时间值。我们用当前K线的时间戳(time),加上6小时对应的毫秒数(360万),从而得到一个比当前K线时间晚6小时的时间坐标。
最后,我们告诉标签要开始使用时间值。因此,第三个参数我们传入了xloc.bar_time。从此刻起,这个标签就从默认的K线编号模式切换到了时间值模式。
再看切换到K线编号。另一种用法是把标签从使用时间值切换回使用K线编号。首先,我们用label.new()创建一个基于时间的标签:
// 在K线的收盘价处创建一个基于时间的标签
myLabel = label.new(x=time, y=close, xloc=xloc.bar_time,
style=label.style_label_left, color=color.fuchsia,
size=size.large)
这段代码在当前K线的时间戳和收盘价处绘制了一个标签。xloc=xloc.bar_time参数告知标签应使用时间值(而非默认的K线编号)。标签的样式为指向左侧的箭头(label.style_label_left),颜色为紫红色(color.fuchsia),尺寸也设置为大号(size.large)。
我们把从label.new()获取的标签标识符存储在myLabel变量中,以便后续还能访问该标签。
然后,我们使用label.set_xloc()把该标签切换回K线编号模式:
// 将标签的坐标类型改回K线编号,并将其向右移动6根K线
label.set_xloc(id=myLabel, x=bar_index + 6, xloc=xloc.bar_index)
我们向该函数传递了三个参数。首先是myLabel,即存有标签标识符的变量,它告诉函数要修改哪个标签。
对于标签新的时间轴坐标,我们把当前K线编号(bar_index)加上6,这会把标签向当前K线右侧移动6根K线。
最后,我们传入xloc.bar_index值,它指示函数应把该标签的坐标类型切换为K线编号。
图表示例
我们上面讨论的两个快速示例,它们在图表上的外观是相同的。效果如下所示:

以下代码展示了如何把切换到时间值这种方法的代码片段整合为一个完整的指标:
//@version=5
indicator(title="label.set_xloc() 快速示例", overlay=true)
// 检查脚本是否正在图表的最后一根价格K线上进行计算
if barstate.islast
// 在当前K线的收盘价处创建一个基于K线编号的标签
myLabel = label.new(x=bar_index, y=close, style=label.style_label_left,
color=color.fuchsia, size=size.large)
// 让标签改用时间值,并将其移动到当前K线
// 右侧6小时的位置
label.set_xloc(id=myLabel, x=time + 6 * 3600000, xloc=xloc.bar_time)
首先,我们用indicator()函数来配置指标。title参数为脚本命名,而overlay=true使脚本叠加显示在主图表上。
接着,一个if语句检查脚本是否正在处理最后一根价格K线(通过barstate.islast判断)。如果条件为真,Pine Script便会执行我们前面讨论过的代码:label.new()创建一个新标签,随后label.set_xloc()把该标签的X轴坐标类型更改为时间值。
关键字参数
label.set_xloc()并非必须使用关键字参数。我在范例中使用它们,主要是为了让代码的意图更清晰。但我们完全可以省略它们,以减少代码的输入量。如果省略可选的id、x和xloc关键字,label.set_xloc()的写法如下:
// 让标签基于时间值定位,并将其向右移动6小时
label.set_xloc(myLabel, time + 6 * 3600000, xloc.bar_time)
// 将标签的定位方式改为K线编号,并将其向右移动6根K线
label.set_xloc(myLabel, bar_index + 6, xloc.bar_index)
label.set_xloc()的使用场景
label.set_xloc()主要用于以下两种场景:把一个采用K线编号定位的标签,切换为使用时间值定位;或者把一个采用时间值定位的标签,切换为使用K线编号定位。
虽然也可以只用label.set_xloc()来更新标签在时间轴上的坐标,但若仅为此目的,使用label.set_x()会更简单直接。
我们通常会把label.set_xloc()放在if条件语句中,这样就只会在特定情况下才去更改标签的时间坐标定位模式。由于标签自身会记住当前所用的定位模式,所以没必要在每一根K线上都去调用它。
总的来说,label.set_xloc()是一个不常用的函数。一旦label.new()在创建标签时指定了定位模式,后续需要再次切换的场景并不多。
在过去,Pine Script不支持通过K线编号来创建指向未来的标签,只有时间值可以,因此我们更频繁地使用label.set_xloc()把已有标签移动到未来坐标。但现在K线编号也支持未来坐标,切换定位模式的需求就大大降低了。
其他能改变标签位置的函数还包括label.set_y()(更新价格坐标)和label.set_x()(更新时间轴坐标)。
脚本范例
我们通过一个完整的脚本来学习label.set_xloc()的用法。下面的指标会绘制两条指数移动平均线(EMA),当均线交叉时,在图表上绘制一个新标签。
这个标签的坐标代表一个价格目标:时间坐标在未来24小时,价格坐标则根据均线交叉方向,设定在当时高点上方2%或低点下方2%的位置。
由于这个目标只对最近一次的交叉有意义,我们会把上一次交叉生成的标签移回其信号发出的K线位置。我们正是使用label.set_xloc()来完成这个操作。
指标的完整代码如下:
//@version=5
indicator(title="更改标签的xloc样式", overlay=true)
// 计算并绘制两条指数移动平均线 (EMAs)
fastAverage = ta.ema(close, 20)
slowAverage = ta.ema(close, 100)
plot(fastAverage, color=color.orange, title="快速均线")
plot(slowAverage, color=color.teal, linewidth=2, title="慢速均线")
// 创建持久化变量,用于追踪标签的相关信息
var barNumLastSignal = 0
var maLastSignal = 0.0
var label signalLabel = na
// 当均线交叉时,用标签进行标记(并重置上一个标签)
if ta.cross(fastAverage, slowAverage)
// 根据交叉方向,定义标签的价格坐标和颜色
labelPrice = high * 1.02
labelColour = color.green
if fastAverage < slowAverage
labelPrice := low * 0.98
labelColour := color.red
// 创建新标签,时间上向未来偏移24小时
signalLabel := label.new(time + 86400000, labelPrice,
xloc=xloc.bar_time, text="Target", color=labelColour,
textcolor=color.white)
// 存储均线交叉时的坐标(以便后续能将标签移回这个图表位置)
barNumLastSignal := bar_index
maLastSignal := fastAverage
// 将上一个旧标签移动到上次均线交叉的坐标,并清除其文本
label.set_xloc(signalLabel[1], barNumLastSignal[1], xloc.bar_index)
label.set_y(signalLabel[1], maLastSignal[1])
label.set_text(signalLabel[1], "")
脚本始于indicator()函数,它负责为脚本命名,并以overlay=true的形式叠加到主图表上。接着,ta.ema()计算出20周期和100周期的两条均线,分别存入fastAverage和slowAverage变量。plot()函数把这两条均线绘制在图表上,快速均线为橙色,慢速均线为青色。
然后,我们创建了三个持久化变量(使用var关键字):barNumLastSignal保存上次信号的K线编号,maLastSignal保存上次信号时快线的值,signalLabel保存标签的标识符。借助它们,我们就能在出现新信号时操作旧的标签。
脚本的核心逻辑位于if ta.cross(...)语句块中,它在均线交叉时触发。块内的代码首先确定标签的价格和颜色。默认是金叉(快线上穿慢线),目标价比高点高2%,颜色为绿色。如果判断为死叉(fastAverage < slowAverage),则目标价比低点低2%,颜色改为红色。
然后,label.new()函数创建一个文本标签:
// 创建新标签,时间上向未来偏移24小时
signalLabel := label.new(time + 86400000, labelPrice,
xloc=xloc.bar_time, text="Target", color=labelColour,
textcolor=color.white)
这个新标签被绘制在未来24小时的位置(time + 86400000毫秒),价格由labelPrice决定。xloc=xloc.bar_time明确指定使用时间值定位。标签文本为”Target”,颜色由labelColour决定,文字为白色。
接着,我们记录下当前交叉发生时的坐标信息:
// 存储均线交叉时的坐标(以便后续能将标签移回这个图表位置)
barNumLastSignal := bar_index
maLastSignal := fastAverage
当新信号发生时,脚本会把前一个标签移回它最初被触发的位置。为此,我们需要知道上一次交叉发生时的坐标。所以,这里我们把当前的K线编号bar_index和快线值fastAverage分别存入持久化变量。
最后,我们更新前一个标签:
// 将上一个旧标签移动到上次均线交叉的坐标,并清除其文本
label.set_xloc(signalLabel[1], barNumLastSignal[1], xloc.bar_index)
label.set_y(signalLabel[1], maLastSignal[1])
label.set_text(signalLabel[1], "")
我们用signalLabel[1]来获取前一个标签的标识符。因为signalLabel是持久化变量,当新标签标识符赋给当前K线的signalLabel时,前一根K线([1])的signalLabel值仍然是上一个标签的标识符。
这段代码里,label.set_xloc()把旧标签的定位模式切换为K线编号,并把它移动到上次信号的K线位置(barNumLastSignal[1]);label.set_y()把其价格坐标移动到上次信号的快线价格(maLastSignal[1]);label.set_text()清空其文本。
最终效果是:最新的均线交叉会生成一个指向未来的Target标签;而当更新的交叉出现时,这个Target标签会被移回交叉点并清除文字,只留下一个标记。在图表上,指标会为最近一次的均线交叉创建一个显示Target的标签,它被放置在交叉信号24小时之后,价格与信号K线相差2%。而其他更早的标签则显示在各自的均线交叉点上,并且不含Target文本:

label.set_xloc()的特性
有几点特性值得注意。一是模式锁定:一旦label.set_xloc()改变了标签的定位模式,后续所有函数(如label.set_x())在操作该标签时都必须使用新的模式。例如,切换到xloc.bar_index后,就只能用K线编号去定位。
二是未来限制:使用xloc.bar_index(K线编号)模式时,标签不能被放置在超过未来500根K线的位置。否则,Pine Script会报错:objects positioned using xloc.bar_index cannot be drawn further than 500 bars into the future。
三是参数兼容性:模式和坐标类型必须匹配。xloc.bar_index必须与K线编号一起使用,而xloc.bar_time必须与时间值一起使用,混用会导致错误。
四是历史无限制:该函数可以把标签放置在任何历史K线位置,无论使用K线编号还是时间值。
总结
label.set_xloc()用于切换一个已存在标签在时间轴上的定位模式。
- 它可以把标签在K线编号(
xloc.bar_index)和时间值(xloc.bar_time)之间切换。 - 函数需要三个参数:标签标识符、新的X轴坐标和新的定位模式。
- 由于只改变X轴(时间)坐标,该函数会使标签在图表上水平移动。
用label.set_yloc()锚定标签
在我们的Pine Script代码绘制出标签后,可以使用label.set_yloc()函数把该标签锚定到价格K线上。
标签锚定的作用是,让标签总是显示在价格K线的上方(或下方)。这样,标签就被绑定(或者说锚定)到了一根特定的K线上。即便我们之后更改标签的价格坐标,它的位置依旧会固定在该K线上。
要配置一个标签的锚定方式,label.set_yloc()需要两个信息:要修改的是哪个标签,以及要使用哪种锚定方式。我们来更深入地探讨一下这个函数。
函数语法格式
该函数的标准语法格式如下:
label.set_yloc(id, yloc)
id参数用于指定我们想要更改其Y轴锚定方式的标签的标识符。这个标识符告知Pine Script我们要修改哪个标签;如果没有它,Pine Script将无从知晓我们的意图。这个标识符由label.new()函数在创建标签时返回。如果我们(不小心)为该参数传入了na值,label.set_yloc()将无法更改标签的锚定方式(并且不会发生任何事)。函数在这种情况下不会报错。yloc参数用于定义标签新的锚定方式。共有三个选项:yloc.abovebar让标签出现在其时间坐标所在K线的上方;yloc.belowbar让标签显示在其时间坐标所在K线的下方;yloc.price则表示标签不被锚定,而是显示在我们选择的精确价格坐标上。
快速示例
要更改一个标签的锚定方式,我们首先需要一个标签。我们用label.new()创建一个:
// 在K线最高价处创建一个指向上方的灰色标签
myLabel = label.new(x=bar_index, y=high, color=color.gray,
style=label.style_label_up, size=size.huge)
这段代码在当前K线的最高价(由bar_index和high确定)处绘制了一个标签。它的颜色是灰色(color.gray),标签样式为指向上方的箭头(label.style_label_up),并且尺寸设置为超大号(size.huge)。
为了方便后续访问,我们把label.new()返回的标识符存储在myLabel变量中。
最初,这个标签显示在K线上方(在其最高价位置)。现在,我们使用label.set_yloc()把它锚定到K线的下方:
// 修改标签的Y轴行为;使其显示在
// 价格K线的下方,无论标签自身的价格坐标为何值
label.set_yloc(id=myLabel, yloc=yloc.belowbar)
我们向label.set_yloc()传递了两个参数。第一个参数myLabel是存有标签标识符的变量,它告诉函数要修改哪个标签。
另一个参数是yloc.belowbar。这个值会把标签锚定在其时间坐标所在的价格K线的下方。现在,无论标签的价格坐标是多少,它将总是显示在K线的下方。
图表示例
在图表上,我们刚刚创建的这个被锚定的标签看起来是这样的:

以下代码展示了如何把上面的两个代码片段整合为一个完整的脚本:
//@version=5
indicator(title="label.set_yloc() 快速示例", overlay=true)
// 判断脚本是否正在最后一根已确认的历史K线上进行计算
if barstate.islastconfirmedhistory
// 在K线最高价处创建一个指向上方的灰色标签
myLabel = label.new(x=bar_index, y=high, color=color.gray,
style=label.style_label_up, size=size.huge)
// 修改标签的Y轴行为;使其显示在
// 价格K线的下方,无论标签自身的价格坐标为何值
label.set_yloc(id=myLabel, yloc=yloc.belowbar)
首先,我们用indicator()函数来配置指标,通过title参数为脚本命名,并通过overlay=true使脚本叠加显示在主图表上。
接着,一个if语句判断脚本当前是否正在处理最后一根已确认的历史K线(通过barstate.islastconfirmedhistory判断)。如果条件为真,脚本便会执行我们前面讨论过的代码:label.new()创建一个新标签,随后label.set_yloc()更改其锚定方式。
关键字参数
label.set_yloc()的关键字参数是可选的。我在范例中使用它们,主要是为了让代码的意图更清晰。一旦熟悉了该函数,我们便可以省略id和yloc这类可选参数,从而减少代码输入量。不使用可选的关键字参数时,label.set_yloc()的写法如下:
// 始终将标签显示在其价格K线的下方
label.set_yloc(myLabel, yloc.belowbar)
label.set_yloc()的使用方式
label.set_yloc()主要有两个用途。一是锚定到K线:无论标签设定的价格坐标是多少,yloc.abovebar都会强制把它置于所属K线的上方,而yloc.belowbar则强制把它置于下方。二是精确定价:通过yloc.price模式,标签会被放置到我们指定的精确价格坐标上。
我们通常把label.set_yloc()放在if条件语句中,以便在特定情况下才触发,进而改变标签的锚定状态。由于标签会记住其锚定模式,所以无需在每个K线上重复调用label.set_yloc()。
如果我们的代码总是在创建标签后立即设定其锚定模式,那么直接在label.new()函数中设置会更方便,比单独再调用一次label.set_yloc()更节省代码。
我们可以使用label.set_x()来改变标签锚定在哪一根K线上。如果标签处于自由定价模式(yloc.price),我们还可以使用label.set_xy()同时修改其时间和价格坐标。
脚本范例
我们通过一个完整的脚本来学习label.set_yloc()的用法。下面的指标创建了一条平滑处理后的指数移动平均线。当价格穿越这条均线时,我们会绘制一个标签。
我们把这个标签作为一个价格目标,放置在距离信号K线15%的位置。当新的穿越信号出现时,上一个标签的目标便失去了意义。因此,我们使用label.set_yloc()把这个过时的标签移动到其K线的正上方,作为历史标记。
指标的完整代码如下:
//@version=5
indicator(title="更改标签的yloc样式", overlay=true)
// 计算并绘制一条平滑的指数移动平均线
smoothEMA = ta.ema(ta.ema(close, 50), 5)
plot(smoothEMA, color=color.orange, title="平滑EMA")
// 创建一个持久化的标签变量(以便我们能访问到上一个标签)
var label crossLabel = na
// 当价格穿越均线信号发生时,创建一个新标签
if ta.cross(close, smoothEMA)
// 根据穿越方向确定标签的价格坐标和颜色
labelPrice = high * 1.15
labelColour = color.green
if close < smoothEMA
labelPrice := low * 0.85
labelColour := color.red
// 在价格目标位创建一个新标签
crossLabel := label.new(bar_index, labelPrice,
text="Target", color=labelColour, textcolor=color.white)
// 将旧的、上一个标签移动到K线上方(并移除其文本)
label.set_yloc(crossLabel[1], yloc.abovebar)
label.set_text(crossLabel[1], "")
脚本始于indicator()函数,它为脚本命名并把它叠加在主图表上。接着,我们对ta.ema()函数进行二次调用(ta.ema(ta.ema(close, 50), 5)),从而得到一条50周期EMA的5周期平滑线,结果保存在smoothEMA变量中。plot()函数把这条平滑均线以橙色线图的形式绘制在图表上。
然后,我们声明一个名为crossLabel的持久化变量(使用var关键字)。该变量用于保存标签的标识符,这种方式能让我们方便地访问到上一个K线周期创建的标签。
if语句使用ta.cross()函数来检测收盘价(close)是否与平滑均线(smoothEMA)发生穿越。一旦穿越,if块内的代码便会执行。
这部分代码首先确定标签的价格和颜色。为简化代码,我们先假定是向上穿越,并把目标价格设在K线高点之上15%,颜色设为绿色。随后,一个嵌套的if语句判断,如果实际是向下穿越,则把目标价修改为K线低点之下15%,颜色也改为红色。
接下来,我们用label.new()创建标签:
// 在价格目标位创建一个新标签
crossLabel := label.new(bar_index, labelPrice,
text="Target", color=labelColour, textcolor=color.white)
这个标签被创建在当前K线(bar_index),其价格坐标由labelPrice变量决定(即高点上浮15%或低点下浮15%)。标签的文本为”Target”,文字颜色为白色,背景色则由labelColour变量(红色或绿色)决定。
label.new()返回的标识符被保存在crossLabel变量中。由于每次出现信号都会执行此操作,我们便可以通过该变量的历史值(crossLabel[1])来引用上一个创建的标签。
因为新标签的出现意味着上一个目标已失效,所以我们需要对旧标签进行处理:
// 将旧的、上一个标签移动到K线上方(并移除其文本)
label.set_yloc(crossLabel[1], yloc.abovebar)
label.set_text(crossLabel[1], "")
首先,label.set_yloc()把上一个标签(通过crossLabel[1]引用)锚定到其K线的正上方,我们为此传入yloc.abovebar值。然后,label.set_text()把该标签的文本设置为空字符串"",从而移除”Target”字样。
每当脚本创建一个新标签时,都会对上一个标签执行这两项修改。最终的效果是,所有历史信号的标签都会被统一移动到其K线的正上方,并清空文本。
在图表上,我们只会看到最近一次均线穿越所产生的Target标签。而所有早期的标签,都因label.set_yloc()的锚定作用,显示在各自价格K线的正上方:

label.set_yloc()的特性
有几个特性在实战中值得注意。一是价格坐标失效:一旦标签被锚定(yloc.abovebar或yloc.belowbar),再修改其价格坐标将不会产生任何效果,标签会粘在K线上。
二是移动锚定标签:若要移动一个已被锚定的标签,需分两步走:先用label.set_yloc(id, yloc.price)解除锚定,然后再用label.set_y()或label.set_xy()设置新的价格坐标。
三是锚定距离:标签与K线之间的距离是由TradingView平台固定的,我们无法通过代码配置这个距离。若想精确控制位置,只能使用yloc.price模式。
四是状态查询:Pine Script中没有提供函数来查询一个标签当前是否处于锚定状态。要确保其状态,只能通过再次调用label.set_yloc()来主动设置。
五是锚定归属:标签锚定在哪一根K线上,取决于其时间坐标(X轴),该坐标由label.new()、label.set_x()等函数设定,而非label.set_yloc()。
六是样式不自动调整:label.set_yloc()只改变位置,不改变样式。例如,把一个默认的向下箭头标签锚定到K线下方(yloc.belowbar),箭头的指向会显得很奇怪。需要使用label.new()或label.set_style()来手动调整标签样式(如改为label.style_label_up)。
总结
label.set_yloc()函数的核心功能是把标签锚定到其所属的价格K线上。- 该函数需要一个标签标识符(从
label.new()获取)和新的锚定模式。 yloc.abovebar使标签始终显示在K线上方;yloc.belowbar使其始终显示在K线下方。yloc.price则用于解除标签的锚定状态,使其恢复到由价格坐标决定的位置。- 标签一旦被锚定,其价格坐标就会失效,它会一直粘在所属的K线上。


