PDA

View Full Version : MMUlt not working



Bazman
03-18-2010, 03:32 PM
Hi there,

In the following when I try to use the following

CorRands = Fn.MMult(cholesky, rands)

I get the error run-time error 1004 unable to get the MMult property of the WorksheetFunction class.

I assume its because cholesky was read in as a Range from the spredsheet and rands is a VBA array. Can anyone tell me how to fix?



Sub SABRLMM()

Dim fwds, correls, Bm, Cm, hParams, gParams, ffCorrels, vvCorrels, fvCorrels, exps, k, nTsteps, Beta, cholesky As Variant
Dim Fn As Object
Dim nfwds As Integer, numeraire As Integer, i As Integer, j As Integer, alpha As Integer, nfactors As Integer, Nf As Integer, Nv As Integer
Dim dt As Double, T As Double, temp As Double, tau As Double, difFwd As Double, difVvol As Double, rand1 As Double, rand2 As Double, Nsims As Double, X As Double


Set Fn = Application.WorksheetFunction

fwds = Range("fwds").Value
nfwds = UBound(fwds)

Dim mu() As Double
ReDim mu(nfwds)

Dim eta() As Double
ReDim eta(nfwds)

Dim s() As Double
ReDim s(nfwds)

Dim totFwds() As Double
ReDim totFwds(nfwds)

Dim Sumer() As Double
ReDim Sumer(nfwds)

Dim square() As Double
ReDim square(nfwds)

Dim SD() As Double
ReDim SD(nfwds)



Nsims = Range("Nsims").Value
nTsteps = Range("nTsteps").Value
Beta = Range("Beta").Value

correls = Range("correls").Value

'nfactors = Range("correls").Columns.Count


Bm = Range("Bm").Value
Nf = Range("Bm").Columns.Count

Cm = Range("Cm").Value
Nv = Range("Cm").Columns.Count

nfactors = Nf + Nv


Dim rands() As Double
ReDim rands(nfactors - 1)

Dim CorRands() As Double
ReDim CorRands(nfactors)

hParams = Range("hParams").Value
gParams = Range("gParams").Value


ffCorrels = Fn.MMult(Bm, Fn.Transpose(Bm))
vvCorrels = Fn.MMult(Cm, Fn.Transpose(Cm))
fvCorrels = Fn.MMult(Bm, Fn.Transpose(Cm))

exps = Range("exps").Value

dt = 1 / (nTsteps \ exps(nfwds, 1))

correls = Range("correls").Value

numeraire = Range("numeraire").Value

k = Range("k").Value

cholesky = Range("cholesky").Value

Dim strike As Double
strike = 0.05601844

For i = 1 To nfwds
mu(i) = 0
eta(i) = 0
s(i) = 0
totFwds(i) = 0
Sumer(i) = 0
square(i) = 0
SD(i) = 0
Next i


For X = 1 To Nsims


For i = 1 To nfwds
totFwds(i) = fwds(i, 1)
Next i


For T = 0 To exps(nfwds, 1) Step dt


For i = 1 To nfwds

If i > numeraire Then

temp = 0

For alpha = numeraire + 1 To i

tau = exps(alpha, 1) - exps(alpha - 1, 1)

temp = temp + ffCorrels(i, alpha) * (fwds(alpha, 1) ^ Beta * g(exps(alpha, 1), T, gParams) * k(alpha, 1) * tau) / (1 + tau * fwds(alpha, 1) ^ Beta)

Next alpha

mu(i) = temp * (fwds(i, 1) ^ Beta * g(exps(i, 1), T, gParams) * k(i, 1))

ElseIf i = numeraire Then

mu(numeraire) = 0


ElseIf i < numeraire Then

temp = 0

For alpha = i + 1 To numeraire

tau = exps(alpha, 1) - exps(alpha - 1, 1)

temp = temp + ffCorrels(i, alpha) * (fwds(alpha, 1) ^ Beta * g(exps(alpha, 1), T, gParams) * k(alpha, 1) * tau) / (1 + tau * fwds(alpha, 1) ^ Beta)

Next alpha

mu(i) = temp * -(fwds(i, 1) ^ Beta * g(exps(i, 1), T, gParams) * k(i, 1))

End If

Next i


For i = 1 To nfwds

If i > numeraire Then

temp = 0

For alpha = numeraire + 1 To i

tau = exps(alpha, 1) - exps(alpha - 1, 1)

temp = temp + fvCorrels(i, alpha) * (fwds(alpha, 1) ^ Beta * g(exps(alpha, 1), T, gParams) * k(alpha, 1) * tau) / (1 + tau * fwds(alpha, 1) ^ Beta)

Next alpha

eta(i) = temp * h(exps(i, 1), T, hParams)

ElseIf i = numeraire Then

eta(numeraire) = 0


ElseIf i < numeraire Then

temp = 0

For alpha = i + 1 To numeraire

tau = exps(alpha, 1) - exps(alpha - 1, 1)

temp = temp + fvCorrels(i, alpha) * (fwds(alpha, 1) ^ Beta * g(exps(alpha, 1), T, gParams) * k(alpha, 1) * tau) / (1 + tau * fwds(alpha, 1) ^ Beta)

Next alpha

eta(i) = -temp * h(exps(i, 1), T, hParams)

End If

Next i



For i = 1 To nfwds

If totFwds(i) <> 0 Then


s(i) = g(exps(i, 1), T, gParams) * k(i, 1)

For j = 0 To nfactors - 1

rand1 = Rnd()
'rand2 = Rnd()

Do While rand1 = 0
rand1 = Rnd()
Loop


'Do While rand2 = 0
'rand2 = Rnd()
'Loop
rands(j) = Fn.NormInv(rand1, 0, 1)

Next j

CorRands = Fn.MMult(cholesky, rands)
'ffCorrels = Fn.MMult(Bm, Fn.Transpose(Bm))
For j = 1 To Nf

difFwd = Sqr(dt) * correls(i, j) * CorRands(j) 'BoxMuller(Halton(i, 3), Halton(i, 5))

Next j



For j = 1 To Nv


difVvol = Sqr(dt) * correls(nfwds + i, j) * CorRands(Nf + j) 'BoxMuller(Halton(i, 3), Halton(i, 5)) '

Next j

totFwds(i) = totFwds(i) + mu(i) * dt + totFwds(i) ^ Beta * s(i) * difFwd

If totFwds(i) <= 0 Then

totFwds(i) = 0

End If

k(i, 1) = k(i, 1) + eta(i) * dt + h(exps(i, 1), T, hParams) * difVvol

End If


Next i


'mu = h(t, , t, a, b, c, d) *k(1,1)
Next T

For i = 1 To nfwds
Sumer(i) = Sumer(i) + totFwds(i) - strike
square(i) = square(i) + Sumer(i) ^ 2
Next i

Next X



For i = 1 To nfwds
SD(i) = (Sqr(square(i) - (1 / Nsims) * Sumer(i) ^ 2)) / (Nsims - 1)
Next i

For i = 1 To nfwds
Sumer(i) = Sumer(i) / Nsims
Next i

End Sub

p45cal
03-19-2010, 04:02 AM
Some help needed here:
1. What is the shape of the range 'cholesky'? (dimensions/horizontal/vertical)
2. What value does nfactors end up having?

Bazman
03-19-2010, 04:04 AM
Hi there,

Cholesky is 4*4

nfactors is 4 (Nf and Nv both equal 2 in this case)

p45cal
03-19-2010, 04:36 AM
Try:
CorRands = Fn.MMult(cholesky, Fn.Transpose(rands))
BUT:
it will want to make CorRands(1 to 4, 1 to 1) but you've already dimensioned CorRands(0 to 4). Just
Dim CorRands()
instead of:
Dim CorRands() As Double
and don't Redim.

Bazman
03-19-2010, 04:44 AM
OK I ended up just coding the mmuilt with a couple of for loops.

Its currently running and will take a couple of hours!!

However I suspect your solution is correct, I will test it and let you know. Thanks for this

p45cal
03-19-2010, 04:59 AM
Actually, if you wanted just a single dimension array use
CorRands = Fn.Transpose(Fn.MMult(cholesky, Fn.Transpose(rands)))
which will result in Corands(1 to 4), a variant containing an array of doubles.
And if you really want to ReDim first:
Dim CorRands() As Variant
ReDim CorRands(1 To nfactors)
but I don't see the point.

Paul_Hossler
03-19-2010, 04:17 PM
Minor point (OK, two minor points)

1. You should always use Option Explicit at the top of the module to allow VBA to catch typing variable names wrong

2. In


Dim fwds, correls, Bm, Cm, hParams, gParams, ffCorrels, vvCorrels, fvCorrels, exps, k, nTsteps, Beta, cholesky As Variant


the variables that are not explicitly defined will be Variants. SO if you wanted fwds to be a Long or a Double, you should Dim it As Double

That will also help debug since Excel will gag if you try to assign a String to a Long

Paul