在特定条件下对 kdb 中的数据进行分组

Grouping data in kdb with certain condition

我有一个名为 raw 的主数据框,如下所示:

tab:([]date:2018.02.05 2018.02.05 2018.02.06 2018.02.06;time:01:30:25.000 02:30:45.000 04:15:15.000 02:15:15.000;vol:50 55 64 12; name:`A`B`B`A)

date           time         vol     name   
2018.02.05     1:30:25      50       A
2018.02.05     2:30:45      55       B
2018.02.06     4:15:15      64       B
2018.02.06     2:15:15      12       A

我需要根据以下条件创建一个新的 table:

在两个特定的日期之间,我需要找出名称 B 在两小时内的累计成交量为 100 的时间。

我认为应该可行的逻辑:按时间升序排列数据。添加所有 vol by name= `B for time within (time[i]: time[i]+2hrs)。如果 cum vol > 100,return 时间间隔和相应的日期。继续 i +1 。我是 kdb 的新手,所以我在实施它时遇到困难。

示例输出:

time1          time2         date1         date2
1:30:00        3:30:00       2018.02.05    2018.02.05
23:00:00       1:00:00       2018.02.05    2018.02.06

感谢任何相关线索。谢谢

我相信使用 aj 可以解决您的问题

最初正如您所指出的,table 应该按时间排序

`time xasc `tab;

然后,应该使用 sums

创建卷的累积总和
tab:update cumvol:sums vol by name from tab

然后使用aj - 得到每次不在2小时内的交易量的累计和。

aj[`name`time;tab;select time:time+02:00,name,cumvol2:cumvol from tab]

然后我们可以执行 cumvol - cumvol2 以获得每 2 小时内的总体积

tab:select time, name, runningvol:cumvol-0^cumvol2 from 
aj[`name`time;tab;select time:time+02:00,name,cumvol2:cumvol from tab]

然后一个简单的select语句就可以得到cumvol大于100的次数

select time,time+02:00 from tab where runningvol>100

可以对此添加的一项改进是在 aj 的第 2 个 table 上添加一个分组属性。 对此的另一项改进是将日期和时间格式化为单个时间戳或日期时间。

可以在此处找到有关函数 aj 和 sums 的更多信息:

http://code.kx.com/q/ref/joins/#aj-aj0-asof-join

http://code.kx.com/q/ref/arith-integer/#sums

您也可以为此使用 window join wj1。举个例子 table:

t:`time xasc ([]time:(1000?2018.02.05 2018.02.06)+1000?24:00:00;sym:1000?`A`B`C;vol:1000?10);

以下函数在相对于时间戳 windows 的 2 小时内聚合 vol,并传递 table t、开始日期 s、结束日期 e 和姓名 n.

fw:{[t;s;e;n]
  r:@[;`sym;`p#]`sym`time xasc select from t where time.date within(s;e),sym=n;
  :select from wj1[r[`time]-/:02:00 00:00;`time;r;(r;(sum;`vol))] where vol>100;
 };

运行 对于 name/sym B 给出:

q)fw[t;2018.02.05;2018.02.06;`B]
time                          sym vol
-------------------------------------
2018.02.05D18:12:39.000000000 B   104
2018.02.05D18:35:47.000000000 B   101
2018.02.05D18:40:17.000000000 B   102
...

也可以修改为给出所有names/syms:

的所有结果
fw1:{[t;s;e]
  r:@[;`sym;`p#]`sym`time xasc select from t where time.date within(s;e);
  :select from wj1[r[`time]-/:02:00 00:00;`sym`time;r;(r;(sum;`vol))] where vol>100;
 };

运行 这次没有 name/sym:

q)fw1[t;2018.02.05;2018.02.06]
time                          sym vol
-------------------------------------
2018.02.05D02:01:36.000000000 A   106
2018.02.05D02:52:23.000000000 A   103
2018.02.05D03:06:51.000000000 A   105
...

虽然这种方法不如使用 aj 有效,但它仍然说明了如何使用 window 连接实现此目的。