从 KDB 服务器拉取 nbbo 数据
Pulling nbbo data from KDB server
我有一个 table 的带有日期、开始时间、结束时间的代码,我需要从服务器上的 nbbo table 中提取 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
理想情况下,我将打开一个服务器句柄,并通过传入此 function:getnnbo 并将其称为:getnnbo[
KT;2014.05.01;15:10 来提取每一行的数据:38.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:38.000; 时,此函数有效。 15:10:58.000]` 但我不确定如何为 table 中的每一行执行此操作,因为我必须使用服务器的句柄。
假设 lst
是具有 `date`starttime`endtime`sym
列的查找 table 的名称,以下内容应该适合您:
getnbbo ./: flip lst[`sym`date`starttime`endtime]
在上面我们做了以下操作:
lst[`sym`date`starttime`endtime]
- 以正确的顺序提取列值,以便它们与函数 args 对齐
flip lst[...]
- 将列值转置为函数的正确形式
关于您粘贴的代码的其他一般要点 --
从右到左求值
从您的 select 声明中提取以下内容:
0.5*(first bid + first ask)
这实际上是按照您的要求进行的,但是是偶然的。它实际上没有正确的范围。 Kdb+ 将从右到左评估这个。所以在上面的形式中它将
- 获得第一个问题
- 添加
bid
列
- 从结果中取第一个值
这是在计算您在这种情况下想要的值,但在不同的情况下可能会误导您。
正确的写法是:
0.5 * first[bid] + first[ask]
这将确保评估的顺序是
- 获得第一个
ask
- 获得第一个
bid
- 将两者相加
- 乘以 0.5
或者,如果您喜欢括号,您可以这样写:
0.5 * (first bid)+(first ask)
字符串生成函数
getnbbo
函数生成字符串形式的查询 - 这对于简单的情况很好,但通常不是好的做法。通常最好将其设为 (1) 带参数的函数或 (2) 切换到函数式 select 语句 - (2) 需要对 Kdb+ 有更深入的了解,我不会在这里深入讨论。
一个直接的改进是使它成为一个接受参数的函数。所以 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) returns select 语句的结果以及适当的子句
- 最后,它将
getDataFunc
发送到带有输入 args 的远程句柄
进一步阅读:
- IPC - Message Formats - 解释
handle(func;arg1;..;argN)
- Operations on Complex Column Data - 涉及查询中从右到左的操作
我建议不要对服务器上的每一行发出请求,而是一次发送完整的 table(如果很大,则发送一部分)并在一次请求中从服务器获取数据。这应该会加快处理速度,因为请求更少,服务器生成结果的时间也会更少,因为通常对列表进行计算比对单个行进行计算要快。
所以你的函数应该像下面这样(只是一个例子)。你可以optimize/modify根据你的需要。我假设您的代码 table 每个 (date;sym) 组合只有一个条目,因此它可以作为主键。
getData:{[tbl] select 0.5*first[bid]+first[ask] from (nbbo ij `date`sym xkey tbl) where linetime within (st;et) }
然后运行它在服务器上使用服务器句柄。 'tbl' 是您输入的 table 和代码。
handle(getData;tbl)
ma3266评论后编辑:
我假设以下两个条件:
a) nbbo table 在服务器上分区
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)}
但如果您的输入 table 包含多个日期的数据,这可能会导致大量内存使用。在这种情况下,您可以使用以下函数按日期中断输入 table。
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}
在这两个函数中,我首先从输入中删除主键属性 table。
此外,检查 nbbo 的列类型和您的输入 table。那可能会给你类型错误。这个查询对我来说工作正常。
我有一个 table 的带有日期、开始时间、结束时间的代码,我需要从服务器上的 nbbo table 中提取 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
理想情况下,我将打开一个服务器句柄,并通过传入此 function:getnnbo 并将其称为:getnnbo[
KT;2014.05.01;15:10 来提取每一行的数据:38.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:38.000; 时,此函数有效。 15:10:58.000]` 但我不确定如何为 table 中的每一行执行此操作,因为我必须使用服务器的句柄。
假设 lst
是具有 `date`starttime`endtime`sym
列的查找 table 的名称,以下内容应该适合您:
getnbbo ./: flip lst[`sym`date`starttime`endtime]
在上面我们做了以下操作:
lst[`sym`date`starttime`endtime]
- 以正确的顺序提取列值,以便它们与函数 args 对齐
flip lst[...]
- 将列值转置为函数的正确形式
关于您粘贴的代码的其他一般要点 --
从右到左求值
从您的 select 声明中提取以下内容:
0.5*(first bid + first ask)
这实际上是按照您的要求进行的,但是是偶然的。它实际上没有正确的范围。 Kdb+ 将从右到左评估这个。所以在上面的形式中它将
- 获得第一个问题
- 添加
bid
列 - 从结果中取第一个值
这是在计算您在这种情况下想要的值,但在不同的情况下可能会误导您。
正确的写法是:
0.5 * first[bid] + first[ask]
这将确保评估的顺序是
- 获得第一个
ask
- 获得第一个
bid
- 将两者相加
- 乘以 0.5
或者,如果您喜欢括号,您可以这样写:
0.5 * (first bid)+(first ask)
字符串生成函数
getnbbo
函数生成字符串形式的查询 - 这对于简单的情况很好,但通常不是好的做法。通常最好将其设为 (1) 带参数的函数或 (2) 切换到函数式 select 语句 - (2) 需要对 Kdb+ 有更深入的了解,我不会在这里深入讨论。
一个直接的改进是使它成为一个接受参数的函数。所以 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) returns select 语句的结果以及适当的子句 - 最后,它将
getDataFunc
发送到带有输入 args 的远程句柄
进一步阅读:
- IPC - Message Formats - 解释
handle(func;arg1;..;argN)
- Operations on Complex Column Data - 涉及查询中从右到左的操作
我建议不要对服务器上的每一行发出请求,而是一次发送完整的 table(如果很大,则发送一部分)并在一次请求中从服务器获取数据。这应该会加快处理速度,因为请求更少,服务器生成结果的时间也会更少,因为通常对列表进行计算比对单个行进行计算要快。
所以你的函数应该像下面这样(只是一个例子)。你可以optimize/modify根据你的需要。我假设您的代码 table 每个 (date;sym) 组合只有一个条目,因此它可以作为主键。
getData:{[tbl] select 0.5*first[bid]+first[ask] from (nbbo ij `date`sym xkey tbl) where linetime within (st;et) }
然后运行它在服务器上使用服务器句柄。 'tbl' 是您输入的 table 和代码。
handle(getData;tbl)
ma3266评论后编辑:
我假设以下两个条件:
a) nbbo table 在服务器上分区
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)}
但如果您的输入 table 包含多个日期的数据,这可能会导致大量内存使用。在这种情况下,您可以使用以下函数按日期中断输入 table。
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}
在这两个函数中,我首先从输入中删除主键属性 table。
此外,检查 nbbo 的列类型和您的输入 table。那可能会给你类型错误。这个查询对我来说工作正常。