蒙特卡罗模拟不足的可能性 - VBA

时间:2016-05-29 17:52:31

标签: excel vba excel-vba

我正在VBA开展一个项目,根据以下公式确定模拟系列终端股票价格值的不足概率

St = S0e(μ-σ^ 2/2)t +σBt其中Bt是标准布朗运动,如sqrt(t)。

以下是我到目前为止所做的代码和评论

Option Explicit

'The following is a subroutine that generates the random terminal stock prices
'An array is passed into it by reference so that the populated values are available to the caller

Private Sub GenerateRandomTerminalStockPrices(ByVal sNaught As Double, _
                                              ByVal r As Double, _
                                              ByVal sigma As Double, _
                                              ByVal t As Double, _
                                              ByVal nSize As Long, _
                                              ByRef STerminal() As Double)

  Dim i As Long
  Dim Drift As Double
  Dim SigmaSqrtT As Double

  'This creates the drift term of the stock price
  Drift = (r - 0.5 * sigma * sigma) * t

  'This creates the Standard Brownian Motion parameter
  SigmaSqrtT = sigma * (t ^ 0.5)

  'The following creates simulated terminal price values for purposes of Monte Carlo Simulation
  For i = 1 To nSize
    STerminal(i) = sNaught * Exp(Drift + SigmaSqrtT * Excel.WorksheetFunction.NormSInv(Rnd()))
  Next i

End Sub

'Creates the probability of shortfall equation
Function Prshortfall(sNaught As Double, r As Double, sigma As Double, t As Double, n As Double)

  'Creating variables of use in the equation
  Dim i As Long
  Dim V() As Variant
  Dim terminalstockprices() As Double
  Dim probability As Double
  Dim variance As Double
  Dim sum As Double
  Dim squaredvalue As Double
  Dim totalvalue As Double
  Dim riskfree As Double
  Dim ret As Double
  Dim averagevalue As Double

  'Specifying parameters of arrays
  ReDim V(1, 1 To 3) As Variant
  ReDim terminalstockprices(n) As Double

  'Setting initial values to 0 for certain variables
  riskfree = 0.02
  sum = 0#
  squaredvalue = 0#
  totalvalue = 0#


  'Generating the terminal values.  Notice that the array is passed by reference
  Call GenerateRandomTerminalStockPrices(sNaught, r, sigma, t, n, terminalstockprices)

  'Tests each terminal stock price in relation to the risk free rate and keeps count if less than risk free rate
  For i = 1 To n
    totalvalue = totalvalue + terminalstockprices(i)
    squaredvalue = squaredvalue + terminalstockprices(i) * terminalstockprices(i)
    ret = (terminalstockprices(i) / sNaught) - 1
    If ret < riskfree Then
      sum = sum + 1
    End If
  Next i

  'Solves for probability, average price, and price variance based on the outcome of simulation
  probability = sum / n
  averagevalue = totalvalue / n
  variance = (squaredvalue - averagevalue * sum) / (n - 1)

  'Outputs the probability, average price, and price standard error
  V(1, 1) = probability
  V(1, 2) = averagevalue
  V(1, 3) = Sqr(variance / n)

  Prshortfall = V

End Function

我使用= prshortfall(100,0.02,0.04,1,100)测试了代码,但只在一个单元格中输出0,而不是我预期的3个概率,平均价格和价格标准误差输出得到。

是否有人对可能存在编码问题或输入错误的位置有任何建议?

3 个答案:

答案 0 :(得分:1)

简单的答案是你需要一个数组来获得输出。

选择B1:D1并输入

=prshortfall(100,0.02,0.04,1,100)

然后CSE它,你有你的号码。

  

需要通过 ctrl + shift + 输入确认数组公式。

enter image description here

修改
我忘记了我改变了行

Prshortfall = V

Prshortfall = Array(probability, averagevalue, Sqr(variance / n))

因此,只有使用2行范围(如A1:B3)时,此解决方案才有效。抱歉:P

答案 1 :(得分:0)

也许它是单元格的格式?

Sub Test()

    Dim a As Variant

    a = Prshortfall(100, 0.02, 0.04, 1, 100)

End Sub

a 包含以下内容:

a contains

您必须抓住 a(1,1) a(1,2) a(1,3)的值)并将它们设置在单元格中。可能需要将这些单元格的格式更改为带有小数位的数字

修改

'Solves for probability, average price, and price variance based on the outcome of simulation
  probability = sum / n
  averagevalue = totalvalue / n
  variance = (squaredvalue - averagevalue * sum) / (n - 1)

  'Outputs the probability, average price, and price standard error
  V(1, 1) = probability
  V(1, 2) = averagevalue
  V(1, 3) = Sqr(variance / n)

  '3 results are in one variable and is the return value
  Prshortfall = V(1, 1) & " " & V(1, 2) & " " & V(1, 3)

End Function

<强>结果

the result in a cell

答案 2 :(得分:0)

在模块顶部添加Option Base 1

或将v行更改为

Dim v(1 to 1,1 to 3)

对不起,我删除了第一个Dim v()As Variant,我的版本中没有Redim。