首页 文章

如何更新KDB表中的相关值

提问于
浏览
2

我正在努力寻找一种有效的方法来更新列值 fv ,当它取决于其他一些列 sAAsBB 的先前值时 . 反过来需要使用新计算的 fv 版本更新当前日期,然后可以计算下一个 fv ,依此类推 .

为了说明这个问题,请考虑一个简单的例子:假设我有一张某些股票的价格表 AABB ,以及权重 wAAwBB ,每个交易日期 td . 此外,我有一个基金 Value fv 和股份拥有列 sAAsBB .

q)t:([] td:2001.01.01 2001.01.02 2001.01.03 2001.01.04 2001.01.05 2001.01.06; 
AA:121.5 125.0 127.0 126.0 129.2 130.0; 
BB:111.0 115.3 117.0 116.0 119.2 120.0; 
wAA: 0.2 0.2 0.3 0.4 0.5 0.9; 
wBB: 0.8 0.8 0.7 0.6 0.5 0.1; 
fv:100000 0N 0n 0n 0n 0n;
sAA: 0n; sBB: 0n;)

(Roundtrip: 000ms)
::

q) t

td          AA      BB      wAA     wBB     fv       sAA   sBB
2001.01.01  121.5   111     0.2     0.8     100000    0n    0n
2001.01.02  125     115.3   0.2     0.8     0n        0n    0n
2001.01.03  127     117     0.3     0.7     0n        0n    0n
2001.01.04  126     116     0.4     0.6     0n        0n    0n
2001.01.05  129.2   119.2   0.5     0.5     0n        0n    0n
2001.01.06  130     120     0.9     0.1     0n        0n    0n

基金 Value 从日期到日期变化,并设置为第一个初始日期( td(0) )的1,000,000,但其余部分未知 . 要计算 fv 除了第一行之外的任何其他行: AA*(prev sAA) + BB*(prev sBB) ,即取决于之前的 sAAsBB 值 .

对于所有日期, sAAsBB 都设置为 0n ,并计算为(伪代码) sAA : fv * wAA % AA . 对于第一行,这很好,因为 fv(0) 是已知的 . 但是对于连续的行,我遇到了问题,因为KDB / Q按列顺序操作,并且更新的内联执行不会更新表直到结束 . 因此 sAAsBB 仍为 0n ,连续 fv 值也是如此 .

最终产品看起来应该类似于:

td          AA     BB     wAA    wBB    fv         sAA        sBB
2001.01.01   121.5  111    0.2    0.8    100000     164.6091   720.7207
2001.01.02   125    115.3  0.2    0.8    103675.2   165.8804   719.3425
2001.01.03   127    117    0.3    0.7    105229.7   248.574    629.5792
2001.01.04   126    116    0.4    0.6    104344.3   331.2519   539.7121
2001.01.05   129.2  119.2  0.5    0.5    107177.4   414.7732   449.5696
2001.01.06   130    120    0.9    0.1    107885.7   746.9007   89.90472

什么是从起点 t 到上面的终点的有效方法?如果您重新构建数据,那么我会欣赏一两行解释(我应该能够遵循其他代码) .

虽然我已经解决了它(我在下面包含了我的解决方案,但可能是可耻的),我的数据以及在某种程度上我自己的想法正在遭受经典的"short and fat"和"row by row"思考和方法(Q中的错误形式) . 因此,我的解决方案不可扩展或易于维护,多次计算相同的值,多次遍历数据,使用"global"变量和其他不良代码 . 在到达下面之前我已经尝试了一些其他的东西,例如在同一个语句中执行更新 fvsAAsBB 的更新语句,但是因为KDB在列上没有更新 sAAsBB ,然后移动到下一个 fv .

我当前和糟糕的解决方案(想象一下添加另外100或1000股的开销......不是真正有利于使用任何人的时间):

t:([] td:2001.01.01 2001.01.02 2001.01.03 2001.01.04 2001.01.05 2001.01.06; 
AA:121.5 125.0 127.0 126.0 129.2 130.0; 
BB:111.0 115.3 117.0 116.0 119.2 120.0; 
wAA: 0.2 0.2 0.3 0.4 0.5 0.9; 
wBB: 0.8 0.8 0.7 0.6 0.5 0.1; 
fv:100000 0N 0n 0n 0n 0n;
sAA: 0n;
sBB: 0n)
t

kt:`td xkey t
// Calculate the first row of shares owned
kt:update sAA:fv*wAA%AA, sBB:fv*wBB%BB from kt
kt

// Global variables for previous shares owned
gPrevSAA:1.0
gPrevSBB:1.0

// Function to calclate the FV. If any of the previous shares owned paraeters are
// null then use the global parameters.
calcFV:{[fv;pSAA;pxA;pSBB;pxB]
    // The first time calcFV is called, pSAA will be defined. The remainder it will be null.
    $[pSAA=0n;pSAA:gPrevSAA;pSAA:pSAA];
    $[pSBB=0n;pSBB:gPrevSBB;pSBB:pSBB];

    // Calculate the fund value
    uFV:-1;
    $[fv=0n;uFV:(pSAA*pxA)+(pSBB*pxB);uFV:fv];

    // update global values
    $[pSAA<>0n;`gPrevSAA set pSAA;];
    $[pSBB<>0n;`gPrevSBB set pSBB;];
    uFV
}

// Calculate the fund values
kt:update fv:calcFV ' [fv;prev sAA;AA;prev sBB;BB] from kt

// Update the shares owned columns with the newly calcualted fund values
kt:update sAA:fv*wAA%AA, sBB:fv*wBB%BB from kt

1 回答

  • 3

    认为你必须用一个来做这个http://code.kx.com/q/ref/adverbs/#over

    q)t:([] td:2001.01.01 2001.01.02 2001.01.03 2001.01.04 2001.01.05 2001.01.06; AA:121.5 125.0 127.0 126.0 129.2 130.0; BB:111.0 115.3 117.0 116.0 119.2 120.0; wAA: 0.2 0.2 0.3 0.4 0.5 0.9; wBB: 0.8 0.8 0.7 0.6 0.5 0.1; fv:100000 0N 0n 0n 0n 0n;sAA: 0n; sBB: 0n)
    q)({update fv:fv^(AA*prev sAA) + BB*prev sBB,sAA:fv*wAA%AA,sBB:fv*wBB%BB from x}/)t
    td         AA    BB    wAA wBB fv       sAA      sBB
    ---------------------------------------------------------
    2001.01.01 121.5 111   0.2 0.8 100000   164.6091 720.7207
    2001.01.02 125   115.3 0.2 0.8 103675.2 165.8804 719.3425
    2001.01.03 127   117   0.3 0.7 105229.9 248.5745 629.5804
    2001.01.04 126   116   0.4 0.6 104351.7 331.2753 539.7503
    2001.01.05 129.2 119.2 0.5 0.5 107139   414.6246 449.4086
    2001.01.06 130   120   0.9 0.1 107830.2 746.517  89.85852
    

    虽然通知值与您的示例答案略有不同,但不确定原因

相关问题