KDB+/Q技术实现:如何标记下一次价格变动的正负方向
KDB+ 实现标记下一次价格变动方向的布尔列isUp
问题背景
现有不含goesUp与isUp列的KDB+表,需要创建布尔列isUp标记下一次价格变动是否为正。原代码仅对比相邻tick的价格,当中间存在价格不变的tick时会出错:例如AAPL第二行,下一次实际价格变动是从2涨到3(应标记为1b),但原代码因下一个tick价格不变返回0b。
原测试代码:
test:([] time:09:30:00.500000000 09:30:00.500500000 09:30:00.600000000 09:30:00.610000000 09:30:00.610100000 09:30:00.620500000 09:30:00.621000000 09:30:00.630000000 09:30:01 09:30:02 09:30:03; RIC:`AAPL`AAPL`AAPL`IBM`AAPL`AAPL`AAPL`IBM`IBM`IBM`IBM; price:1 2 2 11 3 2 1 12 12 11 12; goesUp:`Y`Y`Y`Y`N`N`NA`N`N`Y`NA); result:update isUp:(0b;1b) price< next price by RIC from test;
解决方案
核心思路是:按RIC分组后,为每个tick找到后续第一个价格不同的数值,再对比当前价格与该数值的大小关系。通过where定位价格变动点,结合fills前向填充,为每个tick匹配对应的下一次变动价格。
修改后的代码
// 按RIC分组,为每个tick匹配下一次价格变动后的数值,再计算isUp result: update isUp: price < { // 找到分组内所有价格发生变动的索引(跳过第一个元素的初始0n对比) changeIdxs: where price <> prev price; // 创建字典:变动索引+最后一行位置 对应 变动后价格+0n(无后续变动) changeMap: (changeIdxs, count x)!x[changeIdxs], 0n; // 前向填充,为每个位置分配下一次变动的价格 fills[0n; changeMap] } price by RIC from test;
代码逻辑解释
- 定位变动点:
where price <> prev price筛选出分组内价格发生变化的索引位置(第一个元素因prev price为0n,不会被纳入)。 - 构建映射字典:将变动索引和分组最后一行位置作为键,对应变动后的价格和
0n(标记无后续变动)作为值。 - 前向填充:
fills[0n; changeMap]为每个tick填充后续第一个变动的价格,确保价格不变的tick能继承下一次变动的目标价格。 - 计算isUp:对比当前价格与填充后的下一次变动价格,得到布尔值;最后一行因无后续变动,对比结果为
0b。
修正后的结果
| time | RIC | price | goesUp | isUp |
|---|---|---|---|---|
| 0D09:30:00.500000000 | AAPL | 1 | Y | 1 |
| 0D09:30:00.500500000 | AAPL | 2 | Y | 1 |
| 0D09:30:00.600000000 | AAPL | 2 | Y | 1 |
| 0D09:30:00.610000000 | IBM | 11 | Y | 1 |
| 0D09:30:00.610100000 | AAPL | 3 | N | 0 |
| 0D09:30:00.620500000 | AAPL | 2 | N | 0 |
| 0D09:30:00.621000000 | AAPL | 1 | NA | 0 |
| 0D09:30:00.630000000 | IBM | 12 | N | 0 |
| 0D09:30:01.000000000 | IBM | 12 | N | 0 |
| 0D09:30:02.000000000 | IBM | 11 | Y | 1 |
| 0D09:30:03.000000000 | IBM | 12 | NA | 0 |
可以看到AAPL第二行的isUp已修正为1b,符合下一次价格变动为正的预期;其他价格不变的tick也正确匹配了后续变动方向。
内容的提问来源于stack exchange,提问作者Cole
相关产品推荐
相关产品推荐

