I am trying to implement a vanilla European option pricer with Monte Carlo using R. In the following there is my code for pricing an European plain vanilla call option on non dividend paying stock, under the assumption that the stock follows a GBM.
For teaching reasons, I have used both the analytic formula and the Euler-Maruyama approximation.
However, comparing the obtained results with those of B&S model, I found a quite big difference, therefore I would like to ask you if you can spot the mistake in my Monte Carlo code:
# Compute the Black-Scholes European option price on non-dividend paying stock
# Setting the B&S parameters value
S <- 52 #stock price at time t
K <- 50 #strike price
tau <- 0.25 #time to maturity T - t (in years) #0.25 = 3 months
r <- 0.05 #risk-free annual interest rate
sigma <- 0.3 #annual volatility of the stock price (standard deviation)
#call B&S fair value
d1 <- (log(S/K) + (r + 0.5*sigma^2)*tau)/(sigma*sqrt(tau))
d2 <- d1 - sigma*sqrt(tau)
V_BS_Call <- S*pnorm(d1) - K*exp(-r*(tau))*pnorm(d2) #fair value call
# Compute the Monte Carlo European option price on non-dividend paying stock
# Assuming the non- dividend paying stock follows a Geometric Brownian Motion (GBM)
set.seed(2503) #set the seed
# Setting the Monte Carlo simulation and GBM parameters
tau <- tau #time to expiry (we have already defined this variable)
N <- 250 #number of sub intervals
dt <- tau/N #length of each time sub interval
time <- seq(from=0, to=tau, by=dt) #time moments in which we simulate the process
length(time) #it should be N+1
nSim <- 10000 #number of simulations (paths)
r <- r #GBM parameter 1
sigma <- sigma #GBM parameter 2
X0 <- S #initial condition (price of the underlying today)
#Monte Carlo with analytic formula
Z <- matrix(rnorm(nSim*N, mean=0, sd=1),nrow = nSim, ncol = N) #standard normal sample of N elements
dW <- Z*sqrt(dt) #Brownian motion increments (N increments)x nSim simulations
W <- matrix(numeric(nSim*(N+1)), nrow = nSim, ncol = (N+1))
X_analytic <- numeric(nSim)
for(k in 1:nSim){
W[k,] <- c(0, cumsum(dW[k,]))
X_analytic[k] <- X0*exp((r - 0.5*sigma^2)*tau + sigma*W[k,ncol(W)]) #Analytic solution
}
payoff_expiry_call <-pmax(X_analytic-K,0) #pmax preserve the dimension of the matrix, so apply the max function to each element
expected_payoff_call <- sum(payoff_expiry_call)/length(payoff_expiry_call)
Monte_Carlo_call_price <- exp(-r*(tau))*expected_payoff_call
#Monte Carlo with Euler-Maruyama scheme
X_EM <- matrix(numeric(nSim*(N+1)), nrow = nSim, ncol = (N+1))
X_EM[,1] <- X0 #first element of X_EM is X0. with the for loop we find the other N elements
for(k in 1:nSim){
for(i in 2:ncol(X_EM)){
X_EM[k,i] <- X_EM[k,i-1] + r*X_EM[k,i-1]*dt + sigma*X_EM[k,i-1]*dW[k,i-1]
}
}
payoff_expiry_call <-pmax(X_EM[,ncol(X_EM)]-K,0) #pmax preserve the dimension of the matrix, so apply the max function to each element
expected_payoff_call <- sum(payoff_expiry_call)/length(payoff_expiry_call)
Monte_Carlo_call_price <- exp(-r*(tau))*expected_payoff_call
So, using a 10,000 simulations:
the Monte Carlo price with analytical formula is approximately 4.535
the Monte Carlo price using Euler-Maruyama is approximately 4.536
the B&S price is 4.519
I think that the difference is too big, but I cannot spot the mistake.