-2
$\begingroup$

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.

X-axis = Value of spot prices in interval [1,1.2]

Y-axis = difference in absolute value between estimated option and analytical one

number of simulation = 200000

K = 1

r = q = 0

sigma = 0.5

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()
$\endgroup$
9
  • 2
    $\begingroup$ What is the x axis? How many MC simulations are you doing? In principle, the best way to reduce simulation error is to increase the number of MC simulations. $\endgroup$
    – D Stanley
    Commented Sep 23, 2021 at 16:04
  • 1
    $\begingroup$ Also there's generally no need to set a "seed" for MC (other than to reproduce results). Why not just use a "random" seed? (typically the generator takes one based on the system clock). $\endgroup$
    – D Stanley
    Commented Sep 23, 2021 at 16:06
  • $\begingroup$ I believe the x axis (i in the code) represents the intial stock price S0, which takes various values from 1 to 1.2. $\endgroup$
    – nbbo2
    Commented Sep 23, 2021 at 16:51
  • $\begingroup$ If the x axis is the spot price, the value above and below the strike should be used. I'm also suspicious that the actual ending values are not being calculated correctly (I see no cumulatve product to indicate a random walk) $\endgroup$
    – D Stanley
    Commented Sep 23, 2021 at 19:07
  • $\begingroup$ @DStanley you are absolutely right, i Have update the question $\endgroup$ Commented Sep 24, 2021 at 7:13

2 Answers 2

2
$\begingroup$

The quickest and easiest (for you, not the computer) is to increase the number of simulations. When I use 1 million sims the error is smaller:

MOre simsulations leads to a smaller error

You can find more sophisticated techniques to reduce variance of your estimate in Glasserman's "Monte Carlo methods in financial engineering". For option pricing you can look at Control Variates and Antithetic Variates, they are relatively easy to implement.

$\endgroup$
0
$\begingroup$

I believe that Python's Rand uses some kind of Linear Congruential Generator to recover "random" numbers.

Think about the random generators as algorithms (deterministic ones) that generate a sequence of numbers in [0, 1]. For example: $$0.0234, \ 0.382, \ 0.375432, \ 0.392, \ 0.785, \ ...$$ Those numbers are then "transformed" (see for example inversion of CDF or AR) to Normal "random" drawings.

Think about the seed as the "starting point" of this [0, 1] sequence. Since the algorithm generating the sequence is deterministic, giving the same seed will result always in the same sequence. Changing the seed, you change the starting point and so the whole sequence. If you change the whole sequence your result will always be different.

What you want to achieve is the Monte Carlo convergence. The greater the number of simulations (not always) the lower the standard error of the samples random variables.

Tip: try to avoid using low seeds. At least 1000+ should be used.

$\endgroup$
8
  • 3
    $\begingroup$ Can you elaborate on why you shouldn’t use low seeds? $\endgroup$
    – Bob Jansen
    Commented Sep 23, 2021 at 19:09
  • $\begingroup$ @BobJansen I agree with you. Yoda and Friends is there exist some methods to control the differences between different seed? $\endgroup$ Commented Sep 24, 2021 at 7:16
  • $\begingroup$ @Bob: This is something I have been told from my instructor. If I recall correctly it has to do with the jump there is between one number and the other. $\endgroup$ Commented Sep 24, 2021 at 8:05
  • $\begingroup$ @John: what do you mean by "control" the difference? $\endgroup$ Commented Sep 24, 2021 at 8:06
  • 1
    $\begingroup$ @YodaAndFriends I don't believe it's true for Python's PRNG. $\endgroup$
    – Bob Jansen
    Commented Sep 24, 2021 at 18:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.