DolphinDB基础函数解析:时间序列聚合引擎createTimeSeriesAggregator()

  • 时间序列聚合引擎

    关于聚合引擎,参见《DolphinDB基础概念理解:流数据聚合引擎

  • createTimeSeriesAggregator()

    createTimeSeriesAggregator(name, windowSize, step, metrics, dummyTable, outputTable, timeColumn, [useSystemTime=false], [keyColumn], [garbageSize])
    
    参数意义备注
    name表示时间序列聚合引擎的名称,是时间序列聚合引擎的唯一标识可以包含字母、数字、下划线,但必须以字母开头
    windowSize表示数据窗口的长度,是一个正整数windowSize必须是step的整数倍,否则会抛出异常;
    对流数据进行聚合计算,每次要截取一段静态数据集用于计算,这个截取出来的静态数据集我们也称为数据窗口
    step表示计算的时间间隔,是一个正整数windowSize和step的精度取决于useSystemTime参数
    metrics是元代码,详情可参考元编程可以是系统内置或用户自定义的聚合函数(使用defg关键字定义),如<[sum(qty), avg(price)]>;
    可以对聚合结果使用表达式,如<[avg(price1)-avg(price2)]>;
    也可以对计算列进行聚合运算,如<[std(price1-price2)]>
    dummyTable表对象提供一个样本表对象,它可以不包含数据,但它的结构必须与订阅的流数据表结构相同;
    系统利用dummyTable的schema来决定信息每一列的数据类型
    outputTable表对象,用于保存计算结果。它的第一列必须是时间类型,用于存放发生计算的时间戳(此处是发布表时间序列中的时间,并非本地系统时间),并且该列的数据类型要与dummyTable的时间列一致;
    如果keyColumn参数不为空,那么outputTable的第二列为keyColumn;
    如果keyColumn参数为空,那么从第二列开始,每列用于保存聚合结果。
    timeColumn表示输入流数据表的时间列名称,是字符串标量
    [useSystemTime]表示聚合引擎的驱动方式useSystemTime = true:表示时间驱动方式,windowSize和step的单位是毫秒。每当到达一个预定的时间点,聚合引擎就会激活并以设定的窗口截取流数据进行计算。在此模式下,系统内部会给每一个进入的数据添加一个毫秒精度的系统时间戳作为数据窗口截取的依据;
    useSystemTime = false(默认):表示数据驱动方式,windowSize和step的单位与timeColumn的时间精度一样。只有当数据进入系统时,聚合引擎才会被激活,此时窗口的截取依据是timeColumn列内容,时间的精度也取决于timeColumn列的时间精度。
    [keyColumn]表示分组列,是字符串标量聚合引擎会按照keyColumn对输入数据分组,并在每组中进行聚合计算;
    指定分组计算的组别,以对流数据分组进行聚合计算。比如以股市报价数据中的每支股票为一组进行聚合计算
    [garbageSize]正整数默认值是50,000;
    如果没有指定keyColumn,当内存中历史数据的数量超过garbageSize时,系统会清理本次计算不需要的历史数据;
    如果指定了keyColumn,意味着需要分组计算时,内存清理是各分组独立进行的。当一个组的历史数据记录数超出garbageSize时,会清理该组不再需要的历史数据。若一个组的历史数据记录数未超出garbageSize,则该组数据不会被清理。
  • 规整尺度alignmentSize

    为了便于观察和对比计算结果,系统会对第一个数据窗口的起始时间进行规整。系统会根据step参数和数据的时间精度来确定整数类型的规整尺度alignmentSize

    假设第一条数据的时间的最小精度(ss, mmm)为X,那么第一个数据窗口的左边界的最小精度为
    X / a l i g n m e n t S i z e ∗ a l i g n m e n t S i z e X/alignmentSize*alignmentSize X/alignmentSizealignmentSize
    其中, / / /表示整除。

    例如,第一条数据的时间为2018.10.08T01:01:01.365step=100,那么X=365,第一个数据窗口的左边界的最小精度为 365 / 100 ∗ 100 = 300 365/100*100=300 365/100100=300,第一个数据窗口的起始时间为2018.10.08T01:01.300

    官方文档的这段描述有歧义,补充说明:

    第一个数据窗口的起始时间为2018.10.08T01:01.300。即第一个数据窗口WindowSize坐落在时间间隔[2018.10.08T01:01:01.300, 2018.10.08T01:01:01.400),依据step以此累加,得到每次进行计算的时间点,准确来讲此处是不存在时间区间的,在时间这一列上,有价值的是隐居step得到的一个个点。

    数据窗口一般不是针对时间列而言,只是通过时间节点给出了数据窗口的结束位置,再通过windowSize大小向前推,一直到alignmentSize给出了规整的起始时间。

  1. 数据精度为秒

    当数据的时间精度为秒时,如DATETIME(yyyy-MM-dd HH:mm:ss)SECOND(HH:mm:ss)类型,alignmentSize的取值如下:

    stepalignmentSize
    0~22
    3~55
    6~1010
    11~1515
    16~2020
    21~3030
    31~6060
  2. 数据精度为毫秒

    当数据的时间精度为毫秒时,如TIMESTAMP(yyyy-MM-dd HH:mm:ss.mmm)TIME(HH:mm:ss.mmm)类型,alignmentSize的取值如下:

    stepalignmentSize
    0~22
    3~55
    6~1010
    11~2020
    21~2525
    26~5050
    51~100100
    101~200200
    201~250250
    251~500500
    501~10001000
  • 函数作用

    返回一个表对象,向该表写入数据意味着这些数据进入时间序列聚合引擎进行计算。

    通常***createTimeSeriesAggregator***与subscribeTable函数一起使用。

    ***createTimeSeriesAggregator***返回的==时间序列聚合引擎(name)==可以跨会话调用。

  • 使用示例

  1. 函数及变量准备
    # 创建流数据表
    share streamTable(1000:0, `time`qty, [TIMESTAMP, INT]) as trades
    
    # 创建输出表
    outputTable = table(10000:0, `time`sumQty, [TIMESTAMP, INT])
    
    # 实例化聚合计算表
    tradesAggregator = createTimeSeriesAggregator("streamAggr1", 5, 5, <[sum(qty)]>, trades, outputTable, `time )
    
    # 订阅,从发布表trades订阅到聚合计算表tradesAggregator
    subscribeTable(, "trades", "tradesAggregator", 0, append!{tradesAggregator}, true)
    
    # 定义函数
    def writeData(n){
        timev = 2018.10.08T01:01:01.001 + timestamp(1..n)
        qtyv = take(1, n)
        insert into trades values(timev, qtyv)
    }
    
    
  2. 第一次操作:向发布表写入5行数据

    发布表,是一种流数据表,当向其写入数据,即意味着发布数据,因为需要被不同会话访问,因此需要将其共享。
    流 数 据 表 + 共 享 表 + 写 入 数 据 = 自 动 将 数 据 导 入 订 阅 表 , 实 现 发 布 功 能 流数据表 + 共享表 + 写入数据 = 自动将数据导入订阅表,实现发布功能 ++=

    # 向发布表trades中写入5条数据
    writeData(5)
    

    writeData(5)这个函数实现了三部分动作:

    • 插入n=5个数据对(timev, qtyv)到发布表;
    • 因为订阅的原理,向发布表trades写入数据,自动传入订阅表;
    • 因为聚合引擎的原理,向聚合计算表tradesAggregator(也即订阅表)写入数据意味着这些数据进入(时间序列)聚合引擎进行计算

    这三个动作的后两个,各自还包含了一个消费过程,即接受到数据的同时,还对数据做了实时处理。三个动作详解:

    • 插入n=5个数据对(timev, qtyv)到发布表;

      这个动作是单向一次完成

    • 因为订阅的原理,向发布表trades写入数据,自动传入订阅表;

      关于subscribeTable函数的详解,参见:

      DolphinDB使用案例16:Python实现流数据订阅

      DolphinDB基础概念理解:流数据处理框架

      subscribeTable(, "trades", "tradesAggregator", 0, append!{tradesAggregator}, true)
      # 解析
      subscribeTable(server为空表示本地节点, 
                     tableName="trades"表示发布表, 
                     actionName="tradesAggregator"表示对此订阅的描述标记, 
                     offset=0表示从发布表的第0行开始订阅,
                     handler=append!{tradesAggregator}表示处理(消费)订阅数据的是一个函数,原本两个参数的append!通过部分应用固定被追加数据的表对象,
                    msgAsTable=true表示订阅的数据是表)
      

      关于部分应用(append!{tradesAggregator})参见《DolphinDB基础概念理解:部分应用partial application》。

      此订阅环节中,有对数据进行处理(append!{tradesAggregator})的环节,这个环节就是把数据追加到tradesAggregator表中。

    • 因为聚合引擎的原理,向聚合计算表tradesAggregator(也即订阅表)写入数据意味着这些数据进入(时间序列)聚合引擎进行计算
      tradesAggregator = createTimeSeriesAggregator("streamAggr1", 5, 5, <[sum(qty)]>, trades, outputTable, `time )
      # 解析
      tradesAggregator = createTimeSeriesAggregator(name="streamAggr1"表示时间序列聚合引擎的名称,
                                                    windowSize=5表示数据窗口的长度,
                                                    step=5表示计算的时间间隔,
                                                    metrics=<[sum(qty)]>是表示聚合函数的元代码,
                                                    dummyTable=trades,
                                                    outputTable=outputTable用于保存计算结果, 
                                                    timeColumn=`time表示输入流数据表的时间列 )
      

    ​ 与上述订阅环节有些类似,当(通过订阅的方式)向tradesAggregator表写入数据,就意味着这些数据进入聚合引擎streamAggr1进行计算(sum(qty))。

    经过上述分析,向发布表trades中写入5条数据writeData(5)这个函数,在DolphinDB中真正的过程是:

    1. values()函数生成5对数据;
    2. insert 将5个数据对插入发布表trades
    3. 发布表trades接收到数据就启动了订阅功能,自动推送给handler=append!{tradesAggregator}进行数据消费,保存到tradesAggregator表
    4. 聚合引擎表tradesAggregator收到数据,就启动了时间序列聚合引擎,通过metrics=<[sum(qty)]>对数据进行聚合计算,并将计算后的结果保存到outputTable=outputTable表中。
  3. 查看第一次操作计算结果

    根据上述分析,此时发布表trades中应该有5条记录:

    >> select * from trades
    
    		time			qty
    2018.10.08T01:01:01.002	1
    2018.10.08T01:01:01.003	1
    2018.10.08T01:01:01.004	1
    2018.10.08T01:01:01.005	1
    2018.10.08T01:01:01.006	1
    

    outputTable表中应该有一次计算结果:

    >> select * from outputTable
    
    		time			sumQty
    2018.10.08T01:01:01.005	3
    

    trades中有5条记录,qty的和应该是5,但outputTablesumQty的结果却是3。

    这里就是时间序列聚合函数createTimeSeriesAggregator()通过step的值确定的整型的规整尺寸alignmentSize在起作用:

    此时trades表中time列的数据类型是TIMESTAMP,精度是毫秒alignmentSize的取值规则如下:

    stepalignmentSize
    0~22
    3~55
    6~1010
    11~2020
    21~2525
    26~5050
    51~100100
    101~200200
    201~250250
    251~500500
    501~10001000

    根据规则,此时step=5,则alignmentSize=5,计算第一个数据窗口的左边界最小精度:
    ( x a l i g n m e n t S i z e ) 取 整 ∗ a l i g n m e n t S i z e = ( 2 5 ) 取 整 ∗ 5 = 0 (\frac{x}{alignmentSize})_{取整}*alignmentSize=(\frac{2}{5})_{取整}*5=0 (alignmentSizex)alignmentSize=(52)5=0
    得到第一个计算窗口的左边界为2018.10.08T01:01:01.000,即第一个数据窗口为[2018.10.08T01:01:01.000, 2018.10.08T01:01:01.005),其中包含[2018.10.08T01:01:01.002, 2018.10.08T01:01:01.003, 2018.10.08T01:01:01.004],因此结果sumQty3.

    根据outputTable参数的定义,输出表的第一列必须是时间类型,用于存放计算发生的时间戳,这个列的数据类型要和流数据表中的时间列类型一致。

    • 如果keyColumn参数为空,那么从第二列开始,每列用于保存聚合结果。(当前情况)
    • 如果keyColumn参数不为空,那么输出表的第二列必须是分组列。从第三列开始,按照顺序保存聚合计算的结果。最终的表结构是时间列,分组列(可选),聚合结果列1,聚合结果列2… 这样的格式。

  4. 第二次操作:向发布表写入10行数据

    首先清空发布表trades;

    重新设置windowSize=6,step=3;

    最后模拟写入10条数据。

    writeData(10)写入完成后,select * from trades应该有10条记录,这些都未改变。由于alignmentSize机理的存在,sumQty的结果有所不同。

    根据alignmentSize规则,此时step=3,则alignmentSize=5,计算第一窗口的左边界最小精度:
    ( x a l i g n m e n t S i z e ) 取 整 ∗ a l i g n m e n t S i z e = ( 2 5 ) 取 整 ∗ 5 = 0 (\frac{x}{alignmentSize})_{取整}*alignmentSize=(\frac{2}{5})_{取整}*5=0 (alignmentSizex)alignmentSize=(52)5=0
    根据时间间隔step=3确定计算区间为:

    time
    2018.10.08T01:01:01.000第一个窗口的左边界
    2018.10.08T01:01:01.003第一次发生计算的时间戳
    2018.10.08T01:01:01.006第二次发生计算的时间戳=第一次 + step
    2018.10.08T01:01:01.009第三次发生计算的时间戳

    第一次发生计算的时间戳2018.10.08T01:01:01.003之前取windowSize=6,从000开始只有002一条,因此sumQty=1

    第二次发生计算的时间戳2018.10.08T01:01:01.006之前取windowSize=6,从000开始只有005、004、003、002四条,因此sumQty=4

    第三次发生计算的时间戳2018.10.08T01:01:01.009之前取windowSize=6,从000开始有008、007、006、005、004、003六条,因此sumQty=6

  • References

  1. createTimeSeriesAggregator

  2. Github >> Tutorials_CN >> DolphinDB流数据聚合引擎

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值