2015-10-20 143 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