如何向Pine Script数组的末尾添加元素
创建数组后,可以用array.push()函数向数组的末尾追加一个新元素。每次脚本执行这个函数,Pine Script都会为数组增加一个元素。
该函数的标准语法是:
array.push(id, value)
id是你想操作的数组的引用,通常由创建数组的函数(如array.new_*()系列)返回,有了它才能告知Pine Script具体要修改哪个数组。value是要添加到数组末尾的新元素,可以是bool、color、float、int或string等基本类型,也可以是box、label、line、table等特殊对象。
要注意的是,添加的元素类型必须与数组本身的类型完全匹配。例如有一个颜色数组,就只能向其中添加颜色,而不能是数字或标签。
快速示例
要让array.push()正常工作,它需要知道两件事:要修改哪个数组,以及要添加什么值。假设我们之前创建了一个浮点数数组,引用存储在myArray变量中,可以像下面这样用array.push()添加新值:
// 将 1.1、2.2 和 3.3(按此顺序)添加到
// ID 存储于 'myArray' 变量的数组中
array.push(id=myArray, value=1.1)
array.push(id=myArray, value=2.2)
array.push(id=myArray, value=3.3)
id=和value=这类关键字参数是可选的,省略它们可以减少代码量,效果完全一样:
// 将 1.1、2.2 和 3.3 添加到 'myArray' 数组
array.push(myArray, 1.1)
array.push(myArray, 2.2)
array.push(myArray, 3.3)
array.push()分步详解
那么array.push()函数究竟是如何工作的?我们一步步来看。在向数组添加元素之前,首先需要一个数组:
// 创建一个包含3个初始值为0的整数数组
myArray = array.new_int(size=3, initial_value=0)
这行代码创建了一个整数数组,初始包含3个元素,每个元素的值都是0。返回的数组引用存储在myArray变量中,以便后续使用。此时数组的内容是:
[0, 0, 0]
现在,向数组末尾添加一个新元素:
// 向数组添加一个新值
array.push(id=myArray, value=1)
这里调用array.push(),通过myArray指定目标数组,把值1添加到尾部。执行后数组变为:
[0, 0, 0, 1]
再重复一次,添加另一个元素:
// 向数组末尾添加另一个值
array.push(id=myArray, value=2)
由于array.push()总是添加到末尾,所以2会出现在1的后面:
[0, 0, 0, 1, 2]
最后再添加一个3:
// 向数组追加最后一个元素
array.push(id=myArray, value=3)
数组的最终内容是:
[0, 0, 0, 1, 2, 3]
array.push()的应用场景
array.push()函数有几个常见的用途。最基本的是向数组末尾添加新元素,方便直接。它还可以用来实现队列(先进先出,FIFO):用array.push()在末尾添加新元素,用array.shift()从头部移除旧元素。也可以创建堆栈(后进先出,LIFO):用array.push()在末尾添加新元素,用array.pop()同样从末尾移除元素。
示例脚本
来看一个完整的脚本,了解array.push()的实际应用。下面的指标会把K线的收盘价收集到一个数组中,最新的价格添加到数组末尾。数组的大小由用户输入控制:一旦数组超过设定的最大容量,就从数组的开头移除最旧的元素,从而只保留最新的价格数据。脚本代码如下:
//@version=5
indicator(title="array.push() 基础示例", overlay=true)
// 通过输入选项定义数组的最大容量
maxArraySize = input.int(defval=5, title="最大数组容量")
// 创建一个用于存储浮点数的持久性数组
var closePrices = array.new_float()
// 将每根K线的收盘价添加到数组末尾
array.push(id=closePrices, value=close)
// 如果数组大小超过上限,则从头部移除最旧的元素
if array.size(id=closePrices) > maxArraySize
array.shift(id=closePrices)
// 在图表上显示数组内容以供验证
if barstate.islastconfirmedhistory
label.new(x=bar_index, y=high, color=color.black,
textcolor=color.white, size=size.large,
text="最近 " + str.tostring(maxArraySize) +
" 个收盘价:\n" + str.tostring(closePrices))
逐段解析一下这段代码。脚本先用indicator()进行配置,并用input.int()创建一个名为最大数组容量的输入选项,默认值为5。然后用array.new_float()创建一个浮点数数组,var关键字确保该数组在K线之间是持久的,不会被重置。
在每根K线上,脚本都调用array.push()把当前的收盘价close添加到closePrices数组的末尾。为了防止数组无限增长,用if语句检查其大小:如果array.size()超过了maxArraySize,就调用array.shift()从数组开头移除一个元素(即最旧的那个)。这样就形成了一个滚动的数组,始终只保留最新的一部分数据。
最后,在图表的最后一根历史K线上(通过barstate.islastconfirmedhistory判断)创建一个标签,显示数组的当前内容。
把这个指标添加到图表,默认容量为5时,它会显示最近的5个收盘价:

如果把输入选项的值改为2,标签内容也会相应更新:

array.push()的特性
每次执行array.push(),Pine Script都会自动把数组的大小增加1,无需手动管理数组的容量。不过要注意数组的最大容量限制为100,000个元素,如果在一个已满的数组上再次调用array.push(),TradingView会抛出array is too long(数组过长)的错误。
总结
array.push()函数用于向一个已存在数组的末尾添加新元素,添加的元素类型必须与数组的类型匹配。Pine Script会自动管理数组大小,上限为100,000个元素。
用Pine Script内置函数获取数组统计数据
当我们创建了一个数组并向其中添加元素后,通常下一步就是对数组内的数据进行分析。一种高效的方法是使用Pine Script内置的数组统计函数。
这些函数能够对数组中的所有数值进行运算,并返回一个特定的统计结果。它们运行效率高,代码简洁,是获取数组平均值、标准差、中位数等关键指标的好工具。
Pine Script提供了这样一批数组统计函数:array.avg()返回数组中所有数值的平均值;array.covariance()返回两个数组之间的协方差;array.max()和array.min()分别返回数组中的最大值和最小值;array.median()返回数组的中位数;array.mode()返回数组中出现次数最多的众数;array.range()返回数组中最大值与最小值之差(即极差);array.standardize()基于原数组返回一个所有元素都经过标准化处理的新数组;array.stdev()返回数组中所有数值的标准差;array.sum()返回数组中所有数值的总和;array.variance()返回数组中所有数值的统计方差。
接下来,我们逐一了解这些函数。
计算数组平均值:array.avg()
array.avg()函数返回一个数组中所有数值的算术平均值。使用时只需告诉函数要计算哪个数组,例如:
// 获取数组的平均值
dataAverage = array.avg(id=myArray)
假设myArray数组包含以下值:
[43, -18, 230]
对于这些元素,array.avg()将返回85。
计算数组协方差:array.covariance()
array.covariance()函数计算两个数组之间的协方差,需要向函数提供两个目标数组。例如:
// 获取两个数组的协方差
dataCovariance = array.covariance(id1=myArray1, id2=myArray2)
假设myArray1和myArray2数组的元素如下:
[1.09, 2.38, -3.75]
[-2.282, 0.8032, 3.2]
对于这些数值,array.covariance()将返回0.772968。
获取数组最大值:array.max()
array.max()函数返回数组中的最大值,使用时只需指定要分析的数组。例如:
// 获取数组的最大值
dataMax = array.max(id=myArray)
如果myArray数组包含以下值:
[27, -10, 84]
那么array.max()将返回84。
获取数组中位数:array.median()
array.median()函数返回一个数组的中位数(即排序后位于中间的数值)。例如:
// 获取数组的中位数
dataMedian = array.median(id=myArray)
假设myArray数组包含以下数字:
[2, 2, 5, 7, 9]
对于这些元素,array.median()将返回5。
获取数组最小值:array.min()
array.min()函数用于获取数组中的最小值。例如:
// 获取数组的最小值
dataMin = array.min(id=myArray)
当myArray数组包含以下元素时:
[3.25, 0.02, 9.47, -4.6]
那么array.min()将返回-4.6。
获取数组众数:array.mode()
array.mode()函数返回数组的众数,即数组中出现频率最高的那个数。例如:
// 获取数组的众数
dataMode = array.mode(id=myArray)
假设myArray数组的内容是:
[-7, 12, 4, 4, 32]
对于这些元素,array.mode()将返回4。
计算数组极差:array.range()
array.range()函数返回数组中最大值与最小值之差。例如:
// 获取数组的极差
dataRange = array.range(id=myArray)
假设myArray数组持有以下值:
[1, 26, 17]
对于这些整数,array.range()将返回25。
标准化数组:array.standardize()
array.standardize()函数接收一个原始数组,并返回一个其中所有元素都经过标准化处理的新数组。例如:
// 标准化原始数组
dataStandardized = array.standardize(id=myArray)
假设myArray数组包含以下4个整数:
[5, 5, 2, 11]
在对其进行标准化后,array.standardize()会返回一个如下的新数组:
[-0.2294157339, -0.2294157339, -1.1470786694, 1.6059101371]
计算数组标准差:array.stdev()
array.stdev()函数返回一个数组中所有数值的标准差。例如:
// 获取数组的标准差
dataStDev = array.stdev(id=myArray)
当myArray数组包含以下元素时:
[1.149, 0.238, -2.075]
那么array.stdev()将返回1.3570419628。
计算数组总和:array.sum()
array.sum()函数返回一个数组中所有元素的总和。例如:
// 获取数组的总和
dataSum = array.sum(id=myArray)
假设myArray数组包含以下元素:
[206, -32, 83]
对于这些数字,array.sum()将返回257。
计算数组方差:array.variance()
array.variance()函数返回一个数组中所有元素的统计方差。例如:
// 获取数组的方差
dataVariance = array.variance(id=myArray)
假设myArray数组包含以下三个元素:
[5.3, 2.12, -3.95]
对于这些值,array.variance()将返回14.7244222222。
数组统计函数的共同特性
尽管以上每个函数计算的统计量各不相同,但作为一个函数族,它们共同拥有三个重要特性。
第一,它们与常规数学函数不同。数组统计函数是Pine Script中唯一能直接对数组进行分析的内置函数,因为Pine Script的常规数学函数(如math.min()和math.max())无法直接作用于数组对象。要获取数组的最小值和最大值,不能用math.min()和math.max(),必须用它们在数组函数库中的对应版本array.min()和array.max()。
其根本原因在于数据结构的不同。Pine Script中的常规变量(如close)是一个时间序列,在历史上的每根K线上都有一个对应的值。但数组的工作方式与此不同:在历史K线上,一个数组可能包含完全不同的元素,甚至可能还不存在。因此,对一个历史状态不定的数组计算10周期平均值是没有意义的。数组统计函数的设计正是为了解决这个问题:它们只对数组在当前时刻所包含的元素进行计算,而不考虑其历史状态。
由于数组无法使用常规数学函数,如果我们想进行的某种计算没有现成的数组函数支持(例如对数组所有元素进行四舍五入,并没有array.round()函数),就必须自己编写循环来遍历数组,逐个元素地实现计算逻辑。
第二,它们作用于整个数组。数组统计函数总是对数组中的所有元素进行计算,无法只对部分元素计算而排除其他元素。如果想对数组的某个子集(样本)进行统计,必须先对数组进行处理,方法有两种:一是用array.slice()函数从原数组中提取一个连续的片段来创建新的子集数组;二是通过循环遍历数组,用array.remove()函数把不需要的元素删除。得到一个只包含目标元素的数组后,就可以在其上调用数组统计函数了。
第三,它们会自动忽略na值。当数组中同时包含数字和na值时,数组统计函数会自动忽略na值,仅对有效的数值进行计算,所以分析数组时通常无需担心na值干扰结果。这一点与Pine Script的常规数学函数截然不同——后者一旦在计算中遇到任何一个na值,最终结果就会返回na。
当然,这并不意味着数组统计函数永远不会返回na。当一个数组中的所有元素都是na时,它们也会返回na。这个规则有一个例外:array.standardize()在处理一个只包含na值的数组时,会为每个na元素返回1。


