I am trying to price the following call option using the UVM method in R.
The code I wrote below keeps producing the same price for the min and max volatilities, which is wrong, however, I can't seem to fix this error.
# Market Data
strike_call <- c(150,152.5,155,157.5,160,165,170,172.5,175,177.5,180,182.5,185,187.5,190,192.5,195,197.5,200,202.5,205,207.5,210,212.5,215,217.5,220,222.5,225,227.5,230,232.5,235,245,250)
price_market_call <- c(59.9,57.55,55.05,52.55,50.1,45.1,40.15,37.65,35.15,32.7,30.25,27.6,25.15,22.75,20.35,17.95,15.6,13.3,11.2,9.2,7.45,5.85,4.4,3.2,2.2,1.45,0.92,0.56,0.36,0.23,0.15,0.11,0.07,0.02,0.01)
# UVM Price
UVM_price_call <- function(S, K, T, N, r, sigma_min, sigma_max, upper_price=TRUE) {
delta_t <- T / N
# Initialize WT matrix
WT <- matrix(0, nrow=N+1, ncol=N+1)
for (j in 1:(N + 1)) {
WT[N+1, j] <- max(S - K, 0) # Payoff at maturity
}
# f function as defined
f <- function(x, y, z) {
(1 - sigma_max * sqrt(delta_t)/2) * y + (1 + sigma_max * sqrt(delta_t)/2) * z - 2 * x
}
for (i in N:1) {
for (j in 1:(N+1)) {
L_T_plus <- ifelse(j < N+1, f(WT[i+1, j], WT[i+1, j+1], WT[i+1, j+1]), 0)
L_T_minus <- ifelse(j > 1, f(WT[i+1, j], WT[i+1, j-1], WT[i+1, j-1]), 0)
if (upper_price) {
# UVM Max logic
sigma_used <- ifelse(L_T_plus > 0, sigma_max, ifelse(L_T_minus < 0, sigma_max, sigma_min))
} else {
# UVM Min logic
sigma_used <- ifelse(L_T_plus < 0, sigma_min, ifelse(L_T_minus > 0, sigma_min, sigma_max))
}
WT[i, j] <- WT[i+1, j] + exp(-r * delta_t) * sigma_used * (L_T_plus + L_T_minus)/2
}
}
return(WT[1, 2]) # First time step, second state
}
# Given parameters
sigma_min <- 0.1
sigma_max <- 1.7
N <- 1
S <- 209.68
T <- 4/365
r <- 0.07
# Calculate UVM max and min prices
UVM_max_prices <- sapply(strike_call, function(K) {
UVM_price_call(S, K, T, N, r, sigma_min, sigma_max, upper_price=TRUE)
})
UVM_min_prices <- sapply(strike_call, function(K) {
UVM_price_call(S, K, T, N, r, sigma_min, sigma_max, upper_price=FALSE)
})
# Plot
plot(strike_call, price_market_call, type="l", col="blue", ylab="Option Price",
xlab="Strike", main="Option Price vs. Strike")
lines(strike_call, UVM_max_prices, col="red", lty=2)
lines(strike_call, UVM_min_prices, col="pink", lty=2)
legend("topright", legend=c("Market Price", "UVM Max", "UVM Min"),
col=c("blue", "red", "green"), lty=c(1, 2, 2), cex=0.8)
The approach above is based on the following finite difference approach.
The price of a stock is determined by:
\begin{equation} S(j, n)=S_{0} \mathrm{e}^{(j-n) \cdot \sigma_{\max } \sqrt{\Delta t}+(n-1) \cdot r \Delta t} \end{equation}
When examining an European option with value function ( F(x) ), for a given node ( (j, n) ), the option value is: \begin{equation} F_{n}^{j} = F_{n}(S(j, n)) \end{equation} Using the UVM, the worst-case scenario price for this can be represented as: \begin{equation} W_{n}^{ \pm, j} = \text{Sup or Inf E}\left[ \sum_{k=j+1}^{N} e^{-r(t_{k}-t_{n})} F_{k}(S_{k}) \right] \end{equation} For a trinomial tree structure, the formula is: \begin{equation} W_{n}^{+, j}=F_{n}^{j}+\mathrm{e}^{-r \Delta t} \times \operatorname{Sup}_{p}\left[P_{U}(p) W_{n+1}^{+, j+1}+P_{M}(p) W_{n+1}^{+, j}+P_{D}(p) W_{n+1}^{+, j+1}\right] \end{equation} \begin{equation} W_{n}^{-, j}=F_{n}^{j}+\mathrm{e}^{-r \Delta t} \times \operatorname{Inf}_{p}\left[P_{U}(p) W_{n+1}^{-, j+1}+P_{M}(p) W_{n+1}^{-, j}+P_{D}(p) W_{n+1}^{-, j+1}\right] \end{equation} This is equivalent to the result according to and the BSB equation solutions are represented by $W_{n}^{ \pm, j}$. Therefore, we find $W_{n}$ as: $$ \begin{aligned} & W_{n}^{+, j}=F_{n}^{j}+\mathrm{e}^{-r \Delta t} \begin{cases}W_{n+1}^{+, j}+\frac{1}{2} L_{n+1}^{+, j} & \text { if } L_{n+1}^{+, j} \geqslant 0 \\ W_{n+1}^{+, j}+\frac{\sigma_{\min }^{2}}{2 \sigma_{\max }^{2}} L_{n+1}^{+, j} & \text { if } L_{n+1}^{+, j}<0\end{cases} \\ & W_{n}^{-, j}=F_{n}^{j}+\mathrm{e}^{-r \Delta t}\left\{\begin{array}{cc} W_{n+1}^{-j}+\frac{1}{2} L_{n+1}^{-j} & \text { if } L_{n+1}^{-j}<0 \\ W_{n+1}^{-, j}+\frac{\sigma_{\min }^{2}}{2 \sigma_{\max }^{2}} L_{n+1}^{-j} & \text { if } L_{n+1}^{-, j} \geqslant 0 \end{array}\right. \end{aligned} $$
The parameters are defined as: \begin{aligned} & U=\mathrm{e}^{\sigma_{\max } \sqrt{\Delta t}+r \Delta t} \\ & M=\mathrm{e}^{r \Delta t} \\ & D=\mathrm{e}^{-\sigma_{\max } \sqrt{\Delta t}+r \Delta t} \end{aligned}
The pricing probabilities associated with a singular parameter are expressed as:
\begin{aligned} & P_{U}(p)=p \cdot\left(1-\frac{\sigma_{\max } \sqrt{\Delta t}}{2}\right) \\ & P_{M}(p)=1-2 p \\ & P_{D}(p)=p \cdot\left(\frac{1+\sigma_{\max } \sqrt{\Delta} t}{2}\right) \\ & \frac{\sigma_{\min }^{2}}{2 \sigma_{\max }^{2}} \leqslant p \leqslant 1 / 2 \end{aligned}
By utilising the finite difference approach, we get: \begin{equation} L_{n+1}^{j}=\left(1-\frac{\sigma_{\max } \sqrt{\Delta t}}{2}\right) W_{n+1}^{j+1}+\left(1+\frac{\sigma_{\max } \sqrt{\Delta t}}{2}\right) W_{n+1}^{j-1}-2 W_{n+1}^{j} \end{equation}
The variables $L_{n+1}^{j}$ and $W_{n+1}$ can be either $L_{n+1}^{-, j}$ or $L_{n+1}^{+, j}$, and $W_{n+1}^{-, .}$ or $W_{n+1}^{+, .}$ respectively.
To determine the price range of the portfolio bounded by $W_{0}^{+, 0}$ and $W_{0}^{-, 0}$, we use the method of backward induction. This means that in each step, the value of $W_{n}^{+, j}$ is derived from the values $W_{n+1}^{+, j-1}$, $W_{n+1}^{+, j}$, $W_{n+1}^{+, j+1}$, and other known variables at the time point $t_{n}$. This logic is also applicable for determining $W_{0}^{-, 0}$.
It would be much appreciated if someone could tell me where I have gone wrong.