In [ 25 ]: def srd_exact():
x2 = np.zeros((M + 1 , I))
x2[ 0 ] = x0
for t in range( 1 , M + 1 ):
df = 4 * theta * kappa / sigma ** 2
c = (sigma ** 2 * ( 1 - np.exp(-kappa * dt))) / ( 4 * kappa)
nc = np.exp(-kappa * dt) / c * x2[t - 1 ]
x2[t] = c * npr.noncentral_chisquare(df, nc, size=I)
return x2
x2 = srd_exact()
Figure 10-9 shows the output of the simulation with the exact scheme as a histogram:
In [ 26 ]: plt.hist(x2[- 1 ], bins= 50 )
plt.xlabel(‘value’)
plt.ylabel(‘frequency’)
plt.grid(True)
Figure 10-9. Simulated square-root diffusion at maturity (exact scheme)
Figure 10-10 presents as before the first 10 simulated paths, again displaying the negative
average drift and the convergence to :
In [ 27 ]: plt.plot(x2[:, : 10 ], lw=1.5)
plt.xlabel(‘time’)
plt.ylabel(‘index level’)
plt.grid(True)
Figure 10-10. Simulated square-root diffusion paths (exact scheme)
Comparing the main statistics from the different approaches reveals that the biased Euler
scheme indeed performs quite well when it comes to the desired statistical properties:
In [ 28 ]: print_statistics(x1[- 1 ], x2[- 1 ])
Out[28]: statistic data set 1 data set 2