调整Excel VBA函数以访问VBA

我正在重新访问Excel VBA中的一些旧代码,并试图将其转换为Access VBA。

此代码需要一系列数字(“零”)并计算“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中重现这个相同的function。 此代码引用一个表(“HolderTable”),它由与上述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 

理想情况下,这些应该产生完全相同的数字。 “零”范围和“interpRate”数字是相同的。 我怀疑问题是如何在Access中定义我的数组,但我似乎无法修复它。 两个守则之间是否有不一致之处?

作为参考,我已经附上了Excel电子表格与VBA代码。 http://www.filedropper.com/soewma_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