我知道使用SQL Server 2012窗口函数和OVER()
子句计算简单移动平均值很容易。但是如何使用这种方法计算指数移动平均线?谢谢!
答案 0 :(得分:9)
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 ...
好的,因为你似乎在EWMA_Chart之后我创建了一个显示如何到达那里的SQL Fiddle。但是,请注意它使用递归CTE,每行返回一次递归。因此,在大数据集上,您很可能会遇到灾难性的表现。递归是必要的,因为每行依赖于之前发生的所有行。虽然您可以使用LAG()
获取所有前面的行,但您无法引用先前的计算,因为LAG()
无法引用自身。
另外,下面附带的电子表格中的公式没有意义。它似乎试图计算EWMA_Chart值,但它失败了。在上面的SQLFiddle中,我包含了一个[Wrong]列,它计算了电子表格计算的相同值。
无论哪种方式,如果你需要在大数据集上使用它,你可能更适合编写游标。
这是在上面的SQLFiddle中进行计算的代码。它引用计算10行移动平均线的vSMA
视图。
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;