Python 蒙特卡罗模拟中我的RNG中的某个地方出错?

Python 蒙特卡罗模拟中我的RNG中的某个地方出错?,python,numpy,random,montecarlo,quantitative-finance,Python,Numpy,Random,Montecarlo,Quantitative Finance,所以,对于一个蒙特卡罗类,我创建了一个统一的随机数生成器来模拟正态分布,并将其用于MC期权定价,我在某些地方犯了严重的错误。它使用一个简单的线性同余生成器(lcg),生成一个随机向量,该向量被输入到逆正态分布的数值近似(beasley-springer-morrow算法)中,以生成标准正态分布值(可以找到精确过程的详细说明) 这是到目前为止我的代码 Rng: 逆法线逼近器: def bsm_algorithm(u): # These are my necessary initial c

所以,对于一个蒙特卡罗类,我创建了一个统一的随机数生成器来模拟正态分布,并将其用于MC期权定价,我在某些地方犯了严重的错误。它使用一个简单的线性同余生成器(lcg),生成一个随机向量,该向量被输入到逆正态分布的数值近似(beasley-springer-morrow算法)中,以生成标准正态分布值(可以找到精确过程的详细说明)

这是到目前为止我的代码

Rng:

逆法线逼近器:

def bsm_algorithm(u):

    # These are my necessary initial constants
    a0 = 2.50662823884; a1 = -18.61500062529; a2 = 41.39119773534; a3 = -25.44106049637;

    b0 = -8.47351093090; b1 = 23.08336743743; b2 = -21.06224101826; b3 = 3.13082909833;

    c0 = 0.3374754822726147; c1 = 0.9761690190917186; c2 = 0.1607979714918209; c3 = 0.0276438810333863;
    c4 = 0.0038405729373609; c5 = 0.0003951896511919; c6 = 0.0000321767881768; c7 = 0.0000002888167364;
    c8 = 0.0000003960315187;

    x = [0]*len(u)
    for i in range(len(u)):
        y = u[i] - 0.5
        if abs(y) < 0.42:
            r = y**2
            x[i] = y*(((a3*r+a2)*r+a1)*r+a0)/((((b3*r+b2)*r+b1)*r+b0)*r+1)
        else:
            r = u[i]
            if y > 0:
                r = 1 - u[i]
            r = log(-log(r))
            x[i] = c0+r*(c1+r*(c2+r*(c3+r*(c4+r*(c5+r*(c6+r*(c7+r*c8)))))))
            if y < 0:
                x[i] = -x[i]

    return x

和期权定价函数:

def LookbackOP(S,K,r,sigma,intervals,sims,Call_Put=1):

    ## My objects that will determine the option prices.
    path = [0]*intervals
    values = [0]*sims

    ## Objects to hold the random nums used for simulation.
    randuni = [0]*sims
    randnorm = [0]*sims
    for i in range(sims):
        randuni[i] = lcrm_generator(intervals,301,i,21)
        randnorm[i] = bsm_algorithm(randuni[i]) 

    # Generating the simulation one by one.
    for i in range(sims):
        path[0] = 1

        ## Below is to generate one whole simulated path.

        ################## MY INCORRECT WAY ##################
        for j in range(1,intervals):
            path[j] = path[j-1]*exp((r - .5*sigma**2)*(1/intervals) + sqrt(1/intervals)*randnorm[i][j])

        ################## CORRECT BUILT-IN WAY ##################
            # path[j] = path[j-1]*exp((r - .5*sigma**2)*(1/intervals) + sqrt(1/intervals)*np.random.normal(0,1))

        ## For each separate simulation, price the option either as a call or a put.    
        if Call_Put == 1:
            values[i] = max(S*max(path)-K,0)
        elif Call_Put == 0:
            values[i] = max(K-S*min(path),0)
        else:
            print("Error: You inputted something other than '1 = Call', or '0 = Put'")
    plt.hist(values,bins=30)
    plt.show()

    ## To get expected return of option by takeing their avg.
    option_value = np.mean(values)
    print(option_value)
    return option_value
在最后一段代码中,我指出了我的错误,这似乎可以通过简单地使用numpy的normal rng来修复。使用一个与另一个会产生截然不同的答案,我很想相信numpy而不是我自己,但我的代码看起来很正常,所以我会错在哪里。

首先

a=lcrm_generator(100000,301,"0",21)
这看起来很奇怪-为什么你需要一个角色作为种子?无论如何,这里的表中有好的参数:。但问题不在于LCG,我相信,但你们的高斯分布可能存在系统性差异

我运行代码

from scipy.stats import norm
q = lcrm_generator(100000, 301, "0", 21)
g = bsm(q)

param = norm.fit(g)
print(param)
对于100000、1000000和10000个样本,我的输出是

(0.0009370998731855792, 0.9982155665317061)
(-0.0006429485100838258, 0.9996875045073682)
(-0.0007464875819397183, 1.0002711142625116)
而在1000到10000个样本之间没有任何改善。基本上,对高斯逆函数使用一些近似,这些只是近似的伪影,对此没有什么可做的


我相信Numpy使用的是一种精确的正态抽样方法(我想是Box-Muller)

我对你的伪随机分布和
Numpy.randon.normal
做了一些视觉比较,后者似乎有点尖锐。也许他们并不完全平等?我还尝试使用
numpy.random.rand
生成数字,然后使用
bsm_算法
获得正态分布。它看起来更像是
numpy.random.normal
1,这让我怀疑您的rng没有正确、均匀的分布。因为我对MC期权定价一无所知,所以我不能对最终结果说任何话。这就是我所担心的,不知何故,数据有点不正常。我想我必须阅读更多关于为lcg rng选择正确常数的数学知识,因为我听说你需要选择正确的常数使其工作,但我从未相信它会产生巨大的影响。我只是重新运行了与你相同的测试,除了使用
np.random.normal(0,1)
,随着样本的增加,参数变得更加精确,所以这一定是BSM算法的一个问题。这让我有些焦虑,谢谢你告诉我应该如何测试我的代码以找出问题所在。@coulio2654不客气。在SciPy和Statsmodels中还有更多的测试(Komogorov Smirnov等)
from scipy.stats import norm
q = lcrm_generator(100000, 301, "0", 21)
g = bsm(q)

param = norm.fit(g)
print(param)
(0.0009370998731855792, 0.9982155665317061)
(-0.0006429485100838258, 0.9996875045073682)
(-0.0007464875819397183, 1.0002711142625116)