自定义数据集合:数组
用大小受限的数组保存近期价格,并跟踪元素顺序。
Series 保存与 K 线对应的历史。有时,你希望自己决定收集哪些值、采用什么顺序,以及何时删除。这时可以使用数组。
数组存储什么?
数组由依次排列的元素组成,每个元素都有索引,第一个索引为零。
数组存储相同类型的元素。例如,可以有数字数组或文本数组,但不往数字数组放文本。同类型并非同值:100、103、101 是同一个数组里的不同数字。
如果依次放入 100、103、101,那么索引 0 为 100,索引 1 为 103,索引 2 为 101。这里的索引表示存储位置,不自动表示多少根 K 线以前。
close[1] 是上一根收盘价。array.get(prices, 1) 是 prices 数组的第二个元素。元素有多旧,取决于你怎样填充数组。
array 命名空间
array.new_float(0) 创建初始为空的数字数组。零是初始元素数量,不是初始价格。
| 操作 | 用途 |
|---|---|
array.push(prices, close) | 在数组末尾添加元素 |
array.size(prices) | 返回元素数量 |
array.shift(prices) | 移除并返回第一个元素 |
array.get(prices, 0) | 读取第一个元素 |
array.avg(prices) | 计算已存数字的平均值 |
array.get 索引必须指向存在的元素。三个元素时,0、1、2 有效,3 已经越界。
保存五个近期价格
创建 recent_prices.py:
"""
@pyne edge
"""
from pynecore import Persistent
from pynecore.lib import array, close, color, plot, script, ta
@script.indicator("Recent Prices", overlay=True)
def main():
prices: Persistent[list[float]] = array.new_float(0)
array.push(prices, close)
if array.size(prices) > 5:
array.shift(prices)
stored_average = array.avg(prices)
full_average = ta.sma(close, 5)
plot(stored_average, "Stored average", color=color.blue, linewidth=2)
plot(full_average, "SMA 5", color=color.orange)list[float] 表示存储数字的数组类型。Persistent 保证数组保留到下一根 K 线,不会每根重新创建。
数组操作通过 array 命名空间完成,不需要导入通用 Python 库,也不需要手写列表字面量。
如果你熟悉 Python: 在 PyneCore 的 Python 执行器中,数组底层使用 Python 列表保存,因此类型写作 list[float]。元素必须符合数组指定的类型;与通用 Python 列表不同,这里不混放数字和文本。
在标记为 @pyne、允许更多 Python 功能的程序中,也可以使用列表自身的操作:例如 prices.append(close) 添加元素,prices.pop(0) 删除第一个元素。本书的 @pyne edge 程序用 array.push 和 array.shift 完成这些操作。Edge 中也不用 prices[0] 直接读取,而使用 array.get(prices, 0);创建数组时使用例如 array.new_float(0),而不是 [] 列表字面量。
在演示数据上运行。蓝线绘制已经收集到的价格平均值。第一根只有一个价格,第二根两个,之后三个、四个。从第五根起保留五个。

添加与移除的顺序
第六根先加入第六个收盘价,此时数组有六个元素。if 条件为真,移除最早的第一个元素。计算平均值时,只剩第二到第六根的五个收盘价。
本程序的数组开头是最早保留的价格,末尾是最新价格。因此,满五个元素后,array.get(prices, 0) 返回四根以前的价格,不是当前价格。
要读取最新值,最后一个索引是 array.size(prices) - 1。由于索引从零开始,元素数量与最后索引相差一。
不完整与完整窗口
两条平均线开始时行为不同。数组可以对实际已收集、最多四个价格先求平均;ta.sma(close, 5) 只有完整五元素窗口才给值。
从第五根开始,两者平均的是相同五个收盘价,此后应在数值表示精度范围内一致。
所以,数组平均并不自动等价于内置移动平均。初始窗口规则需要自己定义。
为什么限制大小?
若每根只添加不移除,数组就会随数据长度增长。运行结束时会保存所有已处理收盘价。
这里只需要最近五个价格,因此删除较早元素,使计算时的大小最多为五。实际数据收集任务也应明确哪些数据要保留、保留多久。
自己试一试
让数组只保留三个价格,内置 SMA 也改为三期。随后把数组中最早保留的元素画成第三条线。
参考答案
移除条件:
if array.size(prices) > 3:
array.shift(prices)内置平均和新线:
full_average = ta.sma(close, 3)
oldest_price = array.get(prices, 0)
plot(oldest_price, "Oldest stored price", color=color.gray)每根 K 线都先调用 array.push 再读取,所以此时至少有一个元素。达到三个元素后,最早的价格来自两根以前。
写出数组内容
将保留元素数由五改成三,对 100、103、101、105 这组价格,写出每根 K 线之后的数组。第四根时应按顺序包含 103、101、105。