在交易世界里,我们做的任何分析,无论是看均线、判断趋势,还是寻找突破,都离不开一个核心动作:回测历史。PineScript之所以强大,很大程度上要归功于它提供了一个极其方便的回测时光机:历史引用运算符[]
。
掌握了它,你就掌握了穿越K线、获取任意历史数据的能力。
历史引用运算符 []
的基本用法
这个[]
怎么用?非常简单,在任何会随K线变化的变量或函数后面,跟上一对方括号,在里面填上一个数字N
,就能拿到N
根K线“之前”的数据。
比如,close[1]
就是上一根K线的收盘价,high[5]
就是5根K线前的最高价。
这里的关键在于“之前”这两个字。PineScript在图表上是从左到右,一根K线一根K线地进行计算的。所以,[]
所引用的“历史”,永远是相对于“当前正在计算的这根K线”而言的。这个相对关系,是理解所有历史数据引用的基石。
历史引用运算符的安全守则(避坑指南)
用好这个“时光机”,你还需要知道它的几个“安全守则”,不然很容易出问题:
- 禁止套娃:
[]
不能连续用,像open[1][2]
这种写法是错的。想拿3根K线前的数据,就直接写open[3]
,简单明了。 - 只能往回看:
[]
里面只能是0或者正整数,代表向历史回溯。不能用负数,我们只能回溯历史,不能“预测未来”。 - 只对变化的数据有效:
[]
只能用在那些会随着K线变化的值上,我们称之为“序列”数据,比如close
、volume
或者指标计算结果。你不能对一个写死的、永远不变的文本用它,比如"我的信号"[1]
, 这在逻辑上是讲不通的。 - 越界会返回“无效值”:当图表刚开始,历史K线数量不足时,如果你试图获取一个不存在的数据(比如在第5根K线上获取
close[10]
),程序不会报错,而是会返回一个特殊值NaN
(Not a Number,非数字)。了解这一点,在你写一些需要预热期的指标时非常重要。 - 时间单位的误解:
[]
的单位永远是“K线数量”,而不是“时间”。比如,在日线图上,month[1]
返回的不是“上一个月”,而是“上一根K线(也就是昨天)所在的月份”。这点新手很容易搞错。
一个更深入的理解:[]
返回的是什么?
这里我们聊一个更深入的概念,能帮你理解为什么[]
这么强大。当你写close[5]
时,你可能觉得你只是拿到了“5根K线前那一个收盘价”。但实际上,PineScript返回给你的是一整条全新的价格曲线,这条曲线上每个点的值,都等于原始收盘价曲线向右平移5根K线后的结果。
下面这个简单的脚本和它画出的图,能让你瞬间明白:
//@version=6
indicator(title="历史引用运算符", overlay=true)
// 向右偏移了5根K线
plot(close[5], linewidth=2)
添加到图表后的效果如下:
正因为close[5]
本身就是一条完整的“价格序列”,我们才能对它进行二次计算,比如ta.ema(close[5], 20)
,去计算这条“延迟了5根K线的收盘价曲线”的均线。如果它只是一个孤零零的数值,是没法算均线的。这就是[]
设计的精妙之处。
现在,我们来看两个实战案例。
案例一:获取变量的历史值(计算动量)
下面的例子通过计算当前K线中点价和10根K线前的差值,来构建一个简单的动量指标。
//@version=6
indicator(title="历史引用 - 案例1", overlay=false)
// 1. 计算价格动量
// hl2是内置变量,代表(high + low) / 2,即K线中点价
priceDiff = hl2 - hl2[10]
// 2. 判断动量是否在增强
// 如果当前的动量值 > 上一根K线的动量值 (priceDiff[1]),说明动量在加速
colour = priceDiff > priceDiff[1] ? color.orange : color.blue
// 3. 将动量值以柱状图的形式画出来,并用颜色标记动量的变化
plot(priceDiff, color=colour, style=plot.style_histogram,
linewidth=3)
将此指标添加到图表后,效果如下:
案例二:在函数中使用(构建价格通道)
下面这个例子非常非常实用,它解决了我们在写真实策略时的一个常见痛点:如何创建一个“不包含当前K线”的价格通道(比如唐奇安通道或布林带上轨)。
如果你直接用ta.highest(high, 20)
来做通道上轨,你会发现当前价格永远无法“上穿”这个通道,因为当前K线的最高价high
本身就参与了通道的计算。为了让“突破”这个动作能够被检测到,我们必须让通道的计算完全基于“过去”的数据。[]
就完美解决了这个问题:
//@version=6
indicator(title="历史引用 - 案例2", overlay=true)
// 方法一:先计算,再引用历史值。
highestHigh = ta.highest(high, 20)[1]
// 方法二:先引用历史值,再计算。
// low[1]得到的是一个“向右平移了一格”的最低价序列
// 然后基于这个“延迟的”序列来计算20周期最低价
lowestLow = ta.lowest(low[1], 20)
plot(highestHigh, color=color.green)
plot(lowestLow, color=color.red)
当我们将此指标添加到图表时,可以清晰地看到历史引用运算符是如何让通道的上下轨都延迟了一根K线,从而使其能有效地应用于突破策略中:
总结
- 历史引用运算符
[]
是PineScript的灵魂,是获取任意历史数据的“时光机”。 - 它的“历史”永远是相对于当前计算的K线而言的,单位是“K线根数”。
- 用
[1]
来排除当前K线数据,是构建通道、均线等各类指标,使其能被价格“穿越”的关键技巧。 - 当图表历史数据不足时,它会返回
NaN
(无效值),而不是报错。
掌握了[]
,才算真正踏入了策略编程的大门。