Pregunta

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.

¿Fue útil?

Solución

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;

Otros consejos

That error has nothing to do with ByRef or ByVal; it's simply stating that the type of either a, b, or both is incorrect. For example, if you do this:

Public Sub interpolate()
    Dim a As String
    Dim b As String
    a = 1
    b = 2
    x = Min(a, b)
End Sub

You'll get that error, but if you do this, you won't:

Public Sub interpolate()
    Dim a As Double
    Dim b As Double
    a = 1
    b = 2
    x = Min(a, b)
End Sub

The difference between the two is that, in the second one, a and b are have types that the Min function expects.

The reason that it even uses the term ByRef in that error is that it's just trying to be more specific to help you figure out which argument it's referring to. It's like saying "look at the BLACK dog" instead of just "look at the dog."

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top