The objective of this project is to value a European-style up-and-in put option using Monte Carlo simulation. The pricing routine is implemented in C++ and exposed to R via an Rcpp package.
We assume the underlying follows the geometric Brownian motion under the risk-neutral measure: - Risk-free rate: \(r\) - Volatility: \(\sigma\) - The Monte Carlo estimator is based on simulated discrete-time paths with daily steps (252 steps per year).
The option value is the discounted expectation of the payoff: \[ V_0 \approx e^{-rT} \cdot \frac{1}{N} \sum_{i=1}^{N} \mathrm{Payoff}^{(i)} \]
A European up-and-in put is activated only if the underlying price reaches the barrier level \(L\) at least once before maturity.
Payoff definition:
If \(\max_{0\le t\le T} S_t \ge L\), then \(\Phi_T=\max(K-S_T,0)\)
Otherwise \(\Phi_T=0\)
The pricing function is implemented in the Rcpp package
barrierPutPricer. > Installation code (do NOT run inside this report;
included only for completeness): >
install.packages("barrierPutPricer_0.0.1.tar.gz", repos = NULL, type = "source")
Assignment parameters:
\(S_0=105\), \(K=110\), \(r=0.05\), \(\sigma=0.21\), \(T=0.75\)
Barrier chosen by the author: \(L=120\)
res_base <- barrierPutPricer::price_uai_put_mc(
S0 = 105, K = 110,
r = 0.05, sigma = 0.21,
T = 0.75, barrier = 120,
n_paths = 50000, n_steps = 252,
seed = 123
)
res_base
## $price
## [1] 0.7927712
##
## $stderr
## [1] 0.01435681
##
## $hit_prob
## [1] 0.47976
##
## $n_paths
## [1] 50000
##
## $n_steps
## [1] 252
##
## $barrier
## [1] 120
Estimated price: 0.7928
Standard error: 0.0144
Barrier hit probability: 0.4798
We compute the option price on a grid of volatility \(\sigma\) and maturity \(T\), holding other parameters fixed (\(S_0\), \(K\), \(r\), and \(L\)). This addresses the requirement to analyze how the price depends on \(\sigma\) and \(T\) simultaneously. This addresses the assignment requirement of analyzing price dependence on volatility and maturity.
library(ggplot2)
S0 <- 105
K <- 110
r <- 0.05
barrier <- 120
sigma_vec <- seq(0.10, 0.50, by = 0.05)
T_vec <- seq(0.25, 1.50, by = 0.25)
grid <- expand.grid(sigma = sigma_vec, T = T_vec)
# For speed in the sensitivity plot
n_paths_plot <- 20000
n_steps_per_year <- 252
grid$price <- NA_real_
grid$stderr <- NA_real_
grid$hit_prob <- NA_real_
for (i in seq_len(nrow(grid))) {
sigma_i <- grid$sigma[i]
T_i <- grid$T[i]
n_steps <- as.integer(round(n_steps_per_year * T_i))
res_i <- barrierPutPricer::price_uai_put_mc(
S0 = S0, K = K, r = r,
sigma = sigma_i, T = T_i,
barrier = barrier,
n_paths = n_paths_plot,
n_steps = n_steps,
seed = 123
)
grid$price[i] <- res_i$price
grid$stderr[i] <- res_i$stderr
grid$hit_prob[i] <- res_i$hit_prob
}
head(grid)
## sigma T price stderr hit_prob
## 1 0.10 0.25 0.000000000 0.0000000000 0.01100
## 2 0.15 0.25 0.002276306 0.0008360849 0.07680
## 3 0.20 0.25 0.029057321 0.0030774408 0.17275
## 4 0.25 0.25 0.131606609 0.0073637708 0.26050
## 5 0.30 0.25 0.331688009 0.0132259770 0.33550
## 6 0.35 0.25 0.661471874 0.0206976081 0.39570
p <- ggplot(grid, aes(x = sigma, y = T, fill = price)) +
geom_tile() +
labs(
title = "Up-and-in Put price (MC) vs volatility and maturity",
x = "Volatility (sigma)",
y = "Maturity (T, years)",
fill = "Price"
)
p
### Findings (short): As volatility increases, the option price tends to
increase because the distribution of future prices becomes wider,
increasing the chance of both hitting the barrier and finishing
in-the-money.
As maturity increases, the option price tends to increase because there is more time to hit the barrier and for the put to end in-the-money.
I declare that I followed the Honor Code and that the submitted solution is my own work. I did not cooperate with any other student on this project assignment.