“直播”流的简单移动平均线 - 快速实施

jav*_*red 4 c++ algorithmic-trading

在我的交易应用程序中,我有股票价格的“实时报价”。我需要维持 SMA。假设我想要 20 根蜡烛的 SMA,其中每根蜡烛的持续时间为 10 秒。这意味着

每 10 秒我就有一个“检查点”,其中:

  1. 我“关闭”当前蜡烛并存储最后 10 秒的平均价格。平均值为(最大值 - 最小值)/2
  2. 我“启动”新蜡烛并存储最后的价格。
  3. 我清理“过时的”蜡烛。

每一个刻度:

  1. 我更新当前“形成”蜡烛的“最后”价格并重新计算 SMA。

因此,在任何价格变动时我都需要“重新计算”SMA。在大多数情况下,只有最后一根蜡烛的价格发生变化(因为我们使用最后的价格)。每 10 秒一次,我需要多一点额外的工作 - 我需要“忘记”过时蜡烛的平均值,并“存储”“刚刚创建”蜡烛的平均值。

您能建议如何以最低的延迟实现这一点吗?低延迟是首要要求。

hnk*_*hnk 5

我不确定这是否是您正在寻找的方法,但这里是非常快速的 SMA 的伪代码。

简单移动平均线:

我假设您的数据以某种流的形式出现并存储在连续的内存位置(至少具有连续的可映射地址)

x[1] to x[2000] contain the first 2000 data points

// they don't have to be a real array, could just be a function which manages
// a 'circular' array and maps the 'locations' to real locations in memory.
// Either case, it's small enough to be fully in the cache hopefully
//
// Subsequent prices will be accessible in 'locations x[2001], etc.
// Here we are looking to calculate the MA over the latest 2000 ticks

MA2000(1,2000) = (x[1] + x[2] + ... + x[2000]) / 2000 // Usual average
                                                      // Done only once

MA2000(2,2001) = MA2000(1,2000) * 2000 + x[2001] - x[1]
MA2000(2,2001) /= 2000
Run Code Online (Sandbox Code Playgroud)

这样,通过两次加法和一次乘法(使用 1/2000 ),您可以为新的报价生成后续移动平均线。

指数移动平均线: 这是一个不错的选择,如上所述:

// For an N-day EMA
Alpha = 2 / (N+1)      // one time calculation

EMA(new) = Alpha * NewTickPrice + (1-Alpha) * EMA(old)
Run Code Online (Sandbox Code Playgroud)

这里它并不是真正的 N 日移动平均线。它只是一个加权移动平均线,最近 N 天的权重约为 87%,因此几乎 N 天更像是这样。

编译器优化注意事项:

请注意,打开 SSE 或 AVX 选项(如果可用)将大幅加速这些算法,因为可以在单个 CPU 周期内进行多个计算。