我正在重新访问Excel VBA中的一些旧代码并尝试将其转换为Access VBA。
此代码采用一系列数字(" Zeros")并计算一个简单的加权平均值,权重为" Lambda"。此计算和此代码工作正常,并已验证为正确。
Excel代码如下。
Option Explicit
Function EWMA(Zeros As Range, Lambda As Double, MarkDate As Date, MaturityDate As Date) As Double
Dim vZeros() As Variant
Dim Price1 As Double, Price2 As Double
Dim SumWtdRtn As Double
Dim I As Long
Dim m As Double
Dim LogRtn As Double, RtnSQ As Double, WT As Double, WtdRtn As Double
vZeros = Zeros
m = Month(MaturityDate) - Month(MarkDate)
For I = 2 To UBound(vZeros, 1)
Price1 = 1 / ((1 + vZeros(I - 1, 1)) ^ (m / 12))
Price2 = 1 / ((1 + vZeros(I, 1)) ^ (m / 12))
LogRtn = Log(Price1 / Price2)
RtnSQ = LogRtn ^ 2
WT = (1 - Lambda) * Lambda ^ (I - 2)
WtdRtn = WT * RtnSQ
SumWtdRtn = SumWtdRtn + WtdRtn
Next I
EWMA = SumWtdRtn ^ (1 / 2)
End Function
现在我尝试在Access VBA中重现这个相同的功能。此代码引用了一个表(" HolderTable"),其中包含与" Zeros"完全相同的数字。上述Excel代码中的范围。在Access中,这些标记为" InterpRate"。然后它应用与Excel代码完全相同的计算,但适用于Access语法。
访问代码如下:
Function EWMA(Lambda As Double) As Double
Dim Price1 As Double, Price2 As Double
Dim vInterpRate() As Variant
Dim SumWtdRtn As Double
Dim I As Long
Dim m As Double
Dim rec As Recordset
Dim LogRtn As Double, RtnSQ As Double, WT As Double, WtdRtn As Double
m = 3
Dim x As Integer
Set rec = CurrentDb.OpenRecordset("SELECT InterpRate FROM HolderTable")
x = 1
Do While rec.EOF = False
ReDim Preserve vInterpRate(x + 1)
vInterpRate(x) = rec("InterpRate")
x = x + 1
rec.MoveNext
Loop
For I = 1 To x
Price1 = 1 / ((1 + vInterpRate(I - 1)) ^ (m / 12))
Price2 = 1 / ((1 + vInterpRate(I)) ^ (m / 12))
LogRtn = Log(Price2 / Price1)
RtnSQ = LogRtn ^ 2
WT = (1 - Lambda) * Lambda ^ (I - 2)
WtdRtn = WT * RtnSQ
SumWtdRtn = SumWtdRtn + WtdRtn
Next I
EWMA = SumWtdRtn ^ (1 / 2)
End Function
理想情况下,这些应该产生完全相同的数字。 " Zeros"范围和" interpRate"数字是相同的。我怀疑问题在于我如何在Access中定义我的数组,但我似乎无法修复它。这两个代码之间是否存在任何不一致之处?
作为参考,我附上了带有VBA代码的Excel电子表格。 http://www.filedropper.com/soewma_1
答案 0 :(得分:1)
恕我直言最好的可读方式是从x = 0开始,并将x = x + 1放在每个循环的开头:
Set rec = CurrentDb.OpenRecordset("SELECT InterpRate FROM HolderTable")
x = 0
Do While rec.EOF = False
x = x + 1
ReDim Preserve vInterpRate(x)
vInterpRate(x) = rec("InterpRate")
rec.MoveNext
Loop
由于你访问vInterpRate(I - 1)
,你的第二个循环必须是
For I = 2 To x
而不是For I = 1 To x
。