我正在尝试用DolphinDB重写一个kdb脚本。
让我先解释一下我需要做什么。如果信号高于阈值T1,我们就在证券中建立多头头寸。我们不希望信号一降到T1以下就平仓,所以我们给它一个缓冲:只有当信号降到小于T1的T10以下时,我们才平仓。
另一方面,如果信号低于阈值T2,我们建立空头头寸。只有当信号移动到T20>T2上方时,我们才会关闭位置。
T1>T10>T20>T2。
基本上,我需要以下向量:
- 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脚本为:
0h^fills(-).(0N 1h)[(signal>T1;signal<T2)]^'(0N 0h)[(signal<T10;signal>T20)]有谁知道如何用DolphinDB重写它吗?
发布于 2019-08-17 14:33:28
我在DolphinDB 0.97.4版本中做了直译
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中的空值替换为之前的值。loop和eachPost都是两个高阶函数。
DolphinDB中的测试用例
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 0KDB+中的测试用例
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。下面是性能测试代码。
//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)]发布于 2019-11-06 18:32:26
2019年9月11日更新
备注更新版本
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万个信号
随机生成+计算
仅计算
2.5亿信号
随机生成+计算
仅计算
原始
注意,这并没有回答特定的问题,因为它与DolphinDB相关-但这里也有一个使用ClickHouse的版本。
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答案,最好的答案是:
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 msClickHouse (像DolphinDB一样受限制的4个线程),最好在5个线程中运行:
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 msClickHouse,默认配置/无线程限制,最佳运行时间为5:
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亿个信号。
发布于 2019-08-19 13:06:54
我在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)它只用了330毫秒。
更新:并行版本
DolphinDB提供了函数pcall来并行化执行。
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。
https://stackoverflow.com/questions/57529114
复制相似问题