2013-04-14 73 views
4

我知道使用SQL Server 2012窗口函數和OVER()子句計算簡單移動平均數很容易。但是,如何使用這種方法計算指數移動平均值?謝謝!如何使用SQL Server 2012窗口函數計算指數移動平均數

+0

請在詢問之前嘗試一下。這裏有一個很好的討論可以使用:http://stackoverflow.com/questions/8871426/how-to-calculate-an-exponential-moving-average-on-postgres – sashkello

+0

我已閱讀你提到的討論。它適用於PostgreSQL,因爲它允許在PostgreSQL中使用SQL創建用戶定義的聚合函數,但在SQL Server中不允許。在SQL Server中使用遞歸CTE是一種可行的方式,但我注意到CTE方式可能會產生比窗口函數更多的表掃描。因此,我發表這篇文章,詢問是否可以使用SQL Server 2012窗口函數來計算指數移動平均線,就像計算簡單移動平均線一樣。 – xiagao1982

+0

@ xiagao1982你有工作嗎?會有興趣看到一個例子。 – RedFilter

回答

7

的公式爲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 ... 

OK,你似乎是我創建了一個SQL Fiddle顯示如何到達那裏後EWMA_Chart。但是請注意,它使用的遞歸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; 
+0

我試圖用[this SqlFiddle](http://sqlfiddle.com/#!6/d736e/1)來實現這個查詢。這些數字看起來相當於Excel計算的相同數據:http://stockcharts.com/school/data/media/chart_school/technical_indicators_and_overlays/moving_averages/cs-movavg.xls 你能看到我出錯的地方嗎? – RedFilter

+1

首先,您計算EMA(SMA(x))而不是EMA(x)。其次,你的「平滑常數」實際上是我的公式中的貝塔值,而不是阿爾法。通過這兩個更改,SQLFiddle看起來像這樣:http://sqlfiddle.com/#!6/19192/1但是,實際結果和預期結果之間還是有一點區別的。我會回去看看他們的EMA定義是否與我所知道的相符。 –

+0

我只是看着你附加的電子表格中的公式,它遠離了標準的EMA定義。我的公式計算最後十行的指數移動平均值。電子表格首先計算最後十行的標準平均值,然後計算所有平均值的無限制指數加權移動平均值。這遵循在這裏的公式:http://en.wikipedia.org/wiki/EWMA_chart –