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:
Many thanks in advance.
Try changing this part of interpolateVol
:
Dim vol_minus1, vol_zero, volmin, volmax, vol As Double
To this:
Dim vol_minus1 As Double, vol_zero As Double, volmin As Double, volmax As Double, vol As Double
The issue is that in the original version, only vol
is declared as Double
because it is right next to the word Double
. The other four declarations do not have that Double
applied to them, so they get declared as the Excel VBA default type, which is Variant
. This can be confusing because VBA is not like other languages you might be used to, e.g. C where you can say things like double vol_minus1, vol_zero, volmin, volmax, vol;