如何缓存数据避免重复数据库调用,高效动态计算标准差?
高效计算滚动1000天汇率BPS点差的平均值与标准差
问题概述
需每日为200种货币计算滚动1000天窗口内的BPS点差平均值与标准差,常规每日拉取20万条全量数据的方案成本过高。已实现平均值的动态更新,但标准差计算依赖全量数据,需优化。
现有平均值动态更新逻辑
首次拉取每种货币1000条点差数据并缓存平均值,后续每日通过以下公式更新:
- 移除旧值:
average = ((average * nbValues) - value) / (nbValues - 1); - 添加新值:
average = average + ((value - average) / nbValues);
标准差高效解决方案
无需缓存全量历史数据,只需维护三个核心累计值,结合每日少量数据拉取即可完成动态更新:
核心原理
标准差计算的核心是离均差平方和(SS),可通过以下公式推导:
SS = Σ(xi - μ)² = Σxi² - (Σxi)²/n
其中:
- Σxi:窗口内所有点差的总和(记为
sum_x)- Σxi²:窗口内所有点差的平方之和(记为
sum_x2)- n:窗口内数据点数量(固定为1000)
基于此,平均值μ = sum_x / n,标准差S = sqrt(SS/(n-1))。
具体实现步骤
首次初始化
- 拉取单种货币最近1000天的BPS点差数据
- 计算并缓存三个值:
sum_x = 所有点差的总和 sum_x2 = 所有点差的平方之和 n = 1000 - 记录当前窗口的起始日期(用于后续定位需移除的旧数据)
每日更新流程
- 拉取两个数据:
- 当日该货币的BPS点差(
new_x) - 1000天前该货币的BPS点差(
old_x,即当前窗口要移除的最旧数据)
- 当日该货币的BPS点差(
- 更新累计值:
sum_x = sum_x - old_x + new_x sum_x2 = sum_x2 - old_x * old_x + new_x * new_x - 计算当前窗口的平均值与标准差:
avg = sum_x / n ss = sum_x2 - (sum_x * sum_x) / n std_dev = sqrt(ss / (n-1))
- 拉取两个数据:
优势
- 每日仅需拉取400条数据(200种货币×2条/种),较原方案的20万条数据量骤降99.8%
- 仅需缓存600个数值(200种货币×3个累计值/种),内存占用可忽略
- 计算逻辑简单,无复杂遍历或全量数据依赖
内容的提问来源于stack exchange,提问作者mysteryFruit
相关产品推荐
相关产品推荐

