如何用Pine Script在图表上绘制趋势线
在TradingView平台上,我们可以手动绘制趋势线来分析价格走势。但如果想让指标或策略脚本自动画出趋势线,该怎么做呢?这一节我们就来解决这个问题。
用line.new()创建趋势线
自Pine Script第4版起,代码就可以直接创建趋势线了。要让指标或策略在图表上画线,我们在代码中执行line.new()函数。
在每一根执行该函数的K线上,都会出现一条新的趋势线。线条创建之后,代码还可以对它做多项调整,比如更新位置、更改颜色,也可以删除它。但所有这些操作的前提是:先把线画出来。
要用代码创建一条趋势线,我们需要指定两个图表位置,TradingView随后会在这两点之间连一条线。执行line.new()最少要提供四个值:
line.new(x1, y1, x2, y2)
第一个参数x1设置线条起点的时间轴坐标,y1指定该点的价格轴坐标,这两个参数共同构成线条的起始位置。x2和y2则设置线条终点的时间和价格坐标,决定线条画到哪里结束。
先看一个基本的例子:
line.new(x1=bar_index[10], y1=close[10], x2=bar_index, y2=close)
这里我们创建了一条趋势线,填写了全部四个必需参数。起点用的是10根K线前的K线编号(bar_index[10])和那根K线的收盘价(close[10]),终点落在当前K线编号(bar_index)和当前收盘价(close)上。
line.new()除了这四个必需参数,还有更多可选参数,用来配置线条的外观。它完整的语法格式是这样的:
line.new(x1, y1, x2, y2, xloc, extend, color, style, width)
| 参数 | 描述 |
|---|---|
x1 |
设置线条第一个点的时间坐标(必需)。可以用K线编号(默认)或时间值。当xloc参数设为xloc.bar_time时,应使用时间值。 |
y1 |
指定线条第一个点的价格坐标(必需)。 |
x2 |
设置线条第二个点的时间坐标(必需)。可以是K线编号(默认)或时间值。要用后者,需将xloc参数设为xloc.bar_time。 |
y2 |
定义线条第二个点的价格坐标(必需)。 |
xloc |
指定线条使用哪种时间坐标(可选)。用xloc.bar_index时,线条通过K线编号定位,这是默认行为;用xloc.bar_time时,线条的X轴坐标使用时间值,这样就能把线画到未来。 |
extend |
定义趋势线的延伸方式(可选)。默认是extend.none,线条不超出两个端点。extend.right使线条向右无限延伸,extend.left向左无限延伸,extend.both则向两个方向同时延伸。 |
color |
设置线条的颜色(可选)。可以用标准颜色、十六进制颜色或带透明度的颜色。 |
style |
指定趋势线的样式(可选)。默认是实线(line.style_solid),其他选项有点线(line.style_dotted)、虚线(line.style_dashed)以及箭头样式(line.style_arrow_left、line.style_arrow_right和line.style_arrow_both)。 |
width |
设置趋势线的宽度,以像素为单位(可选)。默认是1,数值越大线条越粗。 |
这里有个细节要注意:使用K线编号作为时间坐标的趋势线,只能画在当前及之前的K线上。如果想把线画到未来的某个时间点,就不能用K线编号,而必须改用时间值——把line.new()的xloc参数设置为xloc.bar_time,时间值本身则可以用K线的时间变量(如time和time_close)来获取。
另外,创建趋势线后,line.new()会返回对这条线的一个引用(也就是它的ID)。把这个值保存在变量里是个好习惯,这样之后才能访问这条线。否则我们将没有办法移动它、改它的样式或删除它。
快速示例:用line.new()画线
实际使用line.new()时,比上表罗列的一堆参数看起来简单得多。我们来上手试试。
大多数情况下,我们用line.new()画的是一条基于K线编号(bar_index)的趋势线。代码如下:
//@version=5
indicator(title="快速示例:line.new()", overlay=true)
// 在最后一根价格K线上,创建一条新的趋势线
if barstate.islast
line.new(x1=bar_index[35], y1=close[35],
x2=bar_index, y2=close)
这个迷你指标里的if语句判断脚本当前是否正在处理图表的最后一根价格K线。如果是,barstate.islast变量返回true。这样,我们就只在一根K线上创建一条趋势线。
在if语句内部,我们执行line.new()并提供四个值。前两个指定线条的起点:X轴坐标是bar_index[35],即35根K线前的K线编号;对应的Y轴坐标是那根K线的收盘价(close[35])。
另外两个值设置线条的终点:当前K线编号(bar_index)作为时间轴坐标,当前收盘价(close)作为价格轴坐标。定义好两个端点后,TradingView就会在它们之间画出一条线。
这条趋势线在图表上的效果如下:

把趋势线画到未来
默认情况下,line.new()创建的线用K线编号作为时间坐标。但我们也可以改用时间值来设置时间坐标,这样就能把线画到未来——也就是当前K线右侧的图表区域。
下面是用时间值创建趋势线的写法:
//@version=5
indicator(title="快速示例:line.new()", overlay=true)
// 在图表的最后一根K线上,绘制一条延伸至
// 未来一天的线条
if barstate.islast
line.new(x1=time[35], y1=close[35],
x2=time + 86400000, y2=close * 0.99,
xloc=xloc.bar_time)
这里我们同样只在最后一根价格K线上(barstate.islast)创建趋势线,并在该K线上执行line.new()。
我们对这个函数做了三件事。首先,通过x1和y1参数设置线条起点:时间坐标是35根K线前的开盘时间(time[35]),价格坐标是那根K线的收盘价(close[35])。
第二件事是定义线条的终点(x2、y2)。终点的时间坐标取当前K线的开盘时间(time)再加上86400000。TradingView的时间值以毫秒为单位,所以要计算未来的时间坐标,就得在当前时间上加一定量的毫秒数——8640万毫秒正好是一天(24小时)。终点的价格坐标设置为当前收盘价(close)乘以0.99,也就是低1%的价格。
第三件事,我们把line.new()的xloc参数设置为xloc.bar_time,告诉TradingView这条线要用时间值作为X轴坐标,而不是默认的K线编号。
这条画到未来的趋势线效果如下:

用可选参数配置线条外观
前面的示例只用了line.new()的必需参数。上表里的那些可选参数,能进一步配置线条的外观。看个快速的例子:
//@version=5
indicator(title="快速示例:line.new()", overlay=true)
// 在图表的最后一根K线上创建一条经过格式化的趋势线
if barstate.islast
line.new(x1=bar_index[20], y1=high[20],
x2=bar_index, y2=low, color=color.lime,
width=10, style=line.style_dashed,
extend=extend.both)
这个指标同样只在最后一根价格K线上创建趋势线,但这次给line.new()传入了更多参数。
前四个参数指定线条的位置:起点设在20根K线前的K线编号和高点(bar_index[20]、high[20]),终点落在当前K线的低点(bar_index、low)。
其余参数负责外观。color设为color.lime,线条呈青柠绿色;width把线条宽度加大到10像素;style把线条样式设为虚线(line.style_dashed);最后extend=extend.both让这条趋势线向两个方向无限延伸。
这条经过格式化的线条在图表上的效果如下:

如何修改已创建的趋势线
通常,用line.new()画出趋势线只是第一步。线条创建之后,脚本经常还需要移动、更改或删除它。要修改一条已存在的趋势线,需要满足两个条件:一是把line.new()返回的线条引用存进变量,二是把这个变量传给TradingView的各种line.*函数来做修改。
line.new()在图表上画出趋势线后,会返回一个所谓的线条引用。这个值非常重要,因为它是代码与图表上那条趋势线之间唯一的连接。我们想对那条线做任何操作,都得提供这个引用,否则TradingView不知道我们要改的是哪一条线。
看一个实际的例子:
// 绘制一条新的趋势线
myLine = line.new(x1=bar_index[10], y1=high[10],
x2=bar_index, y2=high)
// 将线条的颜色更改为红色
line.set_color(id=myLine, color=color.red)
这段代码在10根K线前的高点和当前K线的高点之间画了一条趋势线,和我们之前创建的类似。但这次,我们把line.new()的返回值存进了myLine变量,之后就可以通过这个变量访问这条线。
line.set_color()的调用就是一个例子。这个函数可以更改趋势线的颜色,但它需要知道改哪一条线。这里我们通过myLine变量提供了这个信息,把刚创建的线设置成了红色(color.red)。
虽然并不强制要求把line.new()返回的引用存进变量,但实战里95%的情况你都应该这么做。因为线条引用没有任何其他获取方式——如果创建时不存下来,之后就再也无法更改、移动或删除这条趋势线了。这是新手很容易踩的坑。
修改趋势线的专用函数
line.new()创建的趋势线无法手动修改,只能通过专门的函数来调整。这些函数的共同点是都需要一个线条引用,没有它们就不知道要改哪条线。
要更改线条的视觉外观,代码可以使用:
- line.set_color():更改趋势线的颜色。
- line.set_width():设置趋势线的尺寸(粗细)。
- line.set_style():定义线条样式(如点线、虚线或实线)。
- line.set_extend():在一个或两个方向上延伸趋势线。
要移动一条趋势线,我们用以下函数更新它的坐标:
- line.set_xy1()和line.set_xy2():分别设置线条起点和终点的价格与时间坐标。
- line.set_x1()和line.set_x2():设置线条起点和终点的时间坐标。
- line.set_y1()和line.set_y2():设置线条起点和终点的价格坐标。
要获取一条线的坐标,我们使用:
- line.get_x1()和line.get_x2():返回线条起点和终点的K线编号(或时间)坐标。
- line.get_y1()和line.get_y2():返回线条起点和终点的价格坐标。
要从图表上移除一条线,则使用line.delete()。
你可能会问:既然有这么多函数能改线条外观,创建时用line.new()的参数也能设置样式,那两者有什么区别?总的来说,如果想一次性设定好线条外观,直接在line.new()里写参数更省事;但如果想根据某个条件来改线条样式,就必须用专门的函数。
举个例子,如果一条趋势线应该始终是红色的,那把line.new()的color参数设为color.red最方便,比单独写一条line.set_color()语句代码更少。但如果这条线只在K线价格跌破移动平均线时才变红,我们就需要把if语句和line.set_color()结合起来,实现有条件地改色。
示例指标:绘制高低点连线
现在来看line.new()在完整脚本中的用法。下面的指标会创建两条趋势线:一条标出20周期内的最高高点,另一条标出同期的最低低点。线条创建之后,每当出现新的20周期最高高点或最低低点,我们就更新它们的位置。
这是该指标的完整代码:
//@version=5
indicator(title="基本趋势线示例", overlay=true)
// 只创建一次两条趋势线
var highLine = line.new(x1=bar_index[10], y1=close[10],
x2=bar_index, y2=close, color=color.green,
extend=extend.both)
var lowLine = line.new(x1=bar_index[10], y1=close[10],
x2=bar_index, y2=close, color=color.red,
extend=extend.both)
// 寻找新的20周期高点和低点
newHigh = high == ta.highest(high, 20)
newLow = low == ta.lowest(low, 20)
// 当出现新的高点或低点时更新线条
if newHigh
line.set_xy1(highLine, x=bar_index[10], y=high)
line.set_xy2(highLine, x=bar_index, y=high)
if newLow
line.set_xy1(lowLine, x=bar_index[10], y=low)
line.set_xy2(lowLine, x=bar_index, y=low)
我们一段段来看。首先用indicator()函数定义指标的设置,然后创建两条趋势线:
// 只创建一次两条趋势线
var highLine = line.new(x1=bar_index[10], y1=close[10],
x2=bar_index, y2=close, color=color.green,
extend=extend.both)
var lowLine = line.new(x1=bar_index[10], y1=close[10],
x2=bar_index, y2=close, color=color.red,
extend=extend.both)
这里执行了两次line.new()。第一条线从10根K线前的收盘价(bar_index[10]、close[10])开始,到当前K线编号和当前收盘价(bar_index、close)结束,以绿色(color.green)显示并向两个方向延伸(extend.both)。我们把返回的线条引用存进highLine变量,方便后续访问和修改。
第二个line.new()调用创建了另一条趋势线,坐标和前一条完全相同。这些坐标只是临时占位,后面的代码会把两条线移动到实际位置。第二条线以红色(color.red)显示,同样向两个方向延伸,引用存入lowLine变量。
注意两条线前面都用了var关键字。带var的语句只执行一次,所以这两个line.new()调用总共只会创建两条趋势线,而不是在每根K线上都画两条新线。这是防止图表被大量趋势线弄乱的常用手法。
接下来,我们检查是否出现了新的20周期高点和低点:
// 寻找新的20周期高点和低点
newHigh = high == ta.highest(high, 20)
newLow = low == ta.lowest(low, 20)
这里比较当前K线的高点(high)是否等于(==)ta.highest()得到的20周期最高高点。如果是,newHigh变量就为true(否则为false)。
类似地,接着判断K线的低点(low)是否等于(==)ta.lowest()返回的20周期最低低点,是则newLow变量为true(否则为false)。
知道是否出现新的20周期极值只是第一步,接下来要把趋势线更新到这些位置上:
// 当出现新的高点或低点时更新线条
if newHigh
line.set_xy1(highLine, x=bar_index[10], y=high)
line.set_xy2(highLine, x=bar_index, y=high)
if newLow
line.set_xy1(lowLine, x=bar_index[10], y=low)
line.set_xy2(lowLine, x=bar_index, y=low)
第一个if语句判断是否出现了新的20周期高点。如果newHigh为true,我们就把最高高点线更新到当前的高点:先调用line.set_xy1()更新线条起点,新坐标是10根K线前的K线编号(bar_index[10])和当前K线的高点(high),用highLine变量指明要改哪条线;再执行line.set_xy2()把线条终点更新到当前K线的高点(bar_index、high)。
第二个if语句评估newLow变量。当它为true时,说明当前K线触及了新的20周期低点,于是我们把最低低点线(lowLine)移过去:line.set_xy1()把起点更新到10根K线前的K线编号和当前低点(low),line.set_xy2()把终点更新到当前K线编号和低点。
还记得吗,我们之前把两条趋势线都向左右延伸了,所以它们能横跨整个图表。即使线条的位置只更新到当前K线和10根K线前之间,实际覆盖的范围远不止于此。
这些趋势线在图表上的效果如下:

在这个美元/加元图表上,近期所有的价格行为都被夹在最高高点线和最低低点线之间。当然,这也有运气成分,实战里趋势线并不总是像这里看起来这么完美。
line.new()函数的特性
line.new()有几个值得记住的特性:
- 趋势线可以画在主图表的交易品种上,也可以画在脚本所在的副图面板内,取决于indicator()和strategy()函数的overlay参数。
- 默认情况下,趋势线用K线编号作为时间坐标。改用时间值后,就可以把线画到未来。要让一条线使用时间值,可以把line.new()的xloc参数设为xloc.bar_time,或者用line.set_xloc()函数把已存在的线切换为时间值模式。
- 用line.new()创建的线不能手动修改,必须通过代码操作。
- 单个脚本实例大约能在图表上保留50到55个绘图。代码试图创建更多时,TradingView会自动移除最旧的绘图。
- 趋势线并非总能持久保留在图表上。在K线内部计算过程中创建的线条,会在下一次脚本计算时被自动移除,这样可以避免每次实时价格更新都新画一条线,很快弄乱图表。
- 每个line.new()调用在每根K线上最多创建一条趋势线。想在一根K线上画多条线,代码就得多次调用line.new()。
- line.new()创建的趋势线只在其脚本处于活动状态时保留。禁用或移除脚本后,这些线条也会消失。
- 虽然可以用request.security()从其他交易品种加载数据,但我们不能在该函数返回的数据序列上绘制趋势线。
- 一个脚本创建的线只能由该指标或策略自己修改,其他脚本无法更改、移动或删除它们。
- 代码无法获取图表上手动绘制的趋势线。获取代码创建的趋势线的唯一方式,就是把line.new()返回的引用存进变量。
总结
TradingView的指标和策略用line.new()函数绘制趋势线。它有四个必需参数:x1和y1定义线条的起点坐标,x2和y2指定终点坐标,其余可选参数用于设置线条的视觉外观。
line.new()创建趋势线后会返回一个线条引用。这个值非常重要,因为line.new()画出的线无法手动修改,更改、移动或删除趋势线的唯一方式是使用专门的line.*函数,而这些函数都需要线条引用才知道改哪条线。
line.new()在每根K线上可以创建一条趋势线,想在一根K线上画多条线就要多次调用它。一个脚本能创建的绘图总数也有上限,大约是50个。


