You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按规则为kdb+表各日期分组的合约计算成交量排名

kdb+ 按成交量计算期货主力合约排名

问题说明

现有一张期货合约行情表,表结构示例如下:
原始表示例
需要按照以下规则计算排名列roll_rank:

  • 以日期(date)为分组维度,按每组内成交量(volume)降序设置排名
  • 若volume为空值,对应行不参与排名,roll_rank留空
  • roll_rank=1对应当日主力合约,一旦合约被新主力替换,后续交易日不可再被标记为roll_rank=1

预期输出效果如下:
预期输出示例

可通过以下q代码生成测试样例表:

tab:([]date:`date$();sym:`symbol$();name:`symbol$();volume:`float$();roll_rank:`int$());
`tab insert (2010.01.01;`ESH22;`ES;100.1;0Ni);
`tab insert (2010.01.01;`ESH23;`ES;500.1;0Ni);
`tab insert (2010.01.02;`ESH22;`ES;100.1;0Ni);
`tab insert (2010.01.02;`ESH23;`ES;800.1;0Ni);
`tab insert (2010.01.02;`ESH24;`ES;600.1;0Ni);
`tab insert (2010.01.02;`ESH25;`ES;550.1;0Ni);
`tab insert (2010.01.02;`ESH26;`ES;200.1;0Ni);
`tab insert (2010.01.03;`ESH23;`ES;600.1;0Ni);
`tab insert (2010.01.03;`ESH24;`ES;700.1;0Ni);
`tab insert (2010.01.03;`ESH26;`ES;0n;0Ni);
`tab insert (2010.01.03;`ESH25;`ES;500.1;0Ni);
`tab insert (2010.01.03;`ESH26;`ES;0n;0Ni);
`tab insert (2010.01.04;`ESH23;`ES;50.1;0Ni);
`tab insert (2010.01.05;`ESH23;`ES;300.1;0Ni);
`tab insert (2010.01.05;`ESH24;`ES;800.1;0Ni);
`tab insert (2010.01.05;`ESH25;`ES;100.1;0Ni);

实现代码

核心逻辑为按时间顺序逐交易日处理,维护已退市的历史主力合约集合,确保老主力不会再次被标记为当日主力,具体实现如下:

/ 按升序获取所有交易日
dates:asc distinct tab`date;
/ 初始化状态变量:已退市主力合约集合、上一交易日主力、结果表
retired_syms:`$();
prev_front:`$();
res:();
/ 逐交易日计算排名
{[retired_syms;prev_front;res;x]
  / 提取当日有效记录(volume非空),按成交量降序排序
  valid_rec:`volume xdesc select from tab where date=x, not null volume;
  / 过滤已退市合约,取剩余中成交量最高的为当日主力
  eligible:valid_rec where not valid_rec`sym in retired_syms;
  cur_front:first eligible`sym;
  / 若主力发生切换,将老主力加入退市集合
  if[all not null (prev_front;cur_front), prev_front <> cur_front;
    retired_syms,:prev_front
  ];
  / 生成初始排名
  valid_rec:update roll_rank:1+til count valid_rec from valid_rec;
  / 调整排名:将当日主力rank置为1,原rank1的合约替换为主力原来的排名
  if[cur_front <> first valid_rec`sym;
    fr:first exec roll_rank from valid_rec where sym=cur_front;
    valid_rec:update roll_rank:@[roll_rank; where sym=cur_front; :; 1] from valid_rec;
    valid_rec:update roll_rank:@[roll_rank; where (roll_rank=1) and (sym<>cur_front); :; fr] from valid_rec;
  ];
  / 合并当日volume为空的记录(roll_rank保持空值)
  null_rec:select from tab where date=x, null volume;
  res,:raze (valid_rec;null_rec);
  / 传递状态到下一个交易日
  (retired_syms;cur_front;res)
 }/(retired_syms;prev_front;res;dates);
/ 提取最终结果,按日期、合约排序对齐原表顺序
final_res:`date`sym xasc res 2;

结果验证

运行代码后输出的final_res完全符合规则要求:

  • 2010.01.01-2010.01.02主力为ESH23,roll_rank=1
  • 2010.01.03ESH24成交量超过ESH23成为新主力,ESH23加入退市集合
  • 2010.01.04仅ESH23有成交量,但属于已退市合约,不标记为rank=1
  • 2010.01.05ESH24保持最高成交量,继续为rank=1,ESH23即使有成交量也不会再成为主力
  • 所有volume为空的行roll_rank均为空值

内容的提问来源于stack exchange,提问作者BlackPearl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 19:06:40