【问题标题】:VBA: function returns #VALUEVBA:函数返回#VALUE
【发布时间】:2019-02-06 15:58:59
【问题描述】:

我有一个允许我通过特定模型为选项定价的子。然后我想构建一个以相同方式执行完全相同操作的函数,但出现错误。一些输入可以是向量,所以我尝试了带括号和不带括号的代码。我还用“应用程序”切换了“Worksheet.function”,但都没有奏效。

Public Function TaylorPrice1(S0 As Double, sigma As Double, wgt As Double, rho As Double, T As Double, Kappa As Double, r As Double, num As Double) As Double

Dim ModS() As Double
Dim Z As Double
Dim i, j, L, k As Double
Dim Sum1, Sum2, Sum3, Sum4, Sum5 As Double
Dim U1, U2, U20, U2st, U2nd, U2rd, mz, vz As Double
Dim a1, a2, a3, B1, B2, c1, c2, c3, c4, d1, d2, d3, d4, z1, z2, z3, y, y1, y2 As Double
Dim py, pyst, pynd, Ny1, Ny2 As Double
Dim Modrho() As Double

'ReDim S0(num), sigma(num), wgt(num), rho(num, num) As Double
ReDim ModS(num) As Double
ReDim Modrho(num, num) As Double
Z = 1

        Sum1 = 0
        Sum2 = 0
        Sum3 = 0
        Sum4 = 0
        Sum5 = 0
        U1 = 0
        U2 = 0
        U20 = 0
        U2st = 0
        U2nd = 0
        U2rd = 0

        For i = 0 To num - 1
            ModS(i) = wgt(i) * S0(i) * Exp(r * T)
            U1 = U1 + ModS(i)
        Next i

        For i = 0 To num - 1
            For j = 0 To num - 1
                Modrho(i, j) = rho(i, j) * sigma(i) * sigma(j) * T
                U2 = U2 + ModS(i) * ModS(j) * Exp((Z ^ 2) * Modrho(i, j))
            Next j
        Next i

        mz = 2 * Log(U1) - 0.5 * Log(U2)
        vz = Log(U2) - 2 * Log(U1)

        For i = 0 To num - 1
            For j = 0 To num - 1
                U20 = U20 + ModS(i) * ModS(j)
                U2st = U2st + ModS(i) * ModS(j) * Modrho(i, j)
                U2nd = U2nd + ModS(i) * ModS(j) * Modrho(i, j) ^ 2
                U2rd = U2rd + ModS(i) * ModS(j) * Modrho(i, j) ^ 3
            Next j
        Next i

        a1 = -(U2st * Z ^ 2) / (2 * U20)
        a2 = 2 * a1 ^ 2 - ((U2nd * Z ^ 4) / (2 * U20))
        a3 = 6 * a1 * a2 - 4 * a1 ^ 3 - ((U2rd * Z ^ 6) / (2 * U20))

        For k = 0 To num - 1
            For j = 0 To num - 1
                For i = 0 To num - 1
                    Sum1 = Sum1 + 2 * (ModS(i) * ModS(j) * ModS(k) * Modrho(i, k) * Modrho(j, k))
                Next i
            Next j
        Next k

        B1 = (Z ^ 4) / (4 * U1 ^ 3) * Sum1
        B2 = a1 ^ 2 - 0.5 * a2

        For L = 0 To num - 1
            For k = 0 To num - 1
                For j = 0 To num - 1
                    For i = 0 To num - 1
                        Sum2 = Sum2 + 8 * (ModS(i) * ModS(j) * ModS(k) * ModS(L) * Modrho(i, L) * Modrho(j, k) * Modrho(k, L))
                    Next i
                Next j
            Next k
        Next L
        Sum2 = Sum2 + 2 * U2st * U2nd
        For L = 0 To num - 1
            For k = 0 To num - 1
                For j = 0 To num - 1
                    For i = 0 To num - 1
                        Sum3 = Sum3 + 6 * (ModS(i) * ModS(j) * ModS(k) * ModS(L) * Modrho(i, L) * Modrho(j, L) * Modrho(k, L))
                    Next i
                Next j
            Next k
        Next L
        For k = 0 To num - 1
            For j = 0 To num - 1
                For i = 0 To num - 1
                    Sum4 = Sum4 + 6 * (ModS(i) * ModS(j) * ModS(k) * Modrho(i, k) * (Modrho(j, k) ^ 2))
                Next i
            Next j
        Next k

        For k = 0 To num - 1
            For j = 0 To num - 1
                For i = 0 To num - 1
                    Sum5 = Sum5 + 8 * (ModS(i) * ModS(j) * ModS(k) * Modrho(i, j) * Modrho(i, k) * Modrho(j, k))
               Next i
            Next j
        Next k

        c1 = -1 * a1 * B1
        c2 = (Z ^ 6 / (144 * U1 ^ 4)) * (9 * Sum2 + 4 * Sum3)
        c3 = (Z ^ 6 / (48 * U1 ^ 3)) * (4 * Sum4 + Sum5)
        c4 = a1 * a2 - 2 / 3 * a1 ^ 3 - a3 / 6

        d1 = 0.5 * (6 * a1 ^ 2 + a2 - 4 * B1 + 2 * B2) - 1 / 6 * (120 * a1 ^ 3 - a3 + 6 * (24 * c1 - 6 * c2 + 2 * c3 - c4))
        d2 = 0.5 * (10 * a1 ^ 2 + a2 - 6 * B1 + 2 * B2) - (128 * (a1 ^ 3) / 3 - a3 / 6 + 2 * a1 * B1 - a1 * B2 + 50 * c1 - 11 * c2 + 3 * c3 - c4)
        d3 = (2 * a1 ^ 2 - B1) - 1 / 3 * (88 * a1 ^ 3 + 3 * a1 * (5 * B1 - 2 * B2) + 3 * (35 * c1 - 6 * c2 + c3))
        d4 = (-20 * (a1 ^ 3) / 3 + a1 * (-4 * B1 + B2) - 10 * c1 + c2)

        z1 = d2 - d3 + d4
        z2 = d3 - d4
        z3 = d4
        y = Log(Kappa)
        y1 = (mz - y) / (Sqr(vz)) + Sqr(vz)
        y2 = y1 - Sqr(vz)
        Ny1 = Application.Norm_S_Dist(y1, True)
        Ny2 = Application.Norm_S_Dist(y2, True)
        py = (1 / (Sqr(2 * Application.Pi() * vz))) * Exp((-((y - mz) ^ 2) / (2 * vz)))
        pyst = py * 1 / (-vz) * (y - mz)
        pynd = mz / vz * pyst + py * (1 / (-vz)) * (1 + y * (-1 / vz) * (y - mz))
        TaylorPrice1 = (U1 * Exp(-r * T) * Ny1 - Kappa * Exp(-r * T) * Ny2) + (Exp(-r * T) * Kappa * (z1 * py + z2 * pyst + z3 * pynd))

End Function

【问题讨论】:

  • 哪一行给出了错误?
  • Dim i, j, L, k As Double 声明了 3 个变体和 1 个双精度(仅 k
  • 尝试将Option Explicit 放在文件的第一行。这将有助于调试。
  • 这是一堆变量,FOR 循环 1 个 UDF。如果你真的需要做所有这些,我会将FOR 循环放在另一个UDF 中并调用它。 第二个选项:如果您告诉我们您实际想要达到的目标是什么(可能是您的工作表的屏幕打印),我们或许可以提出更好的方法

标签: excel vba


【解决方案1】:

您正在尝试将某些函数参数用作数组,但您没有将它们初始化为这样

例如

ModS(i) = wgt(i) * S0(i) * Exp(r * T)

你有wgtSO作为

Public Function TaylorPrice1(S0 As Double, sigma As Double, wgt As Double, rho As Double, T As Double, Kappa As Double, r As Double, num As Double) As Double

在你的函数参数中。这同样适用于

Modrho(i, j) = rho(i, j) * sigma(i) * sigma(j) * T

您可以从所有可能为数组的函数参数中删除As Double,并删除当前已注释的Redim... 行,因为取消注释会立即覆盖参数值。

【讨论】:

    【解决方案2】:

    感谢大家的帮助。我发现了问题。该函数的输入实际上是 Excel 电子表格的单元格范围。但是 VBA 没有将它们识别为数组,所以我不得不转换数组中的范围(代码中的 rho)。由于我还有一个多维数组,我发现范围变量将范围的值存储为原始的一维行。例如,我有一个 14x14 矩阵,那么范围的第 17 个值对应于矩阵的第 2 行第 3 列。我希望这些信息对某人有用。这就是我解决主要问题的方法

    Dim i As Double
    Dim j As Double
    Dim L As Double
    Dim k As Double
    Dim S0() As Double
    Dim sigma() As Double
    Dim wgt() As Double
    Dim rho() As Double
    Dim Modrho() As Double
    Dim ModS() As Double
    ' transofrmo range nei vettori
    Dim cell As Range
    Dim num1 As Long, num2 As Long
    Dim rhodritto() As Double
    num1 = 0
    For Each cell In S0Input
          num1 = num1 + 1
    Next cell
    ReDim S0(num1) As Double
    ReDim sigma(num1) As Double
    ReDim wgt(num1) As Double
    ReDim rho(num1, num1) As Double
    ReDim Modrho(num1, num1) As Double
    ReDim ModS(num1) As Double
    
    
    i = 1
    For Each cell In S0Input
        S0(i) = cell.Value
        i = i + 1
    Next cell
    i = 1
    For Each cell In sigmaInput
        sigma(i) = cell.Value
        i = i + 1
    Next cell
    i = 1
    For Each cell In wgtInput
        wgt(i) = cell.Value
        i = i + 1
    Next cell
    num2 = 0
    For Each cell In rhoInput
       num2 = num2 + 1
    Next cell
    ReDim rhodritto(num2)
    i = 1
    For Each cell In rhoInput
        rhodritto(i) = cell.Value
        i = i + 1
    Next cell
    k = 1
    For i = 1 To num1
        For j = 1 To num1
            rho(i, j) = rhodritto(k)
            k = k + 1
        Next j
    Next i
    

    【讨论】:

      猜你喜欢
      • 2018-10-08
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多