vbapass-by-valuelvaluebyval

use of ByVal in VBA


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.


Solution

  • 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;