Aviso
Gracias por su participación en las encuestas! A partir de la próxima semana voy a empezar con tutoriales de data science también. Voy a intentar, dentro de lo posible, buscar aplicaciones en finanzas de estos temas para los ejemplos.
Intro
En este tutorial vamos a cubrir lo siguiente:
Las griegas
Delta
Gamma
Vega
Theta
Rho
1 Las griegas
Vamos a discutir ahora la sensibilidad de la fórmula de Black-Scholes con respecto a sus diferentes parámetros. Las griegas son las derivadas parciales de la fórmula con respecto a sus diferentes inputs. Para fines de mantener la discusión lo más general posible, vamos a usar el modelo de Merton en este tutorial.
1.1 Delta
Delta (Δ) es la derivada parcial del precio de la opción con respecto al precio de la acción. Podemos ver a continuación que el precio de la opción cambia con respecto al precio de la acción:
# 0. Limpiar la sesión
rm(list=ls())
if (names(dev.cur()) != "null device") {
dev.off()
}
cat("\014")
# 1. Cargar herramientas
source("scripts/herramientas.R")
# 2. Calcular precio de la opción vs. precio de la acción
spot <- seq(0, 200, by = 1)
strike <- 90
t <- 0.5
rf <- 0.06
div <- 0.02
sigma <- 0.35
call <- merton.model(strike, spot, rf, t, sigma, div)
put <- merton.model(strike, spot, rf, t, sigma, div, "p")
par(mar = c(5.1, 4.1, 4.1, 8.1))
plot(spot, call, type = "l", lwd = 2,
main = "Precio de la Opción vs. Precio de la Acción",
ylab = "Opción", xlab = "Acción")
lines(spot, put, lwd = 2, col = "red")
legend("topright", inset = c(-0.3, 0),
legend = c("Call", "Put"),
lty = 1, col = c("black", "red"), lwd = 2,
title = "Opción", box.lty = 0, xpd = TRUE)
A nosotros nos interesa saber qué tanto cambiará el precio de la opción por cada incremento de $1 en el subyacente. Eso nos lo va a dar la delta, que se calcula de la siguiente manera:
donde S : precio de la acción
d : dividend yield de la acción
T : tiempo a expiración
K : strike de la opción
r : tasa libre de riesgo
d1: (ln(S/K) + (r - d + σ^2/2)*T)/(σ*√T)
d2: d1 - σ*√T
σ : volatilidad de la acción
En R podemos implementar estas fórmulas de la siguiente manera:
option.delta <- function(spot, strike, t, rf, div,
sigma, tipo = "c") {
# Calcula la delta de una opción basado en el modelo
# de Merton (1973)
# Se necesita:
# - spot: precio spot del subyacente al momento de valuación
# - strike: strike de la opción
# - t: tiempo (en años) que falta para que expire la opción
# - rf: tasa libre de riesgo (anualizada)
# - div: dividend yield del subyacente
# - sigma: volatilidad (anualizada) del subyacente
# - tipo: "c" (call) o "p" (put)
# Se regresa:
# delta: la derivada del precio de la acción con respecto a
# el precio del subyacente (spot)
tipo = tolower(tipo)
if (!(tipo %in% c("c", "p"))) {
stop("El tipo de la opción es incorrecto.
Elige uno de 'c' (call) o 'p' (put).")
}
d1 <- (log(spot/strike) +
(rf - div + sigma^2/2)*t)/(sigma*sqrt(t))
if (tipo == "c") {
delta <- exp(-div*t)*pnorm(d1)
} else {
delta <- -exp(-div*t)*pnorm(-d1)
}
return(delta)
}
Si suponemos que el precio de la acción está en $100 en este momento y calculamos la delta de las opciones definidas anteriormente, obtenemos lo siguiente:
spot <- 100
call_delta <- option.delta(spot, strike, t, rf, div, sigma)
put_delta <- option.delta(spot, strike, t, rf, div, sigma, "p")
O sea que, por cada dólar que gane la acción, el precio del call subirá 73 centavos y el precio del put bajará 26 centavos. Veamos si es cierto:
call <- merton.model(strike, spot, rf, t, sigma, div)
call_2 <- merton.model(strike, spot + 1, rf, t, sigma, div)
put <- merton.model(strike, spot, rf, t, sigma, div, "p")
put_2 <- merton.model(strike, spot + 1, rf, t, sigma, div, "p")
Las diferencias entre los precios son efectivamente de 73 centavos para los calls y 26 centavos para los puts. No son exactamente iguales porque los valores de delta van cambiando entre $100 y $101 (la delta es una en $100, otra en $100.01, otra en $100.02, etc). Delta es una cantidad que varía de manera continua con el precio de la acción. Veamos eso a continuación:
# 3. Calcular sensitividad delta vs. spot
spot <- seq(0, 200, by = 1)
delta_calls <- option.delta(spot, strike, t, rf, div, sigma)
delta_puts <- option.delta(spot, strike, t, rf,
div, sigma, "p")
plot(spot, delta_calls, ylim = c(-1, 1), type = "l", lwd = 2,
main = "Delta vs. precio de la acción (strike = $90)",
ylab = "Delta", xlab = "Precio de la acción")
lines(spot, delta_puts, lwd = 2, col = "red")
abline(h = 0, col = "lightgray", lty = 2)
legend("topright", inset = c(-0.3, 0),
legend = c("Call", "Put"),
lty = 1, col = c("black", "red"), lwd = 2,
title = "Opción", box.lty = 0, xpd = TRUE)
La delta del call va de 0 a 1 dependiendo de que tan ITM esté. La delta del put va de -1 a 0 dependiendo también de que tan ITM esté la opción.
También va a variar la delta dependiendo del tiempo que falte para expiración:
# 4. Calcular sensitividad delta vs. tiempo a expiración
spot <- 100
call_strike_itm <- 75
call_strike_atm <- 100
call_strike_otm <- 125
t <- seq(0, 1, by = 0.01)
delta_call_itm <- option.delta(spot, call_strike_itm, t, rf,
div, sigma)
delta_call_atm <- option.delta(spot, call_strike_atm, t, rf,
div, sigma)
delta_call_otm <- option.delta(spot, call_strike_otm, t, rf,
div, sigma)
plot(t, delta_call_itm, ylim = c(0, 1),
type = "l", lwd = 2, col = "green",
main = "Delta del call vs. tiempo a expiración",
ylab = "Delta", xlab = "Tiempo a expiración")
lines(t, delta_call_atm, lwd = 2, col = "black")
lines(t, delta_call_otm, lwd = 2, col = "red")
legend("topright", inset = c(-0.3, 0),
legend = c("ITM", "ATM", "OTM"),
lty = 1, col = c("green", "black", "red"), lwd = 2,
title = "Moneyness", box.lty = 0, xpd = TRUE)
put_strike_itm <- 125
put_strike_atm <- 100
put_strike_otm <- 75
delta_put_itm <- option.delta(spot, put_strike_itm, t, rf,
div, sigma, "p")
delta_put_atm <- option.delta(spot, put_strike_atm, t, rf,
div, sigma, "p")
delta_put_otm <- option.delta(spot, put_strike_otm, t, rf,
div, sigma, "p")
plot(t, delta_put_itm, ylim = c(-1, 0),
type = "l", lwd = 2, col = "green",
main = "Delta del put vs. tiempo a expiración",
ylab = "Delta", xlab = "Tiempo a expiración")
lines(t, delta_put_atm, lwd = 2, col = "black")
lines(t, delta_put_otm, lwd = 2, col = "red")
legend("topright", inset = c(-0.3, 0),
legend = c("ITM", "ATM", "OTM"),
lty = 1, col = c("green", "black", "red"), lwd = 2,
title = "Moneyness", box.lty = 0, xpd = TRUE)
Mientras más cerca está la expiración, mayor va a ser el impacto de un cambio en el precio de la opción dependiendo si está ITM, ATM o OTM.
1.2 Gamma
Gamma (Γ) es la segunda derivada del precio de la opción con respecto al precio de la acción (o, lo que es lo mismo, la derivada de delta con respecto al precio de la acción). Como ya vimos en la sección anterior, la delta cambia conforme el precio de la acción cambia. La gamma nos va a decir de que manera se da este cambio. A diferencia de la delta, la gamma se calcula de la misma manera para ambos tipos de opciones y siempre es positiva. La fórmula es la siguiente:
Y la podemos implementar en R de la siguiente manera:
option.gamma <- function(spot, strike, t, rf, div, sigma){
# Calcula la gamma de una opción basado en el modelo
# de Merton (1973)
# Se necesita:
# - spot: precio spot del subyacente al momento de valuación
# - strike: strike de la opción
# - t: tiempo (en años) que falta para que expire la opción
# - rf: tasa libre de riesgo (anualizada)
# - div: dividend yield del subyacente
# - sigma: volatilidad (anualizada) del subyacente
# Se regresa:
# gamma: la segunda derivada del precio de la acción con
# respecto a el precio del subyacente (spot)
d1 <- (log(spot/strike) +
(rf - div + sigma^2/2)*t)/(sigma*sqrt(t))
o_gamma <- exp(-div*t)*dnorm(d1)/(spot*sigma*sqrt(t))
return(o_gamma)
}
Y podemos visualizarla con el siguiente script:
# 0. Limpiar la sesión
rm(list=ls())
if (names(dev.cur()) != "null device") {
dev.off()
}
cat("\014")
# 1. Cargar herramientas
source("scripts/herramientas.R")
# 2. Calcular gamma de la opción vs. precio de la acción
spot <- seq(0, 200, by = 1)
strike <- 90
t <- 0.5
rf <- 0.06
div <- 0.02
sigma <- 0.35
gamma_calls <- option.gamma(spot, strike, t, rf, div, sigma)
gamma_puts <- option.gamma(spot, strike, t, rf, div, sigma)
par(mar = c(5.1, 4.1, 4.1, 8.1))
plot(spot, gamma_calls, type = "l", lwd = 2,
main = "Gamma vs. precio de la acción (strike = $90)",
ylab = "Gamma", xlab = "Precio de la acción")
lines(spot, gamma_puts, lwd = 2, col = "red", lty = 2)
legend("topright", inset = c(-0.3, 0),
legend = c("Call", "Put"),
lty = c(1, 2), col = c("black", "red"), lwd = 2,
title = "Opción", box.lty = 0, xpd = TRUE)
Aunque la gamma es exactamente la misma, incluyo las dos líneas en la gráfica para reforzar este hecho.
1.3 Vega
Vega (κ) es la derivada del precio de la acción con respecto a la volatilidad (σ). Esta griega responde la pregunta siguiente: ¿por cada punto porcentual que aumente la volatilidad implícita, cuánto aumentará el precio de la acción? Veamos cómo cambia el precio de las opciones según la volatilidad:
# 0. Limpiar la sesión
rm(list=ls())
if (names(dev.cur()) != "null device") {
dev.off()
}
cat("\014")
# 1. Cargar herramientas
source("scripts/herramientas.R")
# 2. Calcular precio de la opción vs. volatilidad implícita
spot <- 100
strike <- 90
t <- 0.5
rf <- 0.06
div <- 0.02
sigma <- seq(0.05, 0.5, by = 0.01)
call <- merton.model(strike, spot, rf, t, sigma, div)
put <- merton.model(strike, spot, rf, t, sigma, div, "p")
par(mar = c(5.1, 4.1, 4.1, 8.1))
plot(sigma, call, type = "l", lwd = 2, ylim = c(0, 20),
main = "Precio de la Opción vs. Volatilidad",
ylab = "Precio de la Opción", xlab = "Volatilidad")
lines(sigma, put, lwd = 2, col = "red")
legend("topright", inset = c(-0.3, 0),
legend = c("Call", "Put"),
lty = 1, col = c("black", "red"), lwd = 2,
title = "Opción", box.lty = 0, xpd = TRUE)
Ahora veamos la fórmula de vega y cómo implementarla en R:
option.vega <- function(spot, strike, t, rf, div, sigma){
# Calcula la vega de una opción basado en el modelo
# de Merton (1973)
# Se necesita:
# - spot: precio spot del subyacente al momento de valuación
# - strike: strike de la opción
# - t: tiempo (en años) que falta para que expire la opción
# - rf: tasa libre de riesgo (anualizada)
# - div: dividend yield del subyacente
# - sigma: volatilidad (anualizada) del subyacente
# Se regresa:
# vega: la derivada del precio de la acción con respecto a la
# volatilidad del subyacente (sigma)
d1 <- (log(spot/strike) +
(rf - div + sigma^2/2)*t)/(sigma*sqrt(t))
vega <- spot*sqrt(t)*dnorm(d1)*exp(-div*t)
return(vega)
}
1.4 Theta
Theta (θ) es la derivada del precio de la opción con respecto al tiempo a expiración T
. Esta griega nos dice, por cada día que pasa, cuánto valor pierde la opción. Expresamos theta casi siempre como un número negativo, por que las opciones tienden a perder valor conforme se acerca la fecha de expiración (excepto por los puts ITM).
# 0. Limpiar la sesión
rm(list=ls())
if (names(dev.cur()) != "null device") {
dev.off()
}
cat("\014")
# 1. Cargar herramientas
source("scripts/herramientas.R")
# 2. Calcular precio de la opción vs. tiempo a expiración
spot <- 100
strike <- 90
t <- seq(0.01, 1.5, by = 0.01)
rf <- 0.06
div <- 0.02
sigma <- 0.35
call <- merton.model(strike, spot, rf, t, sigma, div)
put <- merton.model(strike, spot, rf, t, sigma, div, "p")
par(mar = c(5.1, 4.1, 4.1, 8.1))
plot(t, call, type = "l", lwd = 2, ylim = c(0, 25),
main = "Precio de la Opción vs. Tiempo a expiración",
ylab = "Precio de la Opción", xlab = "Tiempo")
lines(t, put, lwd = 2, col = "red")
legend("topright", inset = c(-0.3, 0),
legend = c("Call", "Put"),
lty = 1, col = c("black", "red"), lwd = 2,
title = "Opción", box.lty = 0, xpd = TRUE)
Veamos a continuación la fórmula para calcular theta y su implementación en R:
option.theta <- function(spot, strike, t, rf, div,
sigma, tipo = "c") {
# Calcula la theta de una opción basado en el modelo
# de Merton (1973)
# Se necesita:
# - spot: precio spot del subyacente al momento de valuación
# - strike: strike de la opción
# - t: tiempo (en años) que falta para que expire la opción
# - rf: tasa libre de riesgo (anualizada)
# - div: dividend yield del subyacente
# - sigma: volatilidad (anualizada) del subyacente
# - tipo: "c" (call) o "p" (put)
# Se regresa:
# theta: la derivada del precio de la acción con respecto a
# el tiempo a expiración (t)
tipo = tolower(tipo)
if (!(tipo %in% c("c", "p"))) {
stop("El tipo de la opción es incorrecto.
Elige uno de 'c' (call) o 'p' (put).")
}
d1 <- (log(spot/strike) +
(rf - div + sigma^2/2)*t)/(sigma*sqrt(t))
d2 <- d1 - sigma*sqrt(t)
if (tipo == "c") {
theta <- -spot*dnorm(d1)*sigma*exp(-div*t)/(2*sqrt(t)) +
div*spot*pnorm(d1)*exp(-div*t) -
rf*strike*exp(-rf*t)*pnorm(d2)
} else {
theta <- -spot*dnorm(d1)*sigma*exp(-div*t)/(2*sqrt(t)) -
div*spot*pnorm(-d1)*exp(-div*t) +
rf*strike*exp(-rf*t)*pnorm(-d2)
}
return(theta)
}
Podemos entonces analizar el efecto de theta según el precio de la acción:
# 0. Limpiar la sesión
rm(list=ls())
if (names(dev.cur()) != "null device") {
dev.off()
}
cat("\014")
# 1. Cargar herramientas
source("scripts/herramientas.R")
# 2. Calcular precio de la opción vs. tiempo a expiración
spot <- 100
strike <- 90
t <- seq(0.01, 1.5, by = 0.01)
rf <- 0.06
div <- 0.02
sigma <- 0.35
call <- merton.model(strike, spot, rf, t, sigma, div)
put <- merton.model(strike, spot, rf, t, sigma, div, "p")
par(mar = c(5.1, 4.1, 4.1, 8.1))
plot(t, call, type = "l", lwd = 2, ylim = c(0, 25),
main = "Precio de la Opción vs. Tiempo a expiración",
ylab = "Precio de la Opción", xlab = "Tiempo")
lines(t, put, lwd = 2, col = "red")
legend("topright", inset = c(-0.3, 0),
legend = c("Call", "Put"),
lty = 1, col = c("black", "red"), lwd = 2,
title = "Opción", box.lty = 0, xpd = TRUE)
# 3. Theta de una opción vs. precio de la acción
t <- 1
spot <- seq(0, 200, by = 1)
theta_call <- option.theta(spot, strike, t, rf, div, sigma)
theta_put <- option.theta(spot, strike, t, rf, div, sigma, "p")
plot(spot, theta_call, type = "l", lwd = 2, ylim = c(-8, 6),
main = "Theta de la opción vs. Precio de la acción",
ylab = "Theta", xlab = "Precio de la acción")
lines(spot, theta_put, lwd = 2, col = "red")
abline(h = 0, col = "lightgray", lty = 2)
legend("topright", inset = c(-0.3, 0),
legend = c("Call", "Put"),
lty = 1, col = c("black", "red"), lwd = 2,
title = "Opción", box.lty = 0, xpd = TRUE)
Como dijimos, puts que están muy ITM pueden tener una theta positiva, ganando valor conforme se acerca su expiración. Fuera de este caso, las opciones generalmente pierden valor conforme se acerca su fecha de expiración.
1.5 Rho
Rho (ρ) es la derivada del precio de una opción con respecto a la tasa libre de riesgo. Las fórmulas y su implementación en R las vemos a continuación:
option.rho <- function(spot, strike, t, rf, div,
sigma, tipo = "c") {
# Calcula la rho de una opción basado en el modelo
# de Merton (1973)
# Se necesita:
# - spot: precio spot del subyacente al momento de valuación
# - strike: strike de la opción
# - t: tiempo (en años) que falta para que expire la opción
# - rf: tasa libre de riesgo (anualizada)
# - div: dividend yield del subyacente
# - sigma: volatilidad (anualizada) del subyacente
# - tipo: "c" (call) o "p" (put)
# Se regresa:
# rho: la derivada del precio de la acción con respecto a la
# tasa libre de riesgo (rf)
tipo = tolower(tipo)
if (!(tipo %in% c("c", "p"))) {
stop("El tipo de la opción es incorrecto.
Elige uno de 'c' (call) o 'p' (put).")
}
d1 <- (log(spot/strike) +
(rf - div + sigma^2/2)*t)/(sigma*sqrt(t))
d2 <- d1 - sigma*sqrt(t)
if (tipo == "c") {
rho <- strike*t*exp(-rf*t)*pnorm(d2)
} else {
rho <- -strike*t*exp(-rf*t)*pnorm(-d2)
}
return(rho)
}
Rho nos permite entender cómo el precio de la opción cambiará con cada punto porcentual que aumente la tasa libre de riesgo. Veamos el efecto de esta variable en el precio de una opción:
# 0. Limpiar la sesión
rm(list=ls())
if (names(dev.cur()) != "null device") {
dev.off()
}
cat("\014")
# 1. Cargar herramientas
source("scripts/herramientas.R")
# 2. Calcular precio de la opción vs. volatilidad implícita
spot <- 100
strike <- 90
t <- 0.5
rf <- seq(0.01, 0.08, by = 0.01)
div <- 0.02
sigma <- 0.35
call <- merton.model(strike, spot, rf, t, sigma, div)
put <- merton.model(strike, spot, rf, t, sigma, div, "p")
par(mar = c(5.1, 4.1, 4.1, 8.1))
plot(rf, call, type = "l", lwd = 2, ylim = c(0, 20),
main = "Precio de la opción vs. Tasa libre de riesgo",
ylab = "Precio de la opción",
xlab = "Tasa libre de riesgo")
lines(rf, put, lwd = 2, col = "red")
legend("topright", inset = c(-0.3, 0),
legend = c("Call", "Put"),
lty = 1, col = c("black", "red"), lwd = 2,
title = "Opción", box.lty = 0, xpd = TRUE)
Aunque el efecto es menor que las variables anteriores, no está de más tenerlo en mente.
1.6 Tabla de griegas
A continuación les comparto un script para rápidamente visualizar las griegas de una opción en una tabla:
# 0. Limpiar la sesión
rm(list=ls())
if (names(dev.cur()) != "null device") {
dev.off()
}
cat("\014")
# 1. Cargar herramientas
source("scripts/herramientas.R")
# 2. Calcular griegas de las opciones
spot <- 100
strike <- 90
t <- 0.5
rf <- 0.06
div <- 0.02
sigma <- 0.35
precio_call <- merton.model(strike, spot, rf, t, sigma, div)
precio_put <- merton.model(strike, spot, rf, t,sigma, div, "p")
delta_call <- option.delta(spot, strike, t, rf, div, sigma)
delta_put <- option.delta(spot, strike, t, rf, div, sigma, "p")
gamma_call <- option.gamma(spot, strike, t, rf, div, sigma)
gamma_put <- gamma_call
vega_call <- option.vega(spot, strike, t, rf, div, sigma)
vega_put <- vega_call
theta_call <- option.theta(spot, strike, t, rf, div, sigma)
theta_put <- option.theta(spot, strike, t, rf, div, sigma, "p")
rho_call <- option.rho(spot, strike, t, rf, div, sigma)
rho_put <- option.rho(spot, strike, t, rf, div, sigma, "p")
call <- c(precio_call, delta_call, gamma_call,
vega_call, theta_call, rho_call)
put <- c(precio_put, delta_put, gamma_put,
vega_put, theta_put, rho_put)
labels <- c("precio", "delta", "gamma",
"vega", "theta", "rho")
info_df <- data.frame(cbind(call, put), row.names = labels)
print(round(info_df, 4))
Eso fue todo por hoy. Espero que este tutorial les haya servido. Si tienen cualquier duda o comentario pueden dejarlo en la sección de abajo. Si quieren compartir este blog con sus amigos y compañeros o suscribirse, les dejo los botones aquí:
Hasta el próximo tutorial!