从KDB服务器中提取nbbo数据

时间:2015-03-31 19:54:46

标签: kdb

我有一个代码表,其中包含日期,开始时间,结束时间,我需要从服务器上的nbbo表中提取nbbo。例如

Date         starttime    endtime      sym
2014.05.01  15:10:38.000  15:10:58.000 KT
2014.05.01  15:15:53.000  15:16:23.000 IBM
2014.05.01  15:37:39.000  15:37:59.000 AAPL

理想情况下,我将打开服务器的句柄并通过传入此函数来拉取每行的数据:getnnbo并将其称为:getnnbo[ KT; 2014.05.01; 15:10:3​​8.000; 15:10:58.000]`其中函数定义为

getnbbo:{[sym;dt;starttime;endtime]:h1"select 0.5*(first bid + first ask) from nbbo where date=",string[dt],",sym =`",string[sym], ",linetime within (",string[starttime],",",string[endtime],")"}

当我将其称为getnnbo[ KT时,此功能有效; 2014.05.01; 15:10:3​​8.000; 15:10:58.000]`但我不知道如何对表中的每一行进行操作,因为我必须使用服务器的句柄。

2 个答案:

答案 0 :(得分:1)

以下内容适用于您,假设lst是包含`date`starttime`endtime`sym列的查找表的名称:

getnbbo ./: flip lst[`sym`date`starttime`endtime]

在上面我们做了以下几点:

  • lst[`sym`date`starttime`endtime] - 以正确的顺序提取列值,因此它们与函数args
  • 对齐
  • flip lst[...] - 将列值转换为函数
  • 的正确形式

关于您已粘贴的代码的其他一般要点 -

从右到左的评估

从您的select语句中取以下内容:

0.5*(first bid + first ask)

这实际上是在做你需要的,但偶然。它实际上没有正确确定范围。 Kdb +将从右到左评估这个。所以在上面的表格中它将

  1. 第一次提问
  2. bid 添加到其中
  3. 从结果中获取第一个值
  4. 这是在这种情况下计算你想要的值,但可能会在不同的场景中绊倒你。

    写这个的正确方法是:

    0.5 * first[bid] + first[ask]
    

    这将确保评估顺序

    1. 获取第一个ask
    2. 获取第一个bid
    3. 添加两个
    4. 乘以0.5
    5. 或者,如果您赞成括号,您可以按如下方式编写:

      0.5 * (first bid)+(first ask)
      

      字符串生成函数

      getnbbo函数以字符串形式生成查询 - 这对于简单的情况很好,但通常不是很好的做法。通常更好的做法是(1)一个接受参数的函数或(2)切换到一个函数选择语句 - (2)需要更深入地理解Kdb +,我不会在这里进入。< / p>

      立即改进是使其成为一个参与争论的函数。所以getnbbo会成为:

      getnbbo:{[handle;sym;dt;starttime;endtime]
          getDataFunc:{[s;dt;st;et]
              select 0.5*first[bid]+first[ask] from nbbo where date=dt, sym=s, linetime within (st;et)
          };
      
          handle(getDataFunc;sym;dt;starttime;endtime)
       };
      

      在上面,

      • getnbbo func采用与以前相同的args,但我们也传入句柄(不是必需的,但是很好的做法)
      • getnbbo中,我们定义一个新的参数化函数getDataFunc,给定参数(args)返回带有适当子句的select语句的结果
      • 最后,它使用输入参数
      • getDataFunc发送到远程句柄

      进一步阅读:

答案 1 :(得分:0)

我建议不要对服务器上的每一行提出请求,而是立即发送全表(或者如果它很大的话,发送一部分)并从服务器的一个请求中获取数据。这应该会加快进程,因为请求较少,服务器也会花费更少的时间来生成结果,因为通常在列表上进行计算比单个行更快。

所以你的功能应该是下面的东西(只是一个例子)。您可以根据需要对其进行优化/修改。我假设您的股票代码表每个(日期; sym)组合只有一个条目,以便它可以作为主键。

   getData:{[tbl] select 0.5*first[bid]+first[ask] from (nbbo ij `date`sym xkey tbl) where linetime within (st;et) }

然后使用服务器句柄在服务器上运行它。 'tbl'是带有代码的输入表。

   handle(getData;tbl)

编辑ma3266评论后:

我假设有两个条件:

a)nbbo表在服务器上分区

b)您的输入tbl具有与nbbo相同的日期和符号列名称。否则,您可以使用'xcol'重命名它们。

     getData:{tbl:0!tbl; tempNbbo:0!select from nbbo where date in tbl`date,sym in tbl`sym ; select 0.5*first[bid]+first[ask] from (tempNbbo ij `date`sym xkey tbl) where linetime within (starttime;endtime)}

但如果您的输入表包含许多日期的数据,则可能导致大量内存使用。在这种情况下,您可以使用以下函数,它将按日期中断输入表。

   getData:{tbl:0!`date xasc tbl; raze { tempNbbo:0!select from nbbo where date in x`date,sym in x`sym ; select 0.5*first[bid]+first[ask] from (tempNbbo ij `date`sym xkey x) where linetime within (starttime;endtime)} each (where differ tbl`date) cut tbl}

在这两个函数中,我首先从输入表中删除主键属性。

另外,检查nbbo的列类型和输入表。这可能会给你输入错误。这个查询对我来说很好。