Uncertain Volatility Model - Option Pricing R code help
Uncertain Volatility Model - Option Pricing R code help
Loading saved threads...
Imran Jabbar · External communityPost link
External question — Quantitative Finance Stack Exchange
Author: Imran Jabbar
Original post: https://quant.stackexchange.com/questions/76496
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
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.
Quote
Report
Alex D · External communityPost link
External answer — Quantitative Finance Stack Exchange
Author: Alex D
Original post: https://quant.stackexchange.com/a/76530
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
Looks like your
L_T_plus
&
L_T_minus
are always zero. Check your implementation.
Quote
Report
Post Reply
Quoted from Forex.com.bd-Editorial External question — Quantitative Finance Stack Exchange Author: Imran Jabbar Source score (net votes, not local likes): 0 Original post: https://quant.stackexchange.com/questions/76496 License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/ Adaptation: HTML converted to plain text; contact email addresses removed. 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.
Checking account access…