{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE)
{r paquetes} to_install <- c(“quantmod”, “PerformanceAnalytics”, “tseries”, “ggplot2”, “dplyr”, “tidyverse”, “lubridate”, “tibble”, “RQuantLib”) missing_pkgs <- to_install[!(to_install %in% installed.packages()[, “Package”])] if(length(missing_pkgs)) install.packages(missing_pkgs)
lapply(to_install, library, character.only = TRUE)
{r descarga_datos} stocks <- c(“RXRX”, “MRNA”, “BRPHF”) start_date <- as.Date(“2022-06-01”) end_date <- as.Date(“2025-03-31”)
getSymbols(stocks, from = start_date, to = end_date, src = “yahoo”) prices <- do.call(merge, lapply(stocks, function(x) Cl(get(x)))) colnames(prices) <- stocks returns <- na.omit(diff(log(prices))) mu <- colMeans(returns) cov_matrix <- cov(returns)
{r simulacion_mgb} set.seed(123) sim_days <- as.numeric(end_date -
index(prices)[nrow(prices)]) dt <- 1 / 252
num_sims <- 10 sigma <- apply(returns, 2, sd)
MGB_sim <- array(NA, dim = c(sim_days, length(stocks), num_sims)) dimnames(MGB_sim) <- list(NULL, stocks, NULL)
for (sim in 1:num_sims) { for (i in 1:length(stocks)) { last_price <- as.numeric(prices[nrow(prices), i]) S_t <- numeric(sim_days) S_t[1] <- last_price for (t in 2:sim_days) { Z_t <- rnorm(1) S_t[t] <- S_t[t-1] * exp((mu[i] - 0.5 * sigma[i]^2) * dt + sigma[i] * sqrt(dt) * Z_t) } MGB_sim[, i, sim] <- S_t } }
{r opciones_europeas} S <- as.numeric(prices[nrow(prices), ]) K
<- S
T_exp <- 2 r <- 0.04 sigma_opt <- apply(returns, 2, sd)
european_calls <- sapply(1:length(stocks), function(i) { EuropeanOption(“call”, S[i], K[i], 0, r, T_exp, sigma_opt[i])$value })
european_puts <- sapply(1:length(stocks), function(i) { EuropeanOption(“put”, S[i], K[i], 0, r, T_exp, sigma_opt[i])$value })
{r cobertura} inversion_total <- 1e6 porc_cobertura <- 0.85 monto_cobertura <- inversion_total * porc_cobertura precios_opciones <- european_calls + european_puts num_contratos <- monto_cobertura / sum(precios_opciones)
{r frontera} set.seed(123) n_sim <- 5000 pesos_random <- matrix(runif(n_sim * length(stocks)), ncol = length(stocks)) pesos_random <- t(apply(pesos_random, 1, function(x) x / sum(x))) retornos_random <- pesos_random %% mu riesgo_random <- sqrt(rowSums((pesos_random %% cov_matrix) * pesos_random)) sharpe_random <- retornos_random / riesgo_random idx_tangency <- which.max(sharpe_random) pesos_tangency <- pesos_random[idx_tangency, ]
{r grafico_frontera} ggplot() + geom_point(aes(x = riesgo_random, y = retornos_random), alpha = 0.3, color = “blue”) + geom_point(aes(x = sqrt(t(pesos_tangency) %% cov_matrix %% pesos_tangency), y = sum(pesos_tangency * mu)), color = “red”, size = 3) + labs(title = “Frontera Eficiente y Carteras Aleatorias”, x = “Volatilidad”, y = “Retorno Esperado”) + theme_minimal()
{r carteras} w_min <- solve(cov_matrix) %*% rep(1, length(stocks)) w_min <- w_min / sum(w_min) w_min_df <- data.frame(Accion = stocks, Peso = as.numeric(w_min))
w_tan_df <- data.frame(Accion = stocks, Peso = as.numeric(pesos_tangency))
{r grafico_min_var} ggplot(w_min_df, aes(x = Accion, y = Peso, fill = Accion)) + geom_bar(stat = “identity”) + labs(title = “Pesos de la Cartera de Mínima Varianza”, x = “Acción”, y = “Peso”) + scale_y_continuous(labels = scales::percent_format()) + theme_minimal()
{r grafico_tangencia} ggplot(w_tan_df, aes(x = Accion, y = Peso, fill = Accion)) + geom_bar(stat = “identity”) + labs(title = “Pesos de la Cartera de Tangencia (Máximo Sharpe)”, x = “Acción”, y = “Peso”) + scale_y_continuous(labels = scales::percent_format()) + theme_minimal()
{r comparacion} cat(“Pesos de la cartera mínima varianza:”) print(round(w_min, 4))
sharpe_ratio_min <- mean(rowSums(returns %% w_min)) / sd(rowSums(returns %% w_min)) cat(“Ratio cartera mínima varianza:”, round(sharpe_ratio_min, 4), “”)
sharpe_ratio_tan <- mean(rowSums(returns %% pesos_tangency)) / sd(rowSums(returns %% pesos_tangency)) cat(“Sharpe Ratio cartera tangencia:”, round(sharpe_ratio_tan, 4), “”)