jeudi 23 septembre 2021

Python - Reduce variability random numbers in MC simulation

I am interested in estimating the price of a European Call Option using the Montecarlo simulation, to get a good approximation of the analytical Black Scholes formula, so a very simple task. Performing the simulation, I have noticed one thing: if I change the seed for the random numbers, I get different results. Is there any procedure that allows me to get the same price, regardless of the chosen seed? (maybe not exactly the same price, but some strategy to reduce the effect of chosen seed).

As we can see from this pictures, here we have the difference in absolute value between the analytical price and estimated one, with different seed. Here we can see that the best seed is the number 100.

enter image description here

Here I have attached the code used to generate the MC simulation for different kind of seed.

from math import log, sqrt, pi, exp
from scipy.stats import norm
from datetime import datetime, date
import numpy as np
import pandas as pd
from pandas import DataFrame

def Option_MC(s0, K, T, j, sigma, r, q, seed):
    Rand = np.random.RandomState()
    Rand.seed(seed)
    S = np.ndarray(shape=(2, j), dtype=np.double)
    S[0] = s0
    Brownian_Motion = Rand.normal(-.5 * sigma * sigma * T, sigma * sqrt(T), (1, j))
    S[1] = S[0] * np.exp(Brownian_Motion)
    P = np.maximum(S[1] - K, 0)
    mean = np.average(P)
    return mean

def d1(S,K,T,r,sigma):
    return (log(S/K)+(r+sigma**2/2.)*T)/(sigma*sqrt(T))
def d2(S,K,T,r,sigma):
    return d1(S,K,T,r,sigma)-sigma*sqrt(T)
def bs_call(S,K,T,r,sigma):
    return S*norm.cdf(d1(S,K,T,r,sigma))-K*exp(-r*T)*norm.cdf(d2(S,K,T,r,sigma))

analytical = []
for i in arrays:
    analytical.append(bs_call(i,1.,1,0,0.5))

arrays = np.linspace(1,1.2,100)
seeds = [1,10,100,1000]
price_tot = []
for seed in seeds:
    price = []
    for i in arrays:
        price.append(Option_MC(i,1.,1,200000,0.5,0,0,seed))
    price_tot.append(price)

for p,seed in zip(price_tot,seeds):
    plt.plot(arrays,abs(np.array(p)-np.array(analytical)),label=f'Seed = {seed}')
plt.legend()
plt.show()

for p,seed in zip(price_tot,seeds):
    plt.plot(arrays,p,label=f'Seed = {seed}')
plt.legend()
plt.show()



Aucun commentaire:

Enregistrer un commentaire