During an interpolation scheme I had to write, I needed a minimum and maximum function so I quickly wrote functions Min and Max that are called from within my interpolation function. It looked like this:
Function interpolateVol(Strike As Double, Maturity As Double, coupon As Variant)
Dim i, k, j As Long
Dim timeIndex, strikeIndex As Long
Dim vol_minus1, vol_zero, volmin, volmax, vol As Double
Dim w1, w2 As Double
If coupon = "1M" Then
j = 3
ElseIf coupon = "3M" Then
j = 4
ElseIf coupon = "6M" Then
j = 5
End If
' we set i = 1 as the maturities do not matter for
' picking up the time index
If Maturity <= volatilityCube(1, 1, 2) Then
timeIndex = 1
ElseIf Maturity > volatilityCube(noMaturities, 1, 2) Then
timeIndex = noMaturities
Else
i = 1
While volatilityCube(i, 1, 2) < Maturity
i = i + 1
Wend
timeIndex = i ' volatilityCube(timeIndex-1,2) < Maturity <= volatilityCube(timeIndex,2)
End If
' we set k = 1 as the strikes do not matter for
' picking up the strike index
If Strike <= volatilityCube(1, 1, 1) Then
strikeIndex = 1
ElseIf Strike > volatilityCube(1, noStrikes, 1) Then
strikeIndex = noStrikes
Else
k = 1
While volatilityCube(1, k, 1) < Strike
k = k + 1
Wend
strikeIndex = k ' volatilityCube(strikeIndex-1,1) < Strike <= volatilityCube(strikeIndex,1)
End If
' first we interpolate on the tenors
' as a result we will have two interpolated values:
' one for timeIndex, another for timeIndex + 1
w1 = (Maturity - volatilityCube(timeIndex - 1, 1, 2)) / _
(volatilityCube(timeIndex, 1, 2) - volatilityCube(timeIndex - 1, 1, 2))
w2 = (volatilityCube(timeIndex, 1, 2) - Maturity) / _
(volatilityCube(timeIndex, 1, 2) - volatilityCube(timeIndex - 1, 1, 2))
vol_minus1 = w1 * volatilityCube(timeIndex - 1, strikeIndex - 1, j) + _
w2 * volatilityCube(timeIndex, strikeIndex - 1, j)
vol_zero = w1 * volatilityCube(timeIndex - 1, strikeIndex, j) + _
w2 * volatilityCube(timeIndex, strikeIndex, j)
' Now we have two vols interpolated in time, each for another strike.
' These two vols need to be interpolated in strikes:
volmin = Min(vol_minus1, vol_zero)
volmax = Max(vol_minus1, vol_zero)
w1 = (Strike - volatilityCube(1, strikeIndex - 1, 1)) / _
(volatilityCube(1, strikeIndex, 1) - volatilityCube(1, strikeIndex - 1, 1))
w2 = (volatilityCube(1, strikeIndex, 1) - Strike) / _
(volatilityCube(1, strikeIndex, 1) - volatilityCube(1, strikeIndex - 1, 1))
vol = w1 * volmin + w2 * volmax
interpolateVol = vol
End Function
Function Min(number1 As Double, number2 As Double) As Double
Dim var As Double
If (number1 < number2) Then
var = number1
Else
var = number2
End If
Min = var
End Function
Function Max(number1 As Double, number2 As Double) As Double
Max = number1 + number2 - Min(number1, number2)
End Function
However, running the code prompted the `byref argument type mismatch' error. As it turns out, I had to make explicit that I pass values and not references by adding ByVal to the function arguments:
Function Min(ByVal number1 As Double, ByVal number2 As Double) As Double
Dim var As Double
If (number1 < number2) Then
var = number1
Else
var = number2
End If
Min = var
End Function
Function Max(ByVal number1 As Double, ByVal number2 As Double) As Double
Max = number1 + number2 - Min(number1, number2)
End Function
Now I have two questions about this:
- I find it surprising to discover that I need to make passing by value explicit. In C++, function variables pass by value by default. Should I conclude that VBA passes variables by references as default?
- Why does it help to add Byval to the function arguments? I do not see the relation between types (as the error supposedly is about) and passing by value and/or reference ....
Many thanks in advance.