关于金融:干货丨DolphinDB高频数据处理技巧如何将高频信号转化成离散的买卖信号

41次阅读

共计 2857 个字符,预计需要花费 8 分钟才能阅读完成。

高频交易中,咱们通常首先基于 tick 级的报价信息和交易信息来生成信号量,而后将这些信号量转化成离散的交易信号,譬如说 1(买入),0(不变),-1(卖出),接着依据资金和已有头寸以及其余优化规定来生成订单发送到交易系统。本文要探讨第二个步骤,即如何将信号量转化成离散的交易信号,也就是把一个浮点数类型的数组 signal 转化成一个取值为 1,0 或 - 1 的整型数组 direction。

如果转化规定简略,譬如超过某一个阈值 t1 为 +1(买入信号),低于某一个阈值 t2 为 -1(卖出信号),其余状况为 0,那么实现起来也很简略。譬如在 DolphinDB 中用上面这个表达式就能够实现。

iif(signal > t1, 1, iif(signal <t2, -1, 0))

实际中,为了让零碎更加的强壮,不要频繁的切换交易方向,通常不会这么解决。一个罕用的做法是这样:当信号量超过某一个阈值 t1 时,开始转化为买入信号,后续的信号量在衰减到低于 t10 之前,始终放弃买入信号(+1);同理当信号量低于某一个阈值 t2 时,开始转化为卖出信号,后续的信号量在加强到大于 t20 之前,始终放弃卖出信号(-1);其余状况为 0。这儿 t1, t10, t2, t20 满足上面的规定:

t1 > t10 > t20 > t2

当零碎依照下面的规定运行时,决定交易方向的除了以后的信号量值,还有前一个交易信号的状态,这是典型的门路依赖问题。通常咱们认为门路依赖问题不适宜向量化的办法来解决,或者说须要十分高的技巧。而咱们用来回测高频数据的语言通常都是脚本语言(譬如 DolphinDB 和 kdb+),脚本语言在解决量化问题时效率很高,然而如果须要逐行解决门路依赖问题,解析老本会很高,效率低下。明天咱们会介绍一些技巧,如何化解这个矛盾?

咱们先找出买入信号。在一个向量中找到大于 t1 的点很容易(买入信号的临界点),找到不可能是买入信号的点也很简略(小于 t10)。这样咱们把一个向量上的点分成了三种状态,买入信号临界点(+1),不可能是买入信号的点 (0),其余状态未知的点 (NULL)。依据后面的规定,如果状态未知的点,后面呈现了买入临界点,那么该点也应该置为买入信号点;如果后面呈现了非买入信号点(0),那么该点也应该置为非买入信号点。因而咱们能够应用 front fill 来实现。咱们用同样的办法能够找出卖出信号(卖出信号为 +1,其余信号为 0)。两者相减能够失去最终的信号。可能还存在一些为 null 的信号,把这部分信号替换为 0。DolphinDB 的全副代码如下:

buy = iif(signal >t1, 1h, iif(signal < t10, 0h, 00h)).ffill()
sell = iif(signal <t2, 1h, iif(signal > t20, 0h, 00h)).ffill()
direction = (buy - sell).nullFill(0h)

下面的代码能够合并成单个表达式:

direction = (iif(signal >t1, 1h, iif(signal < t10, 0h, 00h)) - iif(signal <t2, 1h, iif(signal > t20, 0h, 00h))).ffill().nullFill(0h)

一个简略的测试如下:

t1= 60
t10 = 50
t20 = 30
t2 = 20
signal =10 20 70 59 42 49 19 25 26  35
direction = (iif(signal >t1, 1h, iif(signal < t10, 0h, 00h)) - iif(signal <t2, 1h, iif(signal > t20, 0h, 00h))).ffill().nullFill(0h)

[-1,-1,1,1,0,0,-1,-1,-1,0]

如果改用 kdb+ 脚本来实现,则表达式如下:

direction: 0h^fills(-).(0N 1h)[(signal>t1;signal<t2)]^'(0N 0h)[(signal<t10;signal>t20)]

如果应用 pandas 实现,代码如下:

t1 = 60
t10 = 50
t20 = 30
t2 = 20
signal = pd.Series([10,20,70,59,42,49,19,25,26,35])
direction = (signal.apply(lambdas: 1 if s > t1 else (0 if s < t10 else np.nan)) -
             signal.apply(lambdas: 1 if s < t2 else (0 if s > t20 else np.nan))).ffill().fillna(0)

上面咱们生成一个长度为 1000 万的在 0~100 之间的随机信号数组,测试 DolphinDB、kdb+ 和 pandas 的性能。测试应用的机器配置如下:

CPU:Intel(R) Core(TM) i7-7700 CPU @3.60GHz 3.60 GHz

内存:16GB

OS:Windows 10

DolphinDB 耗时 330ms, kdb+ 耗时 800ms,pandas 耗时 6.8s 左右 。DolphinDB 的测试脚本如下:

t1= 60
t10 = 50
t20 = 30
t2 = 20
signal = rand(100.0, 10000000)
timer direction = (iif(signal >t1, 1h, iif(signal < t10, 0h, 00h)) - iif(signal <t2, 1h, iif(signal > t20, 0h, 00h))).ffill().nullFill(0h)

kdb+ 的测试脚本如下:

t1:60
t10:50
t20:30
t2:20
signal: 10000000 ? 100.0
t  0h^fills(-).(0N 1h)[(signal>t1;signal<t2)]^'(0N 0h)[(signal<t10;signal>t20)]

pandas 的测试脚本如下:

import time
t1= 60
t10= 50
t20= 30
t2= 20
signal= pd.Series(np.random.random(10000000) * 100)
start= time.time()
direction= (signal.apply(lambdas:1 if s > t1 else (0 if s < t10 else np.nan)) -
            signal.apply(lambdas:1 if s < t2 else (0 if s > t20 else np.nan))).ffill().fillna(0)
end= time.time()
print(end- start)

通过下面这个例子,也不难发现,DolphinDB 和 kdb+ 的脚本在实质上有很多共性的货色。kdb+ 的脚本基本上能逐句逐词的翻译成 DolphinDB 脚本。区别在于 kdb+ 是从左到右解析脚本的,而 DolphinDB 跟惯例的编程语言一样,是从右到左;kdb+ 喜爱用符号来代表某一个性能,而 DolphinDB 更喜爱用函数来表白某一个性能,可读性会比拟好但也会简短一点。

DolphinDB database 下载地址:DolphinDB

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

正文完
 0