如何更新 KDB 中的依赖值 table

How to update dependent values in KDB table

我正在努力寻找一种有效的方法来更新列值 fv,因为它依赖于其他一些列 sAAsBB 的先前值。这些又需要用当前日期新计算的 fv 版本更新,然后可以计算下一个 fv,依此类推。

为了说明问题,考虑一个简单的例子:假设我有一些股票 AABB 的一些价格的 table,以及权重 wAA wBB,每个交易日 td。此外,我有一个基金价值 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

基金价值从日期到日期都在变化,例如,第一个初始日期 (td(0)) 设置为 1,000,000,但其余时间未知。要计算除第一行以外的任何其他行的 fvAA*(prev sAA) + BB*(prev sBB),即取决于先前的 sAAsBB 值..

所有日期的 sAAsBB 都设置为 0n 并计算为(伪代码)sAA : fv * wAA % AA。对于第一行,这很好,因为 fv(0) 是已知的。然而,对于连续的行,我遇到了问题,因为 KDB/Q 按列顺序运行,并且更新的内联执行不会更新 table 直到结束。因此 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 在列上工作时它不会'在进入下一个 fv.

之前更新 sAAsBB

我当前的糟糕解决方案(想象一下再添加 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

认为你必须使用 an over 才能做到这一点 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

尽管注意值与您的示例答案略有不同,但不确定原因