求Kdb中适用于不规则时间序列的EMA函数实现方案
求Kdb中适用于不规则时间序列的EMA函数实现方案
你提到的基于时间差动态调整权重的EMA实现,确实得用到Kdb的三元累加器来搞定,刚好我有个适配这种需求的实现方案,完全对应你说的那个逻辑——也就是根据相邻数据点的时间间隔来计算动态权重,而不是用固定的α值。
核心思路
对于不规则时间序列,EMA的权重不再是固定值,而是基于相邻两个数据点的时间间隔(delta_t)来计算动态α:
α = 1 - exp(-delta_t / τ)
这里的τ是EMA的半衰期(比如你想模拟20分钟的EMA,就把τ设为20分钟对应的时间单位数值,比如如果时间是毫秒,就是20601000)。
具体代码实现
假设你的数据是包含时间列t(timestamp类型)和数值列x的表,我们可以写一个专门的函数:
// 不规则时间序列的EMA计算函数 // 参数说明: // t: 时间列(需为timestamp/timespan类型) // x: 需要计算EMA的数值列 // tau: 半衰期(单位需与t的时间单位一致,比如t是毫秒则tau为毫秒数) emaIrreg:{[t;x;tau] // 计算相邻时间差,第一个数据点补0(不影响初始值) deltas:0, diff t; // 生成每个时间点的动态alpha值 alphas:1 - exp[-deltas%tau]; // 用三元累加器逐行计算EMA:初始值为第一个x,后续值=alpha*当前x + (1-alpha)*前一个EMA ema: {[prevEma; alpha; val] alpha*val + (1-alpha)*prevEma}/[first x]'[alphas;x]; :ema }
使用示例
比如我们有一组时间间隔不规则的测试数据:
// 构造测试表:时间间隔分别为5秒、7秒、3秒的价格数据 testData:([] t:2024.01.01D09:00:00.000 2024.01.01D09:00:05.000 2024.01.01D09:00:12.000 2024.01.01D09:00:15.000; x:100 102 101 103) // 计算半衰期为10秒的EMA(t是毫秒单位,所以tau=10*1000=10000) update emaVal:emaIrreg[t;x;10000] from testData
注意事项
- 确保你的时间列
t已经按时间升序排列,如果没排序,记得先执行testData:asc testData; tau的单位必须和t的时间单位匹配,比如t是秒类型,tau就填秒数;如果是timestamp(毫秒精度),tau就填毫秒数,这样delta_t%tau的计算才是正确的无量纲值;- 第一个数据点的EMA就是它本身,代码里通过给第一个delta补0,让alpha=0,保证初始计算结果正确。
备注:内容来源于stack exchange,提问作者emptydoubleu
相关产品推荐
相关产品推荐

