EsSeries数据结构

极智量化的扩展函数库里有一个核心类型:NumericSeries(定义在 EsSeries.py)。它是自定义技术指标的基础——任何需要「记住上一根 Bar 数值」的指标(EMA、SMA、SAR 等),都要靠它。本章讲清它和普通 list 的关键区别。

它是什么

NumericSeries 继承自 Python 的 list,所以你可以像用 list 一样取长度、切片、迭代。但它在两个地方做了特殊设计:

  1. 写入 -1 号元素时,会按当前 Bar 自动决定是「追加」还是「更新」
  2. 读取越界时自动钳位或返回 NaN,不会抛 IndexError

这两点正好解决了在 handle_data 里逐 Bar 计算有状态指标的痛点。

用法:创建并逐 Bar 赋值

from EsSeries import NumericSeries

ema = NumericSeries()       # 在策略全局区域创建

def handle_data(context):
    # 每根 Bar 把最新算出的值写入 -1 号位
    ema[-1] = ...           # 引擎自动按 CurrentBar() 追加或更新

关键机制在 __setitem__:它内部记录了上次写入时的 _curBarIndex,并与当前的 CurrentBar() 比较——

  • _curBarIndex + 1 == CurrentBar()(进入了新 Bar):追加一个新元素到末尾。
  • _curBarIndex == CurrentBar()(同一根 Bar 内多次写):更新最后一个元素。
  • 这样你只需要每根 Bar 写一句 ema[-1] = value,序列就自动「一根 Bar 一个值」地生长。

读取:越界保护

__getitem__ 对越界做了容错,这对回测初期数据不足时非常实用:

情况行为
序列为空,取任意下标返回 np.nan
下标为负且小于 -len返回最早可用值(下标 -len),并打印提示
下标为正且超过 len-1返回最后一个值,并打印提示
切片按 list 原生切片返回

这意味着 ema[-2] 在序列只有 1 个元素时不会崩溃,而是返回首个值,便于你在策略里少写一堆边界判断。

加法运算

__add__ 已实现:两个等长 NumericSeries 逐元素相加,返回一个新的同类型对象;长度不等时打印提示并返回自身。其他算术运算符(减、乘、除等)在类里已占位但未实现,需要时自行扩展。

一个完整示例:自建 EMA

下面的写法正是平台内置 EsTalib.U_EMA 的工作方式——用 NumericSeries 保存历史值,逐 Bar 递推:

import talib
from EsSeries import NumericSeries

ema_x = NumericSeries()
period = 10

def initialize(context):
    SetBarInterval('ZCE|Z|SR|MAIN', 'M', 1, 500)
    SetTriggerType(5)
    SetOrderWay(2)

def handle_data(context):
    if len(Close()) == 0:
        return
    factor = 2 / (period + 1)
    if len(ema_x) == 0:
        ema_x[-1] = Close()[-1]                       # 首值取收盘价
    else:
        ema_x[-1] = ema_x[-1] + factor * (Close()[-1] - ema_x[-1])  # 递推
    PlotNumeric('ema', ema_x[-1], RGB_Red())

注意第二句 ema_x[-1] = ema_x[-1] + ...:右侧读的是「上一根 Bar 的值」,左侧写入时引擎检测到 Bar 已推进,于是追加新元素——这就是有状态指标的闭环。

与 talib 的取舍

方式优点缺点
talib.MA(Close(), N)一行算完,无状态、开箱即用需要传入完整数组,每次重算
NumericSeries 自建可表达任意有状态逻辑,增量计算高效要自己写递推公式

简单指标用 talib;当指标逻辑复杂、需要保存中间状态、或 talib 没有对应实现时,就用 NumericSeries 自建——这正是下一章 EsTalib技术指标库 里那些 U_ 函数的由来。

小结

NumericSeries 是会「按 Bar 长大」的受保护 list:写 -1 自动追加/更新,读越界自动钳位或返回 NaN。它是极智量化自定义指标的基石。接下来看平台用它封装了哪些现成的指标函数,见 EsTalib技术指标库