def EulerDiscretization(x0, cdt, cdw, coeff_dt, y1, coeff_dw, y2, T, ndiv, dim_z): num = 1 dt = T / ndiv dim_x = x0.shape[0] x = np.zeros((dim_x, ndiv + 1)) x[:, 0] = x0 mynormal = nl.NormalDistribution("Polar-Marsaglia", rndom.randint(10, 10 * ndiv)) mynormal.generateNormalDistribution(ndiv * dim_z) ndist = mynormal.getRdmNumbers() sqrt_t = math.sqrt(dt) done = object() z = np.zeros(dim_z) n = next(ndist, done) while (n is not done): k = 0 while (k < dim_z) and (n is not done): z[k] = n k = k + 1 n = next(ndist, done) x[:, num] = x[:, num - 1] + coeff_dt( x[:, num - 1], y1, dt * num, cdt) * dt + coeff_dw( x[:, num - 1], y2, dt * num, z, cdw) * sqrt_t num = num + 1 return x
def mc_stockprice(S0, r, sigma, T, nsims): normal = nl.NormalDistribution() for i in range(1, T + 1): normal.generateNormalDistribution(nsims) z = normal.getRdmNumbers() const_drift = (r - sigma * sigma / 2.0) * i const_sigt = sigma * math.sqrt(i) l_payoff = list( mc_norm_payoff_variancered(const_drift, const_sigt, 0, z)) yield S0 * (np.mean(l_payoff))
def mc_stockpath(S0, r, sigma, T, ndiv, seed=14): ndiv = (int)(ndiv) normal = nl.NormalDistribution("Polar-Marsaglia", seed) normal.generateNormalDistribution(ndiv) dt = T / ndiv const_drift = (r - sigma * sigma / 2.0) * dt const_sigt = sigma * math.sqrt(dt) z = normal.getRdmNumbers() return mc_calc_exp(const_drift, const_sigt, z, S0)
def mc_callprice(S0, X, r, sigma, T): nldist = nl.NormalDistribution("Polar-Marsaglia") nsim = 1000 nldist.generateNormalDistribution(nsim) z = nldist.getRdmNumbers() const_x_s = X / S0 disc = math.exp(-r * T) const_drift = (r - sigma * sigma / 2.0) * T const_sigt = sigma * math.sqrt(T) l_payoff = list(mc_norm_payoff(const_drift, const_sigt, const_x_s, z)) return disc * S0 * (np.mean(l_payoff)), (disc * S0 * np.std(l_payoff, ddof=1) / math.sqrt(len(l_payoff)))
import matplotlib.pyplot as plt ### Question 5 np.seterr(all='raise') ''' (a) Generate 5,000 Uniformly distributed random numbers on [0,1]. ''' n = 5000 lgm2 = rndgen.LGMRandomGenerator(14) lgm2.generateRdmNumber(n) ''' (b) Generate 5,000 Normally distributed random numbers with mean 0 and variance 1, by Box- Muller Method. ''' boxmullernormal = nl.NormalDistribution("Box-Muller") boxmullernormal.generateNormalDistribution(n) nrm1 = list(boxmullernormal.getRdmNumbers()) bins = np.linspace(-10, 10, 1000) plt.hist(nrm1, bins, alpha=0.5) plt.title("Histogram of Normal distribution : Box-Muller Method") plt.xlabel("Random Number") plt.ylabel("Frequency") #plt.show() ''' (c) Compute the empirical mean and the standard deviation of the sequence of numbers generated above of part (b). ''' #print('Q5. b) Mean %f' % nrm1.mean()) #print(' c) Std Deviation %f' % nrm1.std())
def __init__(self, p=-0.7): self.__p = p self.__normal = nl.NormalDistribution("Polar-Marsaglia")
import BlackScholesOptionPrice as bs ## Question 4 ''' a) Estimate the price c of a European Call option on the stock following geometric brownian motion ''' nsim = 10000 sigma = 0.2 r = 0.04 S0 = 88 T = 5 X = 100 nldist = nl.NormalDistribution("Polar-Marsaglia") nldist.generateNormalDistribution(nsim) z = nldist.getRdmNumbers() mc_call = mc.mc_callprice(S0, X, r, sigma, T, z, False) print('Q4. a) European Call Option Price by MC Simulation = %f with std dev = %f' % (mc_call[0], mc_call[1])) ''' Compute the exact value of the option c by the Black-Scholes formula. Now use variance reduction techniques (whichever you want) to estimate the price in part (a) again. Did the accuracy improve? Comment. ''' bsCallPrice = bs.EuropeanCallPrice(S0, X, r, sigma, T) print('Q4. b) Black Scholes Price = %f' % bsCallPrice) # We generate only half random numbers. nsim = nsim/2 nldist = nl.NormalDistribution("Polar-Marsaglia")
done = object() z1 = next(n1, done) z2 = next(n2, done) while (z1 is not done) and (z2 is not done): yield (1 + math.exp(-0.08 * t + sqr_t * (z1 / 3 + 3 * z2 / 4))) z1 = next(n1, done) z2 = next(n1, done) start_time2 = timeit.default_timer() T = 3 sqrt_t = math.sqrt(T) nsims = 10000 normal1 = nl.NormalDistribution("Polar-Marsaglia", 14) normal2 = nl.NormalDistribution("Polar-Marsaglia", 18) normal1.generateNormalDistribution(nsims) normal2.generateNormalDistribution(nsims) n1 = normal1.getRdmNumbers() n2 = normal2.getRdmNumbers() res = wp.mycuberoot(np.asarray(list(myMC(n1, n2, T, sqrt_t)))) res_mean = np.mean(res) res_var = np.var(res, ddof=1) elapsed2 = timeit.default_timer() - start_time2 print( ' b) Expected value of the function E[(1+Y)^(1/3)] = %f with var =%f ****[%f sec]' % (res_mean, res_var, elapsed2))