2016-06-13 116 views
0

我正在重新訪問Excel VBA中的一些舊代碼並嘗試將其轉換爲Access VBA。調整Excel VBA函數以訪問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中重現這個相同的功能。此代碼引用一個表格(「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

+1

難道只是x在您的訪問版本中增加了1倍太多? –

+0

我認爲這可能是可能的,我怎麼能改變它來解決這個問題? – beeba

+1

最簡單的方法是在你的Do ... While循環中添加「x = x - 1」 –

回答

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),你的第二個循環必須be

For I = 2 To x 

而不是For I = 1 To x

+0

非常感謝你,完全解決它。 – beeba

+0

你能否爲我澄清一點? vInterpRate(0)給出數組的第一個元素,vInterpRate(1)給出第二個元素。如果我設置I = 2,是不是我跳過一個元素? – beeba

+0

例如「debug.Print vInterpRate(0)」給出了「0.38」,我可以確認它是數組的第一個元素 – beeba