5

OVER()我知道使用 SQL Server 2012 窗口函数和子句很容易计算简单的移动平均值。但是如何使用这种方法计算指数移动平均线?谢谢!

4

1 回答 1

10

的公式EMA(x)是:

EMA(x 1 ) = x 1 
EMA(x n ) = α * x n + (1 - α) * EMA(x n-1 )

β := 1 - α
相当于

EMA(x n ) = β n-1 * x 1 + α * β n-2 * x 2 + α * β n-3 * x 3 + ... + α * x n

在这种形式下,很容易用LAG. 对于 4 行 EMA,它看起来像这样:

SELECT LAG(x,3)OVER(ORDER BY ?) * POWER(@beta,3) + 
       LAG(x,2)OVER(ORDER BY ?) * POWER(@beta,2) * @alpha + 
       LAG(x,1)OVER(ORDER BY ?) * POWER(@beta,1) * @alpha + 
       x * @alpha
FROM ...

好的,正如您似乎在 EWMA_Chart 之后我创建了一个SQL Fiddle来展示如何到达那里。但是,请注意,它使用的是递归 CTE,每返回一行需要一个递归。因此,在大型数据集上,您很可能会获得灾难性的性能。递归是必要的,因为每一行都取决于之前发生的所有行。虽然您可以获得所有前面的行,LAG()但您也不能引用前面的计算,因为LAG()不能引用自身。

此外,您在下面附加的电子表格中的公式没有意义。它似乎正在尝试计算 EWMA_Chart 值,但它失败了。在上面的 SQLFiddle 中,我包含了一个 [Wrong] 列,它计算的值与电子表格正在计算的值相同。

无论哪种方式,如果您需要在大型数据集上使用它,您可能最好编写一个游标。

这是在上面的 SQLFiddle 中进行计算的代码。它引用vSMA了计算 10 行移动平均值的视图。

WITH

smooth AS(
  SELECT CAST(0.1818 AS NUMERIC(20,5)) AS alpha
),

numbered AS(
  SELECT Date, Price, SMA, ROW_NUMBER()OVER(ORDER BY Date) Rn
  FROM vSMA
  WHERE SMA IS NOT NULL
),

EWMA AS(
  SELECT Date, Price, SMA, CAST(SMA AS NUMERIC(20,5)) AS EWMA, Rn
  , CAST(SMA AS NUMERIC(20,5)) AS Wrong
  FROM numbered
  WHERE Rn = 1
  UNION ALL
  SELECT numbered.Date, numbered.Price, numbered.SMA, 
    CAST(EWMA.EWMA * smooth.alpha + CAST(numbered.SMA AS NUMERIC(20,5)) * (1 - smooth.alpha) AS NUMERIC(20,5)), 
    numbered.Rn
    , CAST((numbered.Price - EWMA.EWMA) * smooth.alpha + EWMA.EWMA AS NUMERIC(20,5))
  FROM EWMA
  JOIN numbered
  ON EWMA.rn + 1 = numbered.rn
  CROSS JOIN smooth
)
SELECT Date, Price, SMA, EWMA
, Wrong
FROM EWMA

ORDER BY Date;
于 2013-04-14T03:59:46.703 回答