2015-10-20 160 views
1

我正在嘗試一個相當簡單的函數來計算Excel VBA中的指數加權移動平均波動率following。不過,我認爲我的功能有些錯誤,我無法查明,因爲我沒有得到正確的解決方案。計算指數加權移動平均數

Function EWMA(numbers As Range, Lambda As Single) As Double 

Dim mean As Double 

Dim x As Double 

Dim c As Range 

Dim n As Integer 

mean = WorksheetFunction.Average(numbers) 

n = WorksheetFunction.Count(numbers) 

For Each c In numbers 

    x = x + (Lambda^(n - c.Count)) * ((c.Value - mean)^2) 

Next c 

EWMA = (1 - Lambda) * x 

End Function 

我使用的值與目標揮發度(使用電子表格EWMA計算)是here

我在做什麼錯?

更新:用羅恩·羅森菲爾德的解決方案:

Option Explicit 

Function EWMA(Zero As Range, Lambda As Double) As Double 

    Dim vZero As Variant 
    Dim SumWtdRtn As Double 
    Dim I As Long 
    Dim vPrices As Variant 

    Dim LogRtn As Double, RtnSQ As Double, WT As Double, WtdRtn As Double 

    vZero = Zero 

For I = 2 To UBound(vZero, 1) 

    vPrices = 1/((1 + vZero(I, 1))^(3/12)) 
    LogRtn = Log(vPrices(I - 1, 1)/vPrices(I, 1)) 
    RtnSQ = LogRtn^2 
    WT = (1 - Lambda) * Lambda^(I - 2) 
    WtdRtn = WT * RtnSQ 
    SumWtdRtn = SumWtdRtn + WtdRtn 

Next I 

EWMA = SumWtdRtn^(1/2) 

End Function 
+0

我的猜測是你的一個變量不是它應該是的。添加一個斷點並比較每個變量與它應該是什麼。 –

+0

這實際上是一個比Excel問題更重要的數學問題。您需要向我們展示您期望的值與您獲得的價值,否則您需要等待某人加入數學和Excel解決方案。 –

+0

C.Count將始終爲1.我假設你希望它每次代碼循環時增加1。你需要在循環中添加一個計數器來適應。 –

回答

1

這裏做的VBA函數的一點點不同的方式。輸入是價格數組,假設您按照降序顯示,Lambda。我們希望,該變量的名稱將讓你看到的邏輯:

Option Explicit 
Function EWMA2(Prices As Range, Lambda As Double) As Double 
    Dim vPrices As Variant 
    Dim dSumWtdRtn As Double 
    Dim I As Long 

    Dim dLogRtn As Double, dRtnSQ As Double, dWT As Double, dWtdRtn As Double 

vPrices = Prices 
For I = 2 To UBound(vPrices, 1) 
    dLogRtn = Log(vPrices(I - 1, 1)/vPrices(I, 1)) 
    dRtnSQ = dLogRtn^2 
    dWT = (1 - Lambda) * Lambda^(I - 2) 
    dWtdRtn = dWT * dRtnSQ 
    dSumWtdRtn = dSumWtdRtn + dWtdRtn 
Next I 

EWMA2 = dSumWtdRtn^(1/2) 

End Function 

與您的數據,它給出了相同的結果電子表格計算

(的數據類型的精度範圍內)編輯

如果您想要輸入3M CAD Zero Rates作爲範圍輸入,而不是定價,那麼您可以修改上述內容以根據收益數據計算兩個相關價格。在這種情況下,它將是:

Option Explicit 
Function EWMAV(Zeros As Range, Lambda As Double) As Double 
    Dim vZeros() As Variant 
    Dim dPrice1 As Double, dPrice2 As Double 
    Dim dSumWtdRtn As Double 
    Dim I As Long 

    Dim dLogRtn As Double, dRtnSQ As Double, dWT As Double, dWtdRtn As Double 

vZeros = Zeros 
For I = 2 To UBound(vZeros, 1) 
    dPrice1 = 1/((1 + vZeros(I - 1, 1))^(3/12)) 
    dPrice2 = 1/((1 + vZeros(I, 1))^(3/12)) 

    dLogRtn = Log(dPrice1/dPrice2) 
    dRtnSQ = dLogRtn^2 
    dWT = (1 - Lambda) * Lambda^(I - 2) 
    dWtdRtn = dWT * dRtnSQ 
    dSumWtdRtn = dSumWtdRtn + dWtdRtn 
Next I 

EWMAV = dSumWtdRtn^(1/2) 

End Function 
+0

這個功能完美,比我的解決方案更有效率 - 非常感謝。 – beeba

+0

你會如何建議我改變這個來計算以零利率欄作爲輸入而不是價格欄的平均值? – beeba

+0

我試圖改變它,以便它將零作爲範圍作爲其輸入,然後以零的形式定義vPrices,但這給了我一個錯誤 – beeba