Python中的蒙特卡洛

扬·斯图勒

编辑以包括VBA代码以进行比较

此外,我们知道蒙特卡洛应收敛到的分析值8.021,这使比较更加容易。

Excel VBA根据平均5个蒙特卡洛模拟(7.989、8.187、8.045、8.034、8.075)给出8.067

Python根据5个MC(7.913、7.915、8.203、7.739、8.095)和更大的方差给出了7.973!

VBA代码甚至还不是“那么好”,而是使用了一种相当糟糕的方式来从Standard Normal生成样本!

我正在用Python运行一个超级简单的代码,以通过Monte Carlo为欧式看涨期权定价,而对于10,000个“模拟路径”的融合有多么“糟糕”,我感到惊讶。通常,在C ++甚至VBA中针对此简单问题运行Monte-Carlo时,我会获得更好的收敛性。

我在下面显示代码(该代码摘自教科书“ Python for Finance”,并且在Visual Studio Code中以Python 3.7.7(64位版本)运行):作为示例,我得到以下结果:Run 1 = 7.913,运行2 = 7.915,运行3 = 8.203,运行4 = 7.739,运行5 = 8.095,

诸如此类的结果相差太大,将是无法接受的。如何改善融合???(显然,通过运行更多路径,但正如我所说:对于10,000条路径,结果应该已经收敛得更好):

#MonteCarlo valuation of European Call Option

import math
import numpy as np

#Parameter Values
S_0 = 100.  # initial value
K = 105.    # strike
T = 1.0     # time to maturity
r = 0.05    # short rate (constant)
sigma = 0.2 # vol

nr_simulations = 10000

#Valuation Algo:

# Notice the vectorization below, instead of a loop
z = np.random.standard_normal(nr_simulations)

# Notice that the S_T below is a VECTOR!
S_T = S_0 * np.exp((r-0.5*sigma**2)+math.sqrt(T)*sigma*z)

#Call option pay-off at maturity (Vector!)
C_T = np.maximum((S_T-K),0) 

# C_0 is a scalar
C_0 = math.exp(-r*T)*np.average(C_T) 

print('Value of the European Call is: ', C_0)

我还包括VBA代码,它产生的效果略好(我认为):使用下面的VBA代码,我得到7.989、8.187、8.045、8.034、8.075。

Option Explicit

Sub monteCarlo()

    ' variable declaration
    ' stock initial & final values, option pay-off at maturity
    Dim stockInitial, stockFinal, optionFinal As Double

    ' r = rate, sigma = volatility, strike = strike price
    Dim r, sigma, strike As Double

    'maturity of the option
    Dim maturity As Double

    ' instatiate variables
    stockInitial = 100#

    r = 0.05
    maturity = 1#
    sigma = 0.2
    strike = 105#

    ' normal is Standard Normal
    Dim normal As Double

    ' randomNr is randomly generated nr via "rnd()" function, between 0 & 1
    Dim randomNr As Double

    ' variable for storing the final result value
    Dim result As Double

    Dim i, j As Long, monteCarlo As Long
    monteCarlo = 10000

    For j = 1 To 5
        result = 0#
        For i = 1 To monteCarlo

            ' get random nr between 0 and 1
            randomNr = Rnd()
            'max(Rnd(), 0.000000001)

            ' standard Normal
            normal = Application.WorksheetFunction.Norm_S_Inv(randomNr)

            stockFinal = stockInitial * Exp((r - (0.5 * (sigma ^ 2))) + (sigma * Sqr(maturity) * normal))

            optionFinal = max((stockFinal - strike), 0)

            result = result + optionFinal

        Next i

        result = result / monteCarlo
        result = result * Exp(-r * maturity)
        Worksheets("sheet1").Cells(j, 1) = result

    Next j


    MsgBox "Done"

End Sub

Function max(ByVal number1 As Double, ByVal number2 As Double)

    If number1 > number2 Then
        max = number1
    Else
        max = number2
    End If

End Function
彼得·雷

我认为Python或numpy内部没有任何问题,无论您使用哪种工具,收敛都应该是相同的。我使用不同的样本量和不同的sigma值进行了一些仿真。毫不奇怪,事实证明收敛速度在很大程度上受到sigma值的控制,请参见下图。请注意,x轴在对数刻度上!在较大的振荡消失之后,在稳定之前会有更多较小的波。在sigma = 0.5时最容易看到。看到这张图片

我绝对不是专家,但正如您提到的,我认为最明显的解决方案是增加样本量。很高兴看到C ++或VBA的结果和代码,因为我不知道您对numpy和python函数有多熟悉。也许某事没有按照您认为的去做。

生成绘图的代码(让我们不谈论效率,这太可怕了):

import numpy as np
import matplotlib.pyplot as plt

S_0 = 100.  # initial value
K = 105.    # strike
T = 1.0     # time to maturity
r = 0.05    # short rate (constant)

fig = plt.figure()
ax = fig.add_subplot()
plt.xscale('log')

samplesize = np.geomspace(1000, 20000000, 64)
sigmas = np.arange(0, 0.7, 0.1)
for s in sigmas:
    arr = []

    for n in samplesize:

        n = n.astype(int)

        z = np.random.standard_normal(n)

        S_T = S_0 * np.exp((r-0.5*s**2)+np.sqrt(T)*s*z)


        C_T = np.maximum((S_T-K),0) 


        C_0 = np.exp(-r*T)*np.average(C_T) 


        arr.append(C_0)

    ax.scatter(samplesize, arr, label=f'sigma={s:.2f}')

plt.tight_layout()
plt.xlabel('Sample size')
plt.ylabel('Value')
plt.grid()
handles, labels = ax.get_legend_handles_labels()
plt.legend(handles[::-1], labels[::-1], loc='upper left')
plt.show()

加法

这次,您使用VBA获得了接近真实价值的结果。但是有时候你没有。这里随机性的影响太大。事实是,从低样本数模拟中平均仅得出5个结果是没有意义的。例如,在Python中平均进行50个不同的仿真(只有n = 10000,即使您愿意得到正确的答案也不要这样做),结果为8.025167(置信度为95%的±0.039717),这是非常接近真正的解决方案。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用GPU加速python中的蒙特卡洛仿真

来自分类Dev

蒙特卡洛模拟python

来自分类Dev

蒙特卡洛模拟python

来自分类Dev

R中的蒙特卡洛模拟

来自分类Dev

R中的蒙特卡洛模拟

来自分类Dev

python,乌龟,pi和蒙特卡洛

来自分类Dev

使用降雪的R中并行蒙特卡洛模拟

来自分类Dev

在简单的Java中对Pi进行蒙特卡洛模拟?

来自分类Dev

使用R中的蒙特卡洛模拟股价

来自分类Dev

在Matlab中增加蒙特卡洛的值

来自分类Dev

如何使用蒙特卡洛方法在python中查找球体的体积?

来自分类Dev

蒙特卡洛模拟在Python中连续两个头部的预期投掷

来自分类Dev

蒙特卡洛人口实施

来自分类Dev

了解蒙特卡洛树搜索

来自分类Dev

N骰子的蒙特卡洛模拟

来自分类Dev

$ \ pi $的蒙特卡洛估计

来自分类Dev

python中的蒙特卡洛模拟:使用ipyparallel进行并行化要比序列化花费更长的时间

来自分类Dev

用于基于蒙特卡洛的Pi计算的Python有效矢量化

来自分类Dev

如何绘制随机行走/蒙特卡洛模拟Python的平均值

来自分类Dev

在数个阵列中建立一个。蒙特卡洛法

来自分类Dev

是否有办法从使用R的大型样本蒙特卡洛模拟中确定精确分数?

来自分类Dev

在数个阵列中建立一个。蒙特卡洛法

来自分类Dev

如何在R中构造易于扩展的蒙特卡洛模型

来自分类Dev

MCNP蒙特卡洛模拟的开源替代方案

来自分类Dev

蒙特卡洛模拟无法识别连通图

来自分类Dev

使用蒙特卡洛方法计算n球的体积

来自分类Dev

从甲板上抽牌进行蒙特卡洛扑克模拟

来自分类Dev

使用蒙特卡洛的rand()方法查找“ pi”

来自分类Dev

如何可视化大蒙特卡洛树