J'ai codé un sous-programme dans Access VBA, montré ici pour référence: Lecture en boucle des dates dans strSQL dans Access VBA. C'est comme suit:

Sub SampleReadCurve()

Dim rs As Recordset
Dim iRow As Long, iField As Long
Dim strSQL As String
Dim CurveID As Long
Dim MarkRunID As Long
Dim MaxOfMarkAsofDate As Date
Dim userdate As String

CurveID = 15

Dim I As Integer
Dim x As Date

userdate = InputBox("Please Enter the Date (mm/dd/yyyy)")

x = userdate

For I = 0 To 150

MaxOfMarkAsofDate = x - I


strSQL = "SELECT * FROM VolatilityOutput WHERE CurveID=" & CurveID & " AND MaxOfMarkAsofDate=#" & MaxOfMarkAsofDate & "# ORDER BY MaxOfMarkasOfDate, MaturityDate"

Set rs = CurrentDb.OpenRecordset(strSQL, Type:=dbOpenDynaset, Options:=dbSeeChanges)
If rs.RecordCount <> 0 Then

    rs.MoveFirst

    rs.MoveLast

    Dim BucketTermAmt As Long
    Dim BucketTermUnit As String
    Dim BucketDate As Date
    Dim MarkAsOfDate As Date
    Dim InterpRate As Double

    BucketTermAmt = 3
    BucketTermUnit = "m"
    BucketDate = DateAdd(BucketTermUnit, BucketTermAmt, MaxOfMarkAsofDate)
    InterpRate = CurveInterpolateRecordset(rs, BucketDate)
    Debug.Print BucketDate, InterpRate

End If

Next I


End Function

L'exécution de ce sous-programme calcule une plage de 76 nombres. Je veux prendre ces 76 numéros et les utiliser dans la fonction suivante comme "ZeroCurveInput".

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

    Dim vZeros() As Variant
    vZeros = ZeroCurveInput
    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 = ZeroCurveInput

m = BucketTermAmt

For I = 2 To UBound(vZeros, 1)

    Price1 = Exp(-vZeros(I - 1, 1) * (m / 12))

    Price2 = Exp(-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

J'ai initialement codé cette fonction dans Excel VBA et j'essaye de la porter sur Access VBA. Dans Excel, je viens de lire cette colonne de 76 nombres comme plage et de la dimensionner en tant que variante à stocker sous forme de tableau, puis de l'utiliser dans la fonction. Cependant, je ne peux pas utiliser la propriété range dans Access pour faire quelque chose de similaire et je ne sais pas quoi utiliser à la place.

Comment pourrais-je stocker les nombres sous forme de tableau, puis les transmettre à la fonction?

0
beeba 5 janv. 2016 à 17:19

2 réponses

Meilleure réponse

Vous pouvez également simplement écrire les nombres de SampleReadCurve dans une table, puis parcourir la table comme vous le feriez dans votre tableau. Donc, votre sub changerait à ceci (en passant, est-ce que cela fonctionne? Vous créez un Sub et terminez une fonction ...):

Sub SampleReadCurve()

Dim rs As Recordset
Dim rs2 as Recordset
Dim iRow As Long, iField As Long
Dim strSQL As String
Dim CurveID As Long
Dim MarkRunID As Long
Dim MaxOfMarkAsofDate As Date
Dim userdate As String

CurveID = 15

Dim I As Integer
Dim x As Date

userdate = InputBox("Please Enter the Date (mm/dd/yyyy)")

x = userdate

For I = 0 To 150

MaxOfMarkAsofDate = x - I


strSQL = "SELECT * FROM VolatilityOutput WHERE CurveID=" & CurveID & " AND MaxOfMarkAsofDate=#" & MaxOfMarkAsofDate & "# ORDER BY MaxOfMarkasOfDate, MaturityDate"

Set rs = CurrentDb.OpenRecordset(strSQL, Type:=dbOpenDynaset, Options:=dbSeeChanges)
Set rs2 = CurrentDb.OpenRecordset("MyNewTable")

If rs.RecordCount <> 0 Then

    rs.MoveFirst

    rs.MoveLast

    Dim BucketTermAmt As Long
    Dim BucketTermUnit As String
    Dim BucketDate As Date
    Dim MarkAsOfDate As Date
    Dim InterpRate As Double

    BucketTermAmt = 3
    BucketTermUnit = "m"
    BucketDate = DateAdd(BucketTermUnit, BucketTermAmt, MaxOfMarkAsofDate)
    InterpRate = CurveInterpolateRecordset(rs, BucketDate)
    Debug.Print BucketDate, InterpRate
    rs2.AddNew
    rs2("BucketDate") = BucketDate
    rs2("InterpRate") = InterpRate
    rs2.Update

End If

Next I


End Function

Ensuite, votre fonction EWMA ressemblerait à ceci:

Function EWMA(Lambda As Double) As Double

    Dim Price1 As Double, Price2 As Double
    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 = BucketTermAmt

Set rec = CurrentDB.OpenRecordset("SELECT InterpRate FROM MyNewTable")

I = 2
Do While rec.EOF = False

    Price1 = Exp(-rec("InterpRate")(I - 1, 1) * (m / 12))
    Price2 = Exp(-rec("InterpRate")(I, 1) * (m / 12))
    LogRtn = Log(Price1 / Price2)
    RtnSQ = LogRtn ^ 2
    WT = (1 - Lambda) * Lambda ^ (I - 2)
    WtdRtn = WT * RtnSQ
    SumWtdRtn = SumWtdRtn + WtdRtn
    I = I + 1

Loop

EWMA = SumWtdRtn ^ (1 / 2)

End Function
1
Johnny Bones 14 janv. 2016 à 15:29

Il existe plusieurs façons de procéder, notamment en utilisant un tableau comme vous le suggérez. Si tout ce dont vous avez besoin sont les 76 numéros, vous pouvez le faire en utilisant une collection. L'avantage de la collection est que vous n'avez pas besoin de savoir à l'avance combien d'articles y figureront.

Voici un exemple de travail simple d'utilisation d'une collection:

Sub TestColl()
    Dim TestCollection As Collection
    Set TestCollection = CreateColl()
    LoopThruColl TestCollection
End Sub
Function CreateColl() As Collection
    Dim MyColl As Collection
    Set MyColl = New Collection

    Dim i As Integer
    For i = 1 To 5
        MyColl.Add i * 2
    Next i
    Set CreateColl = MyColl
End Function
Sub LoopThruColl(CollToLoop As Collection)
    Dim i As Integer
    For i = 2 To CollToLoop.Count
        Debug.Print i, CollToLoop.Item(i - 1), CollToLoop.Item(i)
    Next i
End Sub
1
mwolfe02 5 janv. 2016 à 17:42