在我必须编写的插值方案中,我需要一个最小和最大函数,因此我快速编写了从插值函数中调用的函数Min和Max。它看起来像这样:
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
但是,运行代码会提示“byref参数类型不匹配”错误。事实证明,我必须通过将ByVal添加到函数参数来明确表示我传递值而不是引用:
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
现在我有两个问题:
非常感谢提前。
答案 0 :(得分:3)
尝试更改interpolateVol
的这一部分:
Dim vol_minus1, vol_zero, volmin, volmax, vol As Double
对此:
Dim vol_minus1 As Double, vol_zero As Double, volmin As Double, volmax As Double, vol As Double
问题在于,在原始版本中,只有vol
被声明为Double
,因为它紧挨着Double
这个词。其他四个声明没有应用Double
,因此它们被声明为Excel VBA默认类型,即Variant
。这可能令人困惑,因为VBA与您可能习惯使用的其他语言不同,例如C,你可以说double vol_minus1, vol_zero, volmin, volmax, vol;
答案 1 :(得分:1)
该错误与ByRef
或ByVal
无关;它只是声明a
,b
或两者的类型不正确。例如,如果您这样做:
Public Sub interpolate()
Dim a As String
Dim b As String
a = 1
b = 2
x = Min(a, b)
End Sub
你会得到那个错误,但如果你这样做,你就不会:
Public Sub interpolate()
Dim a As Double
Dim b As Double
a = 1
b = 2
x = Min(a, b)
End Sub
两者之间的区别在于,在第二个中,a
和b
具有Min
函数所期望的类型。
它甚至在该错误中使用术语ByRef
的原因是它只是试图更具体地帮助您找出它所引用的参数。这就像说“看着黑狗”,而不仅仅是“看着狗。”