乐趣区

关于金融:干货丨DolphinDB高频数据处理技巧数据透视的应用

行列转换(pivot)是一个常见的整顿数据的需要,又称为转置或者透视。

高频数据通常以下图的格局保留:每一行为一个股票在某个时刻的信息。

咱们进行数据处理时,思考到后续的向量化操作,有时会心愿数据或者两头后果将原始数据转置,即每行代表不同的时刻,而每列代表一只股票。在 DolphinDB 中可通过 pivot by 语句对原始数据或分组聚合后果进行行列转置。若与向量化操作搭配应用,在高频数据处理和计算中,行列转换不仅可简化策略代码,还能进步代码效率。具体请看上面的两个例子。

  1. 计算股票收益的两两相关性

在配对交易 (pair trading) 及危险对冲 (hedging) 时,常常须要计算给定一篮子股票之间的两两相关性。这种简单的计算在传统的数据库中无奈执行,而应用个别的统计软件不仅须要数据迁徙,还须要繁琐的代码。上面咱们应用 DolphinDB 来计算股票收益的两两相关性。

首先,载入美股股票高频交易数据库:

quotes = loadTable("dfs://TAQ", "quotes")

接下来,抉择 2009 年 8 月 4 日中 500 只报价变动最频繁的股票:

dateValue=2009.08.04
num=500
syms = (exec count(*) from quotes where date = dateValue, time between 09:30:00 : 15:59:59, 0<bid, bid<ofr, ofr<bid*1.1 group by Symbol order by count desc).Symbol[0:num]

上面咱们利用 pivot by 将高频数据降维成为分钟级数据,并且扭转原始数据的构造,生成一个分钟级股票价格矩阵:每一列是一只股票;每一行是一分钟。

priceMatrix = exec avg(bid + ofr)/2.0 as price from quotes where date = dateValue, Symbol in syms, 0<bid, bid<ofr, ofr<bid*1.1, time between 09:30:00 : 15:59:59 pivot by time.minute() as minute, Symbol

DolphinDB 的语言非常灵活。在这里,pivot by 不仅将数据转换为透视表,同时也能够搭配聚合函数应用,具备 ”group by” 的性能。

利用高阶函数 each 将价格矩阵转换为收益率矩阵:

retMatrix = each(def(x):ratios(x)-1, priceMatrix)

利用高阶函数 pcross 计算这 500 只股票之间收益的两两相关性:

corrMatrix = pcross(corr, retMatrix)

选取与每只股票相关性最高的 10 只股票:

mostCorrelated = select * from table(corrMatrix).rename!(`sym`corrSym`corr) context by sym having rank(corr,false) between 1:10

选取与 SPY 相关性最高的 10 只股票:

select * from mostCorrelated where sym='SPY' order by corr desc

quotes 总共有 2,693 亿条数据,2009 年 8 月 4 日这天一共有近 1.9 亿条数据,执行下面的计算,耗时仅需 1,952 毫秒

  1. 计算股票组合的价值

在进行指数套利交易回测时,须要计算给定股票组合的价值。当数据量极大时,回测时采纳个别数据分析系统,对系统内存及速度的要求极高。而 DolphinDB database 从底层进行优化,对硬件的要求不高。

在本例中,为了简化起见,假设某个指数只由两只股票组成:AAPL 与 FB,工夫戳精度为纳秒,指数成分权重存在 weights 字典中。

Symbol=take(`AAPL, 6) join take(`FB, 5)
Time=2019.02.27T09:45:01.000000000+[146, 278, 412, 445, 496, 789, 212, 556, 598, 712, 989]
Price=173.27 173.26 173.24 173.25 173.26 173.27 161.51 161.50 161.49 161.50 161.51
quotes=table(Symbol, Time, Price)
weights=dict(`AAPL`FB, 0.6 0.4)
ETF = select Symbol, Time, Price*weights[Symbol] as weightedPrice from quotes
select last(weightedPrice) from ETF pivot by Time, Symbol;

运行后果如下:

Time                          AAPL    FB
----------------------------- ------- ------
2019.02.27T09:45:01.000000146 103.962
2019.02.27T09:45:01.000000212         64.604
2019.02.27T09:45:01.000000278 103.956
2019.02.27T09:45:01.000000412 103.944
2019.02.27T09:45:01.000000445 103.95
2019.02.27T09:45:01.000000496 103.956
2019.02.27T09:45:01.000000556         64.6
2019.02.27T09:45:01.000000598         64.596
2019.02.27T09:45:01.000000712         64.6
2019.02.27T09:45:01.000000789 103.962
2019.02.27T09:45:01.000000989         64.604

因为工夫戳精度为纳秒,基本上所有交易的工夫戳均不统一。如果回测时的数据行数极多(几亿或几十亿行)且指数成分股数量也较多(如 S &P500 指数的 500 只成分股),应用传统剖析零碎,要计算任一时刻的指数价值,须要将原始数据表的 3 列(工夫,股票代码,价格)转换为等同长度然而宽度为指数成分股数量 + 1 的数据表,向前补充空值(forward fill NULLs),进而计算每行的指数成分股对指数价格的奉献之和。这种做法,会产生比原始数据表大很多倍的两头过程数据表,很有可能会导致系统内存不足。同时,计算速度也很慢。

应用 DolphinDB 的 pivot by 语句,只须要一行代码,即可实现上述的所有步骤,代码简洁,而且无需产生两头过程数据表,无效防止内存不足的问题,同时极大晋升计算速度。

select rowSum(ffill(last(weightedPrice))) from ETF pivot by Time, Symbol;

后果如下:

Time                          rowSum
----------------------------- -------
2019.02.27T09:45:01.000000146 103.962
2019.02.27T09:45:01.000000212 168.566
2019.02.27T09:45:01.000000278 168.56
2019.02.27T09:45:01.000000412 168.548
2019.02.27T09:45:01.000000445 168.554
2019.02.27T09:45:01.000000496 168.56
2019.02.27T09:45:01.000000556 168.556
2019.02.27T09:45:01.000000598 168.552
2019.02.27T09:45:01.000000712 168.556
2019.02.27T09:45:01.000000789 168.562
2019.02.27T09:45:01.000000989 168.566

DolphinDB 下载:DolphinDB

应用过程中有任何问题,欢送退出智臾科技:DolphinDB 技术交换群,内含二维码

退出移动版