如何使用SQL Server 2012窗口函数计算指数移动平均值

xia*_*982 5 sql sql-server sql-server-2012

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

Seb*_*ine 10

公式为EMA(x):

EMA(x1) = x1
EMA(xn) = α * xn + (1 - α) * EMA(xn-1)

β := 1 - α
这相当于

EMA(xn) = βn-1 * x1 + α * βn-2 * x2 + α * βn-3 * x3 + ... + α * xn

在那种形式下,它很容易实现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 ...
Run Code Online (Sandbox Code Playgroud)

好吧,因为你似乎在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;
Run Code Online (Sandbox Code Playgroud)