Почему VBA вычисляет по-разному в зависимости от того, находится ли значение в массиве или нет? - PullRequest
0 голосов
/ 13 января 2019

В Excel VBA я создал код для моделирования некоторых цен, основанный на каком-либо параметре, но один из параметров дает совершенно разные результаты моделирования, когда он исходит из массива, а не из переменной, которую я не могу понять (значения «Медь» становится слишком отрицательной в нескольких прогонах при использовании массива).

Версия с использованием массива:

'Calculate Price Matrix
For j = 1 To Years
    'For each Commodity
    For i = 1 To N
        'Generate Correlated Brownian Motions
        For k = 1 To i
            dW(i) = dW(i) + A(i, k) * 0.5
        Next k

        'Calculate Price for year
        S(i) = Exp(-Lambda(i)) * S(i) + (1 - Exp(-Lambda(i))) * Mu(i) + Sigma(i) * Sqr((1 - Exp(-2 * Lambda(i))) / (2 * Lambda(i))) * dW(i)

        'Populate Price in Model
        Sheets("Prices").Cells(i + 1, j + 2).Value = S(i)
    Next i
Next j

Версия с использованием double:

'Calculate Price Matrix
For j = 1 To Years            
    'For each Commodity
    For i = 1 To N
        'Generate Correlated Brownian Motions
        dW = 0.5

        'Calculate Price for year
        S(i) = Exp(-Lambda(i)) * S(i) + (1 - Exp(-Lambda(i))) * Mu(i) + Sigma(i) * Sqr((1 - Exp(-2 * Lambda(i))) / (2 * Lambda(i))) * dW

        'Populate Price in Model
        Sheets("Prices").Cells(i + 1, j + 2).Value = S(i)
    Next i
Next j

При A(1,1)=1 выполнение двух кодов должно дать одинаковый результат для S(1)..., но это не так. Я даже пытался изменить dW(i) = dW(i) + A(i, k) * 0.5 просто на dW(i) = 0.5. Но результаты все еще различаются. Что может вызвать эту проблему?

Надеюсь, у кого-то была такая же проблема раньше. Это какое-то ограничение в MS Excel?

1 Ответ

0 голосов
/ 15 января 2019

Извините за отсутствие информации. Ниже приведен полный код с использованием диапазона для dW ()

Option Explicit
Sub SimulatePrices()
'Variables
    Dim Lambda() As Double
    Dim Sigma() As Double
    Dim Mu() As Double
    Dim Exp1() As Double
    Dim Exp2() As Double
    'Dim dW() As Double
    Dim A() As Double
    Dim S() As Double
    Dim i, j, k, N, Years As Long
'Define Ranges for Price Simulations
    Sheets("DataInput").Select
    N = Range(Cells(1, 1), Cells(1, 1).End(xlDown)).Rows.Count - 1
    Sheets("Prices").Select
    Years = Range(Cells(1, 2), Cells(1, 2).End(xlToRight)).Columns.Count - 1

    ReDim Lambda(1 To N)
    ReDim Sigma(1 To N)
    ReDim Mu(1 To N)
    ReDim S(1 To N)

    ReDim dW(1 To N)
    ReDim A(1 To N, 1 To N)

'Populate Variable Matrices
    Sheets("DataInput").Select

    For i = 1 To N

        'Populate OUP Parmameters
        S(i) = Cells(i + 1, 5)
        Lambda(i) = Cells(i + 1, 2)
        Sigma(i) = Cells(i + 1, 4)
        Mu(i) = Cells(i + 1, 3)

        'Populate Cholesky Matrix
        For j = 1 To N
            A(i, j) = Cells(i + 13, j + 1).Value
        Next j

    Next i

'Calculate Price Matrix
    For j = 1 To Years

        'For each Commodity
        For i = 1 To N

            'Generate Correlated Brownian Motions
             For k = 1 To i
                dW(i) = dW(i) + A(i, k) * MSRndNorm

             Next k

            'Calculate Price for year
                S(i) = Exp(-Lambda(i)) * S(i) + (1 - Exp(-Lambda(i))) * Mu(i) + Sigma(i) * Sqr((1 - Exp(-2 * Lambda(i))) / (2 * Lambda(i))) * dW(i)
            'Populate Price in Model
                Sheets("Prices").Cells(i + 1, j + 2).Value = S(i)
        Next i
Next j
Sheets("Prices").Activate
    Application.Calculation = xlAutomatic
End Sub

Function MSRndNorm() As Double
'Marsaglia-Bray modification of Box-Muller method
Dim U1, U2 As Double
Dim x As Double, y As Double
x = 1.1
While x > 1
U1 = Rnd()
U2 = Rnd()
U1 = 2 * U1 - 1
U2 = 2 * U2 - 1
x = U1 ^ 2 + U2 ^ 2
Wend
y = Sqr(-2 * Log(x) / x)
MSRndNorm = U1 * y
End Function
...