Accuracy of Monte-Carlo Simulation for Option Pricing

Joined
12/24/08
Messages
8
Points
11
Hi all! I have a question regarding the accuracy of Monte-Carlo simulations for option pricing. I have used the following VBA code to price a plain-vanilla European call option, and then compared the result to the output from the Black-Scholes formula. When I set the time to expiration to 3 years, the simulation result agreed with the analytical value. However, when I set the time to expiration to 8 years, the simulation result was far off from the analytical value. 100,000 iterations were used for the simulations. Could this be an issue with the random number generator provided by VBA? Please let me know if you have any insight into this issue. Thanks, Joe.

'Simulation Parameters (dt = 1/252)
nudt = (rfr - div - 0.5 * sig ^ 2) * dt
sigsdt = sig * Sqr(dt)
'Simulation begins
For i = 1 To sim

St = S0

For j = 1 To Round((T / dt), 0)
z = norm_rnd 'from box-muller
St = St * Exp(nudt + sigsdt * z)

Next j
payoff = comp_max(St - K, 0)
cum_payoff = cum_payoff + payoff * Exp(-rfr * T)

Next i
Worksheets("Sheet1").Range("B10").Value = cum_payoff / sim
 
Sorry i'm a beginner in Vba, here is a matlab code, i think it could help you find the mistake

S0=100; K=100; r=0.06; sig=0.2; T=5; div=0;

dt = 1/252;
nudt = (r - div - 0.5 * sig ^ 2) * dt;
sigsdt = sig * sqrt(dt)
sim=10000;
Si=zeros(1,sim);

drifts=255*T
for i=1:sim
S=S0;
for j=1:drifts;
z=randn(1,1);

S = S* exp(nudt + sigsdt * z);
end
Si(i)=S;
end

payoff = max(Si - K, 0);
cal=mean(payoff) * exp(-r* T)

calbs=blsprice(S0,K,r,T,sig,div) <---B&S

results:

cal = 32.0173


calbs = 31.6150
 
I can't find an error.

For j = 1 To Round((T / dt), 0)
might well be the source of trouble.

For j = 1 To T *252
 
Alfredo,

Thanks for sharing your Matlab code with me. I think my VBA code is doing exactly the same thing. Could you try running the simulation using the following parameters and see if your simulation result agrees with the Black-Scholes formula? S0=158, K=141, r=1.30%, div=2.38%, T=8, sig=73.21%.

Thanks,
Joe
 
Andy and Brastian,

Thanks for the suggestion, but I don't think rounding is the issue here as I have checked it. The difference between the round function in Excel spreadsheet and VBA is that the VBA version uses the banker's rounding (like the round function in Access) while the spreadsheet version uses our typical "normal" rounding. There is only difference (and a minor one) when the digit following the rounding digit is 5.

Regards,
Joe
 
I ran the matlab code and have it very close to the analytical result. Just make sure to change the simulation to 100K instead of 10K and use div in blsprice()

cal =

92.0009


calbs =

91.8954
 
Thanks, Andy. If there is no error in my VBA code and the Matlab code that does essentially the same thing manage to price the call option correctly, this makes me wonder if there is something wrong with VBA random number generator, or the box-muller method in getting univariate standard normal random numbers.
 
There a lot of things that can go wrong

1. RNG is bad, for example rand() is bad
2. The finite difference method is bad (e.g. Euler)
3. The SDE might be 'stiff' (large e-values)
(4. Coding problem)

The books by Kloeden deal with these issues. These issues must be addressed.

Plan B: Compute the Put price (instead of Call) and then use put-call parity. Results are usually better.
 
1. To improve your (pseudo-) random number generator use HotBits generated by radioactive decay.
2. Use refined schemes like the Milstein-method.
 
For software-based and standard RNG, the www.boost.org is a good source. In particular, Mersenne Twister.

Regarding Milstein there are several versions (explicit, implicit) and they are just OK in my experience/opinion. For special problems (e.g. Heston), some special schemes are needed in order to avoid bias.

Here is a 101 code:

#include<iostream>
#include<boost/random.hpp>
#include<boost/random/mersenne_twister.hpp>
#include<boost/random/normal_distribution.hpp>
#include<boost/random/variate_generator.hpp>
#include<ctime>
usingnamespace std;
usingnamespace boost;
int main()
{
static mt19937 rng(static_cast<unsigned> (std::time(0)));
uniform_01<mt19937> gen(rng);
return gen();
}


//
You can download boost from

Boost C++ Libraries Installers for Windows - BoostPro Computing
 
Predictor-corrector schemes are working well in my experience and mind.
 
Predictor-corrector schemes are working well in my experience and mind.

Are you using the Stratonovich formulation?

edit: we have tried a number of schemes for the Heston model; the Andersen QE is the best one to date.

edit2: The PC averaging in both drift and diffusion looks good. Platen and Lei Shi have a nice paper on it.
 
If I finish my paper about this issue, you will get a preprint!
 
Back
Top Bottom