首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在DolphinDB数据库中重写kdb脚本

在DolphinDB数据库中重写kdb脚本
EN

Stack Overflow用户
提问于 2019-08-17 01:55:16
回答 4查看 513关注 0票数 0

我正在尝试用DolphinDB重写一个kdb脚本。

让我先解释一下我需要做什么。如果信号高于阈值T1,我们就在证券中建立多头头寸。我们不希望信号一降到T1以下就平仓,所以我们给它一个缓冲:只有当信号降到小于T1的T10以下时,我们才平仓。

另一方面,如果信号低于阈值T2,我们建立空头头寸。只有当信号移动到T20>T2上方时,我们才会关闭位置。

T1>T10>T20>T2。

基本上,我需要以下向量:

代码语言:javascript
复制
 - if signal>T1, return 1. Subsequent elements are 1 until when signal<T10; 
 - if signal<T2, return -1. Subsequent elements are -1 until when signal>T20;
 - 0 otherwise

上述任务的kdb脚本为:

代码语言:javascript
复制
0h^fills(-).(0N 1h)[(signal>T1;signal<T2)]^'(0N 0h)[(signal<T10;signal>T20)]

有谁知道如何用DolphinDB重写它吗?

EN

回答 4

Stack Overflow用户

发布于 2019-08-17 14:33:28

我在DolphinDB 0.97.4版本中做了直译

代码语言:javascript
复制
eachPost(-, loop(nullFill, [iif(signal<T10, 0h, 00h), iif(signal>T20, 0h, 00h)], [iif(signal>T1, 1h, 00h), iif(signal<T2, 1h, 00h)]))[0].ffill().nullFill(0h)

iif(cond, trueResult, falseResult)是一个基于元素的条件函数。00h表示short类型中的空值。nullFill(X, Y)将X中的空值替换为Y中的相应值。ffill(X)将X中的空值替换为之前的值。loopeachPost都是两个高阶函数。

DolphinDB中的测试用例

代码语言:javascript
复制
T1= 60
T10 = 50
T20 = 30
T2 = 20
signal = 10 20 70 59 42 49 19 25 26  35
eachPost(-, loop(nullFill, [iif(signal<T10, 0h, 00h), iif(signal>T20, 0h, 00h)], [iif(signal>T1, 1h, 00h), iif(signal<T2, 1h, 00h)]))[0].ffill().nullFill(0h)

-1 -1 1 1 0 0 -1 -1 -1 0

KDB+中的测试用例

代码语言:javascript
复制
T1:60
T10:50
T20:30
T2:20
signal:10 20 70 59 42 49 19 25 26  35
0h^fills(-).(0N 1h)[(signal>T1;signal<T2)]^'(0N 0h)[(signal<T10;signal>T20)]

-1 -1 1 1 0 0 -1 -1 -1 0

我还做了一个快速的性能比较。我生成了1000万个随机信号,并分别在DolphinDB和KDB+中运行了上面的表达式。KDB+需要800ms,而DolphinDB只需要480ms。下面是性能测试代码。

代码语言:javascript
复制
//DolphinDB
T1= 60
T10 = 50
T20 = 30
T2 = 20
signal = 1 + rand(99.0, 10000000)
timer eachPost(-, loop(nullFill, [iif(signal<T10, 0h, 00h), iif(signal>T20, 0h, 00h)], [iif(signal>T1, 1h, 00h), iif(signal<T2, 1h, 00h)]))[0].ffill().nullFill(0h)

//KDB+
T1:60
T10:50
T20:30
T2:20
signal: 1.0 + 10000000 ? 99.0
\t  0h^fills(-).(0N 1h)[(signal>T1;signal<T2)]^'(0N 0h)[(signal<T10;signal>T20)]
票数 1
EN

Stack Overflow用户

发布于 2019-11-06 18:32:26

2019年9月11日更新

备注更新版本

代码语言:javascript
复制
WITH 
    rand()/4294967295*100 AS s,
    60 AS t1, 
    50 AS t10, 
    30 AS t20, 
    20 AS t2, 
    if(s < t10, 0, if(s > t1, 1, NULL)) as signal1,
    if(s > t20, 0, if(s < t2, 1, NULL)) as signal2
SELECT
    arrayFill(x -> (x != -2), groupArray(toInt8(ifNull(signal1 - signal2, -2)))) as k
FROM numbers_mt(10000000);

根据来自Summer.H.的反馈进行了更新。以下时间安排在我的系统(Core i7-7820X)上运行。它们之间的时间差异很小。

1000万个信号

随机生成+计算

  • 1线程- DolphinDB 337ms,ClickHouse 291ms
  • 2线程(1核)- DolphinDB 226ms,ClickHouse 189ms

计算

  • 1线程- DolphinDB 302ms,ClickHouse 233ms
  • 2线程(1核)- DolphinDB 179ms,ClickHouse 165ms

2.5亿信号

随机生成+计算

  • 1线程- DolphinDB 7.901s、ClickHouse 7.103s
  • 2线程(1核)- DolphinDB 4.786s、ClickHouse 4.297s
  • 4线程(2核)- ClickHouse 2.965s

计算

  • 1线程- DolphinDB 7.106s,ClickHouse 5.564s
  • 2线程(1核)- DolphinDB 3.966s,ClickHouse 3.668s
  • 4线程(2核)- ClickHouse 2.573s

原始

注意,这并没有回答特定的问题,因为它与DolphinDB相关-但这里也有一个使用ClickHouse的版本。

代码语言:javascript
复制
WITH 
    60 AS t1, 
    50 AS t10, 
    30 AS t20, 
    20 AS t2, 
    ([if(s < t10, 0, NULL), if(s > t20, 0, NULL)], [if(s > t1, 1, NULL), if(s < t2, 1, NULL)]) AS signal
SELECT arrayFill(x -> (x != -2), groupArray(ifNull(coalesce((signal.1)[1], (signal.2)[1]) - coalesce((signal.1)[2], (signal.2)[2]), -2))) AS k
FROM 
(
    SELECT arrayJoin([10, 20, 70, 59, 42, 49, 19, 25, 26, 35]) AS s
)
FORMAT TSV

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

对1000万个随机样本进行基准测试。在我的系统上,Summer.H给出了最快的DolphinDB答案,最好的答案是:

代码语言:javascript
复制
DolphinDB (4 threads)

./dolphindb
DolphinDB Systems 0.99.0 64 bit Copyright (c) 2011~2019 DolphinDB, Inc. Licensed to Trial User. Expires on 2019.12.31 (Build:2019.10.25)

>timer t1= 60
timer t10 = 50
timer t20 = 30
timer t2 = 20
timer 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)
;>>>>>>
Time elapsed: 0.01 ms
Time elapsed: 0.001 ms
Time elapsed: 0.001 ms
Time elapsed: 0.001 ms
Time elapsed: 72.675 ms
Time elapsed: 305.442 ms

Total time: 378 ms

ClickHouse (像DolphinDB一样受限制的4个线程),最好在5个线程中运行:

代码语言:javascript
复制
CREATE TEMPORARY TABLE dtest2 AS
WITH
    rand()%100 + rand()/4294967295 AS s,
    60 AS t1,
    50 AS t10,
    30 AS t20,
    20 AS t2,
    ([if(s < t10, 0, NULL), if(s > t20, 0, NULL)], [if(s > t1, 1, NULL), if(s < t2, 1, NULL)]) AS signal
SELECT arrayFill(x -> (x != -2), groupArray(ifNull(coalesce((signal.1)[1], (signal.2)[1]) - coalesce((signal.1)[2], (signal.2)[2]), -2))) AS k
FROM numbers_mt(10000000)

Ok.

0 rows in set. Elapsed: 0.300 sec. Processed 10.00 million rows, 80.00 MB (33.37 million rows/s., 266.94 MB/s.)

Total time 300 ms

ClickHouse,默认配置/无线程限制,最佳运行时间为5:

代码语言:javascript
复制
CREATE TEMPORARY TABLE dtest2 AS
WITH
    rand()%100 + rand()/4294967295 AS s,
    60 AS t1,
    50 AS t10,
    30 AS t20,
    20 AS t2,
    ([if(s < t10, 0, NULL), if(s > t20, 0, NULL)], [if(s > t1, 1, NULL), if(s < t2, 1, NULL)]) AS signal
SELECT arrayFill(x -> (x != -2), groupArray(ifNull(coalesce((signal.1)[1], (signal.2)[1]) - coalesce((signal.1)[2], (signal.2)[2]), -2))) AS k
FROM numbers_mt(10000000)

Ok.

0 rows in set. Elapsed: 0.191 sec. Processed 10.00 million rows, 80.00 MB (52.22 million rows/s., 417.74 MB/s.)

每一项的最终计时:

kdb (800ms)、DolphinDB (480ms、378ms、330ms?)、ClickHouse (191ms)

我在这里进一步测试了2.5亿个随机信号- DolphinDB花费了9214.99ms (1420ms随机信号生成+ 7794.24ms计算)。ClickHouse总共花费了4272毫秒的时间进行随机生成和计算。

但ClickHouse在17.4秒(内存表)或20.1秒(到磁盘)内管理了10亿个信号。

票数 1
EN

Stack Overflow用户

发布于 2019-08-19 13:06:54

我在DolphinDB中优化了测试代码,如下所示:

代码语言:javascript
复制
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)

它只用了330毫秒。

更新:并行版本

DolphinDB提供了函数pcall来并行化执行。

代码语言:javascript
复制
def foo(signal){
 t1= 60
 t10 = 50
 t20 = 30
 t2 = 20
 return iif(signal >t1, 1h, iif(signal < t10, 0h, 00h)) - iif(signal <t2, 1h, iif(signal > t20, 0h, 00h))
}
signal = rand(100.0, 250000000)

//with single threads
timer foo(signal).ffill().nullFill(0h)

//with multiple threads
timer pcall(foo,signal).ffill().nullFill(0h)

单个线程的计算时间为6412ms(2.5亿),而两个线程的计算时间为2938ms,四个线程的计算时间仅为2086ms。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57529114

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档