El objetivo principal de este proyecto es analizar y comparar las fronteras eficientes de portafolios en los mercados de valores de México (BMV) y Estados Unidos (EE.UU.). Utilizando técnicas de optimización de portafolios, buscamos identificar los portafolios óptimos que ofrecen el mejor equilibrio entre riesgo y retorno. Este análisis tiene implicaciones prácticas significativas para los inversores que buscan maximizar sus retornos ajustados por riesgo en diferentes mercados.
En la teoría de portafolios moderna, introducida por Harry Markowitz en 1952, la frontera eficiente es un concepto clave. Representa el conjunto de portafolios que ofrecen el máximo retorno esperado para un nivel dado de riesgo o, alternativamente, el mínimo riesgo para un nivel dado de retorno esperado. La construcción de la frontera eficiente implica la diversificación de activos para reducir el riesgo sin sacrificar los retornos esperados.
Los mercados de valores de México y Estados Unidos presentan características diferentes en términos de volatilidad, retornos y estructura del mercado. Este proyecto busca explorar estas diferencias y proporcionar una comparación cuantitativa y visual de las fronteras eficientes de ambos mercados. Además, se incluye un análisis de la Línea del Mercado de Capitales (CML) y los ratios de Sharpe para evaluar la eficiencia de los portafolios en términos de su relación riesgo-retorno.
Para llevar a cabo este análisis, se utilizaron datos históricos de precios de acciones de ambos mercados. Se seleccionaron tres acciones representativas de cada mercado: FEMSAUBD.MX, CEMEXCPO.MX, y GMEXICOB.MX para el BMV, y tres acciones de EE.UU. con características similares. Los datos fueron obtenidos de fuentes confiables como Yahoo Finance y abarcan un periodo de un año.
La metodología incluye los siguientes pasos:
Recolección de Datos: Obtención de precios históricos de las acciones seleccionadas.
Cálculo de Retornos: Cálculo de los retornos diarios a partir de los precios históricos.
Optimización de Portafolios: Utilización de técnicas de optimización de portafolios para construir las fronteras eficientes para ambos mercados.
Análisis de la Frontera Eficiente: Identificación de portafolios de mínima varianza y máximo Sharpe.
Comparación de Fronteras: Comparación visual y cuantitativa de las fronteras eficientes de BMV y EE.UU.
Análisis Adicional: Inclusión de la Línea del Mercado de Capitales (CML) y evaluación de ratios de Sharpe.
Este estudio es crucial para inversores que buscan diversificar sus inversiones a nivel internacional y optimizar sus portafolios en diferentes mercados. Al comprender las diferencias en la eficiencia de los portafolios entre BMV y EE.UU., los inversores pueden tomar decisiones más informadas y estratégicas, adaptando sus estrategias de inversión a las características específicas de cada mercado.
Además, este análisis contribuye a la literatura existente sobre la teoría de portafolios y proporciona una base sólida para futuras investigaciones en el campo de las finanzas internacionales. Las herramientas y técnicas utilizadas en este proyecto pueden ser aplicadas a otros mercados y periodos, ofreciendo un enfoque versátil y robusto para la optimización de portafolios.
El objetivo de esta sección del código es instalar y cargar los paquetes necesarios, definir los activos a analizar de la Bolsa Mexicana de Valores (BMV) y del mercado de valores de Estados Unidos (EE.UU.), obtener los datos históricos de precios de estos activos desde Yahoo Finance, combinar estos datos en estructuras adecuadas para su análisis posterior, y calcular los retornos diarios.
Para realizar el análisis financiero y la optimización de portafolios, se utilizan varios paquetes de R:
library(quantmod)
## Warning: package 'quantmod' was built under R version 4.3.3
## Loading required package: xts
## Warning: package 'xts' was built under R version 4.3.3
## Loading required package: zoo
## Warning: package 'zoo' was built under R version 4.3.3
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
## Loading required package: TTR
## Warning: package 'TTR' was built under R version 4.3.3
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(forecast)
## Warning: package 'forecast' was built under R version 4.3.3
library(PortfolioAnalytics)
## Warning: package 'PortfolioAnalytics' was built under R version 4.3.3
## Loading required package: foreach
## Warning: package 'foreach' was built under R version 4.3.3
## Loading required package: PerformanceAnalytics
## Warning: package 'PerformanceAnalytics' was built under R version 4.3.3
##
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
##
## legend
library(ROI)
## Warning: package 'ROI' was built under R version 4.3.3
## Registered S3 method overwritten by 'ROI':
## method from
## print.constraint PortfolioAnalytics
## ROI: R Optimization Infrastructure
## Registered solver plugins: nlminb, glpk, quadprog.
## Default solver: auto.
##
## Attaching package: 'ROI'
## The following objects are masked from 'package:PortfolioAnalytics':
##
## is.constraint, objective
library(TTR)
library(CVXR)
## Warning: package 'CVXR' was built under R version 4.3.3
##
## Attaching package: 'CVXR'
## The following objects are masked from 'package:ROI':
##
## constraints, constraints<-, objective, objective<-
## The following object is masked from 'package:PortfolioAnalytics':
##
## objective
## The following object is masked from 'package:stats':
##
## power
library(ROI.plugin.quadprog)
## Warning: package 'ROI.plugin.quadprog' was built under R version 4.3.3
library(ROI.plugin.glpk)
## Warning: package 'ROI.plugin.glpk' was built under R version 4.3.3
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
library(reshape2)
## Warning: package 'reshape2' was built under R version 4.3.3
Estos paquetes proporcionan funciones para la recolección de datos financieros, la construcción y optimización de portafolios, y la visualización de resultados.
Se seleccionaron activos representativos tanto de la Bolsa Mexicana de Valores (BMV) como del mercado de Estados Unidos:
tickers_bmv <- c("FEMSAUBD.MX", "CEMEXCPO.MX", "GMEXICOB.MX")
tickers_us <- c("^IXIC", "^DJI", "AAPL", "MSFT", "AMZN")
# Definir el índice de la BMV (ejemplo usando IPC) y el índice de EE.UU. (ejemplo usando S&P 500)
indice_bmv <- "^MXX"
indice_us <- "^GSPC"
Para obtener los datos históricos de precios, se define un rango de fechas (el último año) y se implementa una función para extraer estos datos desde Yahoo Finance:
start_date <- Sys.Date() - 365
end_date <- Sys.Date()
getYahooData <- function(tickers, start, end) {
data_list <- list()
for (ticker in tickers) {
tryCatch({
data_temp <- getSymbols(ticker, from = start, to = end, auto.assign = FALSE)
data_list[[ticker]] <- Ad(data_temp)
print(paste("Successfully retrieved data for", ticker))
}, error = function(e) {
print(paste("Error retrieving data for", ticker))
})
}
return(data_list)
}
Esta función utiliza getSymbols del paquete
quantmod para descargar los datos y Ad para
extraer los precios de cierre ajustados. Los datos se almacenan en una
lista.
Después de obtener los datos, se inspeccionan los datos individuales de cada activo para verificar su corrección y completitud
data_bmv_list <- getYahooData(tickers_bmv, start_date, end_date)
## [1] "Successfully retrieved data for FEMSAUBD.MX"
## [1] "Successfully retrieved data for CEMEXCPO.MX"
## [1] "Successfully retrieved data for GMEXICOB.MX"
data_us_list <- getYahooData(tickers_us, start_date, end_date)
## [1] "Successfully retrieved data for ^IXIC"
## [1] "Successfully retrieved data for ^DJI"
## [1] "Successfully retrieved data for AAPL"
## [1] "Successfully retrieved data for MSFT"
## [1] "Successfully retrieved data for AMZN"
print("Datos individuales de la BMV:")
## [1] "Datos individuales de la BMV:"
for (ticker in tickers_bmv) {
print(paste("Datos de", ticker))
print(head(data_bmv_list[[ticker]]))
print(nrow(data_bmv_list[[ticker]]))
}
## [1] "Datos de FEMSAUBD.MX"
## FEMSAUBD.MX.Adjusted
## 2023-06-26 174.1714
## 2023-06-27 177.8266
## 2023-06-28 176.6961
## 2023-06-29 178.0810
## 2023-06-30 178.4390
## 2023-07-03 182.3769
## [1] 250
## [1] "Datos de CEMEXCPO.MX"
## CEMEXCPO.MX.Adjusted
## 2023-06-26 11.81793
## 2023-06-27 12.03790
## 2023-06-28 11.89792
## 2023-06-29 11.96791
## 2023-06-30 12.09789
## 2023-07-03 12.16787
## [1] 250
## [1] "Datos de GMEXICOB.MX"
## GMEXICOB.MX.Adjusted
## 2023-06-26 80.82468
## 2023-06-27 80.85348
## 2023-06-28 80.19115
## 2023-06-29 78.86647
## 2023-06-30 79.00085
## 2023-07-03 81.85180
## [1] 250
print("Datos individuales de EE.UU.:")
## [1] "Datos individuales de EE.UU.:"
for (ticker in tickers_us) {
print(paste("Datos de", ticker))
print(head(data_us_list[[ticker]]))
print(nrow(data_us_list[[ticker]]))
}
## [1] "Datos de ^IXIC"
## IXIC.Adjusted
## 2023-06-26 13335.78
## 2023-06-27 13555.67
## 2023-06-28 13591.75
## 2023-06-29 13591.33
## 2023-06-30 13787.92
## 2023-07-03 13816.77
## [1] 250
## [1] "Datos de ^DJI"
## DJI.Adjusted
## 2023-06-26 33714.71
## 2023-06-27 33926.74
## 2023-06-28 33852.66
## 2023-06-29 34122.42
## 2023-06-30 34407.60
## 2023-07-03 34418.47
## [1] 250
## [1] "Datos de AAPL"
## AAPL.Adjusted
## 2023-06-26 185.27
## 2023-06-27 188.06
## 2023-06-28 189.25
## 2023-06-29 189.59
## 2023-06-30 193.97
## 2023-07-03 192.46
## [1] 250
## [1] "Datos de MSFT"
## MSFT.Adjusted
## 2023-06-26 328.60
## 2023-06-27 334.57
## 2023-06-28 335.85
## 2023-06-29 335.05
## 2023-06-30 340.54
## 2023-07-03 337.99
## [1] 250
## [1] "Datos de AMZN"
## AMZN.Adjusted
## 2023-06-26 127.33
## 2023-06-27 129.18
## 2023-06-28 129.04
## 2023-06-29 127.90
## 2023-06-30 130.36
## 2023-07-03 130.22
## [1] 250
Los datos de diferentes activos se combinan en un solo objeto
xts para facilitar el análisis:
combineData <- function(data_list) {
if (length(data_list) == 0) {
return(xts())
}
data_combined <- data_list[[1]]
for (ticker in names(data_list)[-1]) {
data_combined <- merge(data_combined, data_list[[ticker]], join = "inner")
}
colnames(data_combined) <- names(data_list)
return(data_combined)
}
data_bmv <- combineData(data_bmv_list)
data_us <- combineData(data_us_list)
# Función para obtener datos del índice
getIndexData <- function(index_ticker, start, end) {
tryCatch({
index_data <- getSymbols(index_ticker, from = start, to = end, auto.assign = FALSE)
return(Ad(index_data)) # Usar solo el precio de cierre ajustado del índice
}, error = function(e) {
print(paste("Error al obtener datos para el índice", index_ticker))
return(NULL)
})
}
# Obtener datos del índice de la BMV y de EE.UU.
index_bmv_data <- getIndexData(indice_bmv, start_date, end_date)
index_us_data <- getIndexData(indice_us, start_date, end_date)
Esta función asegura que solo se consideren las fechas comunes a todos los activos, lo cual es crucial para el análisis comparativo y la optimización de portafolios.
Finalmente, se verifica la estructura de los datos combinados y se calculan los retornos diarios para cada activo, omitiendo valores faltantes:
print("Estructura de data_bmv combinada:")
## [1] "Estructura de data_bmv combinada:"
print(str(data_bmv))
## An xts object on 2023-06-26 / 2024-06-21 containing:
## Data: double [250, 3]
## Columns: FEMSAUBD.MX, CEMEXCPO.MX, GMEXICOB.MX
## Index: Date [250] (TZ: "UTC")
## xts Attributes:
## $ src : chr "yahoo"
## $ updated: POSIXct[1:1], format: "2024-06-24 21:28:02"
## NULL
print("Primeros registros de data_bmv combinada:")
## [1] "Primeros registros de data_bmv combinada:"
print(head(data_bmv))
## FEMSAUBD.MX CEMEXCPO.MX GMEXICOB.MX
## 2023-06-26 174.1714 11.81793 80.82468
## 2023-06-27 177.8266 12.03790 80.85348
## 2023-06-28 176.6961 11.89792 80.19115
## 2023-06-29 178.0810 11.96791 78.86647
## 2023-06-30 178.4390 12.09789 79.00085
## 2023-07-03 182.3769 12.16787 81.85180
print("Estructura de data_us combinada:")
## [1] "Estructura de data_us combinada:"
print(str(data_us))
## An xts object on 2023-06-26 / 2024-06-21 containing:
## Data: double [250, 5]
## Columns: ^IXIC, ^DJI, AAPL, MSFT, AMZN
## Index: Date [250] (TZ: "UTC")
## xts Attributes:
## $ src : chr "yahoo"
## $ updated: POSIXct[1:1], format: "2024-06-24 21:28:03"
## NULL
print("Primeros registros de data_us combinada:")
## [1] "Primeros registros de data_us combinada:"
print(head(data_us))
## ^IXIC ^DJI AAPL MSFT AMZN
## 2023-06-26 13335.78 33714.71 185.27 328.60 127.33
## 2023-06-27 13555.67 33926.74 188.06 334.57 129.18
## 2023-06-28 13591.75 33852.66 189.25 335.85 129.04
## 2023-06-29 13591.33 34122.42 189.59 335.05 127.90
## 2023-06-30 13787.92 34407.60 193.97 340.54 130.36
## 2023-07-03 13816.77 34418.47 192.46 337.99 130.22
if (nrow(data_bmv) > 1) {
returns_bmv <- na.omit(ROC(data_bmv, type = "discrete"))
print("Primeros registros de returns_bmv:")
print(head(returns_bmv))
} else {
print("data_bmv no tiene suficientes registros para calcular rendimientos.")
}
## [1] "Primeros registros de returns_bmv:"
## FEMSAUBD.MX CEMEXCPO.MX GMEXICOB.MX
## 2023-06-27 0.020986561 0.018612487 0.0003562443
## 2023-06-28 -0.006357277 -0.011627908 -0.0081917395
## 2023-06-29 0.007837507 0.005882393 -0.0165189870
## 2023-06-30 0.002010245 0.010860479 0.0017038486
## 2023-07-03 0.022068505 0.005785164 0.0360876150
## 2023-07-04 -0.028772072 -0.008216983 -0.0092647802
if (nrow(data_us) > 1) {
returns_us <- na.omit(ROC(data_us, type = "discrete"))
print("Primeros registros de returns_us:")
print(head(returns_us))
} else {
print("data_us no tiene suficientes registros para calcular rendimientos.")
}
## [1] "Primeros registros de returns_us:"
## ^IXIC ^DJI AAPL MSFT AMZN
## 2023-06-27 1.648870e-02 0.0062888673 0.015059066 0.0181679888 0.014529104
## 2023-06-28 2.661623e-03 -0.0021834732 0.006327781 0.0038258025 -0.001083754
## 2023-06-29 -3.089535e-05 0.0079687008 0.001796546 -0.0023820703 -0.008834407
## 2023-06-30 1.446436e-02 0.0083575453 0.023102511 0.0163856766 0.019233769
## 2023-07-03 2.092383e-03 0.0003158368 -0.007784681 -0.0074881607 -0.001073944
## 2023-07-05 -1.818018e-03 -0.0037720483 -0.005871375 0.0004733976 0.001228718
El cálculo de retornos se realiza usando la función ROC
del paquete quantmod, que calcula los retornos discretos
diarios. Esta información es fundamental para los análisis de riesgo y
retorno que se realizarán en las siguientes etapas del proyecto.
Esta primera parte del código establece la base de datos necesaria para realizar un análisis completo de portafolios y comparar las fronteras eficientes entre los mercados de BMV y EE.UU.
Para llevar a cabo cualquier análisis de portafolio, primero se deben
calcular los rendimientos diarios de los activos. Esto se realiza
mediante la función ROC del paquete quantmod,
que calcula los retornos discretos:
returns_bmv <- na.omit(ROC(data_bmv, type = "discrete"))
returns_us <- na.omit(ROC(data_us, type = "discrete"))
# Calcular rendimientos diarios para los índices de la BMV y de EE.UU.
returns_index_bmv <- na.omit(ROC(index_bmv_data, type = "discrete"))
returns_index_us <- na.omit(ROC(index_us_data, type = "discrete"))
Una vez calculados los retornos, es importante obtener estadísticas descriptivas para entender mejor el comportamiento de los datos:
summary(returns_bmv)
## Index FEMSAUBD.MX CEMEXCPO.MX
## Min. :2023-06-27 Min. :-0.1088718 Min. :-8.384e-02
## 1st Qu.:2023-09-21 1st Qu.:-0.0084869 1st Qu.:-1.137e-02
## Median :2023-12-21 Median : 0.0002827 Median : 1.477e-03
## Mean :2023-12-22 Mean : 0.0005514 Mean : 3.666e-05
## 3rd Qu.:2024-03-22 3rd Qu.: 0.0084646 3rd Qu.: 1.222e-02
## Max. :2024-06-21 Max. : 0.0630001 Max. : 6.667e-02
## GMEXICOB.MX
## Min. :-0.0650554
## 1st Qu.:-0.0119256
## Median : 0.0005605
## Mean : 0.0009398
## 3rd Qu.: 0.0128703
## Max. : 0.0733570
summary(returns_us)
## Index ^IXIC ^DJI
## Min. :2023-06-27 Min. :-0.024251 Min. :-0.0152700
## 1st Qu.:2023-09-25 1st Qu.:-0.004093 1st Qu.:-0.0026133
## Median :2023-12-21 Median : 0.001117 Median : 0.0011641
## Mean :2023-12-23 Mean : 0.001183 Mean : 0.0006192
## 3rd Qu.:2024-03-22 3rd Qu.: 0.007502 3rd Qu.: 0.0042629
## Max. :2024-06-21 Max. : 0.029572 Max. : 0.0169649
## AAPL MSFT AMZN
## Min. :-0.0480201 Min. :-0.037638 Min. :-0.0557716
## 1st Qu.:-0.0074512 1st Qu.:-0.006113 1st Qu.:-0.0087306
## Median : 0.0007577 Median : 0.001672 Median : 0.0006484
## Mean : 0.0005496 Mean : 0.001342 Mean : 0.0017373
## 3rd Qu.: 0.0079040 3rd Qu.: 0.009484 3rd Qu.: 0.0113069
## Max. : 0.0726491 Max. : 0.039800 Max. : 0.0826934
El comando summary proporciona un resumen estadístico
que incluye medidas como la media, mediana, desviación estándar, valores
mínimos y máximos de los retornos diarios para cada activo.
La correlación entre activos es crucial para entender cómo se mueven los precios relativos entre sí, lo que influye en la diversificación del portafolio:
cor_bmv <- cor(returns_bmv)
cor_us <- cor(returns_us)
print("Correlación entre activos de la BMV:")
## [1] "Correlación entre activos de la BMV:"
print(cor_bmv)
## FEMSAUBD.MX CEMEXCPO.MX GMEXICOB.MX
## FEMSAUBD.MX 1.0000000 0.1858206 0.1634858
## CEMEXCPO.MX 0.1858206 1.0000000 0.3600142
## GMEXICOB.MX 0.1634858 0.3600142 1.0000000
print("Correlación entre activos de Estados Unidos:")
## [1] "Correlación entre activos de Estados Unidos:"
print(cor_us)
## ^IXIC ^DJI AAPL MSFT AMZN
## ^IXIC 1.0000000 0.6704522 0.6036005 0.7295710 0.6959493
## ^DJI 0.6704522 1.0000000 0.3640180 0.4929631 0.4058131
## AAPL 0.6036005 0.3640180 1.0000000 0.4346671 0.2587352
## MSFT 0.7295710 0.4929631 0.4346671 1.0000000 0.5655599
## AMZN 0.6959493 0.4058131 0.2587352 0.5655599 1.0000000
Para realizar una optimización de portafolios, se necesita calcular los rendimientos esperados y las volatilidades (desviaciones estándar) de los retornos, así como la matriz de covarianza. Esto se realiza mediante la siguiente función:
calculatePortfolioStats <- function(returns) {
mean_returns <- colMeans(returns)
sd_returns <- apply(returns, 2, sd)
cov_matrix <- cov(returns)
list(mean_returns = mean_returns, sd_returns = sd_returns, cov_matrix = cov_matrix)
}
La optimización del portafolio de varianza mínima implica encontrar la combinación de activos que minimiza el riesgo (varianza) del portafolio, sujeta a ciertas restricciones. Se utilizan las siguientes funciones para definir y optimizar el portafolio:
Definición del Específico del Portafolio:
Para la BMV:
portfolio_spec_bmv <- portfolio.spec(assets = colnames(returns_bmv))
portfolio_spec_bmv <- add.constraint(portfolio_spec_bmv, type = "full_investment")
portfolio_spec_bmv <- add.constraint(portfolio_spec_bmv, type = "long_only")
portfolio_spec_bmv <- add.objective(portfolio_spec_bmv, type = "risk", name = "var")
Para EE.UU.:
portfolio_spec_us <- portfolio.spec(assets = colnames(returns_us))
portfolio_spec_us <- add.constraint(portfolio_spec_us, type = "full_investment")
portfolio_spec_us <- add.constraint(portfolio_spec_us, type = "long_only")
portfolio_spec_us <- add.objective(portfolio_spec_us, type = "risk", name = "var")Optimización del Portafolio:
Se utiliza el método de optimización ROI para encontrar el portafolio de varianza mínima:
Para la BMV:
opt_min_variance_bmv <- optimize.portfolio(returns_bmv, portfolio = portfolio_spec_bmv, optimize_method = "ROI")
Para EE.UU.:
opt_min_variance_us <- optimize.portfolio(returns_us, portfolio = portfolio_spec_us, optimize_method = "ROI")Visualización de Resultados:
Los resultados de la optimización se imprimen para inspección:
print("Portafolio de Varianza Mínima - BMV:")
## [1] "Portafolio de Varianza Mínima - BMV:"
print(opt_min_variance_bmv)
## ***********************************
## PortfolioAnalytics Optimization
## ***********************************
##
## Call:
## optimize.portfolio(R = returns_bmv, portfolio = portfolio_spec_bmv,
## optimize_method = "ROI")
##
## Optimal Weights:
## FEMSAUBD.MX CEMEXCPO.MX GMEXICOB.MX
## 0.4908 0.2798 0.2295
##
## Objective Measure:
## StdDev
## 0.01285
print("Portafolio de Varianza Mínima - EE.UU.:")
## [1] "Portafolio de Varianza Mínima - EE.UU.:"
print(opt_min_variance_us)
## ***********************************
## PortfolioAnalytics Optimization
## ***********************************
##
## Call:
## optimize.portfolio(R = returns_us, portfolio = portfolio_spec_us,
## optimize_method = "ROI")
##
## Optimal Weights:
## ^IXIC ^DJI AAPL MSFT AMZN
## 0.0000 0.9593 0.0407 0.0000 0.0000
##
## Objective Measure:
## StdDev
## 0.006114En esta tercera parte del código se realiza el cálculo de los betas de los activos individuales respecto a sus respectivos índices de mercado utilizando el modelo CAPM (Capital Asset Pricing Model):
Se define la función calculateCAPMBetas que toma como
entrada los retornos de los activos individuales y el retorno del
mercado. Para cada activo, se ajusta un modelo de regresión lineal
simple para calcular el beta:
calculateCAPMBetas <- function(returns_assets, returns_market) {
betas <- sapply(returns_assets, function(asset_returns) {
lm_result <- lm(asset_returns ~ returns_market)
beta <- coef(lm_result)[2] # Coeficiente beta del modelo CAPM
return(beta)
})
return(betas)
}
Para la BMV:
Se calculan los betas de los activos individuales respecto al índice de la BMV :
# Verificar las dimensiones de los datos
dim(returns_bmv)
## [1] 249 3
dim(returns_index_bmv)
## [1] 249 1
# Asegurarse de que los índices (fechas u otros) estén alineados correctamente
head(index(returns_bmv)) # Asegúrate de que coincida con el índice de returns_index_bmv
## [1] "2023-06-27" "2023-06-28" "2023-06-29" "2023-06-30" "2023-07-03"
## [6] "2023-07-04"
# índices no están alineados, alinea los datos
aligned_returns_bmv <- returns_bmv[index(returns_bmv) %in% index(returns_index_bmv)]
aligned_returns_index_bmv <- returns_index_bmv[index(returns_index_bmv) %in% index(returns_bmv)]
# Calcular los betas nuevamente con los datos alineados
betas_bmv <- calculateCAPMBetas(aligned_returns_bmv, aligned_returns_index_bmv)
# Imprimir los resultados
print("Betas de los activos de la BMV respecto al índice de la BMV:")
## [1] "Betas de los activos de la BMV respecto al índice de la BMV:"
print(betas_bmv)
## FEMSAUBD.MX.returns_market CEMEXCPO.MX.returns_market
## 0.7555859 1.1236303
## GMEXICOB.MX.returns_market
## 1.2701705Para EE.UU.:
Se calculan los betas de los activos individuales de EE.UU. respecto al índice de EE.UU.:
# índices no están alineados, alinea los datos
aligned_returns_us <- returns_us[index(returns_us) %in% index(returns_index_us)]
aligned_returns_index_us <- returns_index_us[index(returns_index_us) %in% index(returns_us)]
# Calcular los betas de los activos individuales de EE.UU. respecto al índice de EE.UU.
betas_us <- calculateCAPMBetas(aligned_returns_us, aligned_returns_index_us)
print("Betas de los activos de EE.UU. respecto al índice de EE.UU.:")
## [1] "Betas de los activos de EE.UU. respecto al índice de EE.UU.:"
print(betas_us)
## ^IXIC.returns_market ^DJI.returns_market AAPL.returns_market
## 1.3119745 0.7272216 1.0671939
## MSFT.returns_market AMZN.returns_market
## 1.2039237 1.5165033La cuarta parte del código se enfoca en realizar un resumen detallado de los resultados obtenidos tras el análisis de datos y la aplicación de diversas técnicas financieras sobre los activos de la Bolsa Mexicana de Valores (BMV) y de Estados Unidos (EE.UU.). Aquí se presenta un enfoque narrativo que explica cada sección relevante:
Resumen de la Bolsa Mexicana de Valores (BMV):
Activos analizados: Se muestran los tickers de los activos específicos de la BMV que han sido evaluados en el análisis.
Rendimientos esperados: Se presentan los rendimientos esperados calculados para cada activo en la BMV.
Volatilidades: Se detallan las volatilidades de cada activo, proporcionando una medida de su riesgo basada en la desviación estándar de sus rendimientos.
Correlaciones: Se muestra la matriz de correlaciones entre todos los activos de la BMV, destacando cómo se relacionan entre sí en términos de sus movimientos de precios.
Portafolio de Varianza Mínima: Se exhibe el portafolio óptimo de varianza mínima para la BMV, calculado para minimizar el riesgo dado un nivel esperado de retorno.
Betas respecto al índice de la BMV: Se calculan los betas de cada activo respecto al índice de la BMV, proporcionando una medida de la sensibilidad de cada activo frente a movimientos del mercado en general.
# Resumen final de lo realizado
print("Resumen de la BMV:")
## [1] "Resumen de la BMV:"
print("Activos analizados:")
## [1] "Activos analizados:"
print(tickers_bmv)
## [1] "FEMSAUBD.MX" "CEMEXCPO.MX" "GMEXICOB.MX"
print("Rendimientos esperados:")
## [1] "Rendimientos esperados:"
print(calculatePortfolioStats(returns_bmv)$mean_returns)
## FEMSAUBD.MX CEMEXCPO.MX GMEXICOB.MX
## 5.514258e-04 3.665645e-05 9.397804e-04
print("Volatilidades:")
## [1] "Volatilidades:"
print(calculatePortfolioStats(returns_bmv)$sd_returns)
## FEMSAUBD.MX CEMEXCPO.MX GMEXICOB.MX
## 0.01662952 0.01921566 0.02063720
print("Correlaciones:")
## [1] "Correlaciones:"
print(cor_bmv)
## FEMSAUBD.MX CEMEXCPO.MX GMEXICOB.MX
## FEMSAUBD.MX 1.0000000 0.1858206 0.1634858
## CEMEXCPO.MX 0.1858206 1.0000000 0.3600142
## GMEXICOB.MX 0.1634858 0.3600142 1.0000000
print("Portafolio de Varianza Mínima:")
## [1] "Portafolio de Varianza Mínima:"
print(opt_min_variance_bmv)
## ***********************************
## PortfolioAnalytics Optimization
## ***********************************
##
## Call:
## optimize.portfolio(R = returns_bmv, portfolio = portfolio_spec_bmv,
## optimize_method = "ROI")
##
## Optimal Weights:
## FEMSAUBD.MX CEMEXCPO.MX GMEXICOB.MX
## 0.4908 0.2798 0.2295
##
## Objective Measure:
## StdDev
## 0.01285
print("Betas respecto al índice de la BMV:")
## [1] "Betas respecto al índice de la BMV:"
print(betas_bmv)
## FEMSAUBD.MX.returns_market CEMEXCPO.MX.returns_market
## 0.7555859 1.1236303
## GMEXICOB.MX.returns_market
## 1.2701705Resumen de Estados Unidos (EE.UU.):
print("Resumen de EE.UU.:")
## [1] "Resumen de EE.UU.:"
print("Activos analizados:")
## [1] "Activos analizados:"
print(tickers_us)
## [1] "^IXIC" "^DJI" "AAPL" "MSFT" "AMZN"
print("Rendimientos esperados:")
## [1] "Rendimientos esperados:"
print(calculatePortfolioStats(returns_us)$mean_returns)
## ^IXIC ^DJI AAPL MSFT AMZN
## 0.0011833541 0.0006192346 0.0005495841 0.0013423858 0.0017373458
print("Volatilidades:")
## [1] "Volatilidades:"
print(calculatePortfolioStats(returns_us)$sd_returns)
## ^IXIC ^DJI AAPL MSFT AMZN
## 0.009831206 0.006136877 0.013816896 0.012731530 0.017323639
print("Correlaciones:")
## [1] "Correlaciones:"
print(cor_us)
## ^IXIC ^DJI AAPL MSFT AMZN
## ^IXIC 1.0000000 0.6704522 0.6036005 0.7295710 0.6959493
## ^DJI 0.6704522 1.0000000 0.3640180 0.4929631 0.4058131
## AAPL 0.6036005 0.3640180 1.0000000 0.4346671 0.2587352
## MSFT 0.7295710 0.4929631 0.4346671 1.0000000 0.5655599
## AMZN 0.6959493 0.4058131 0.2587352 0.5655599 1.0000000
print("Portafolio de Varianza Mínima:")
## [1] "Portafolio de Varianza Mínima:"
print(opt_min_variance_us)
## ***********************************
## PortfolioAnalytics Optimization
## ***********************************
##
## Call:
## optimize.portfolio(R = returns_us, portfolio = portfolio_spec_us,
## optimize_method = "ROI")
##
## Optimal Weights:
## ^IXIC ^DJI AAPL MSFT AMZN
## 0.0000 0.9593 0.0407 0.0000 0.0000
##
## Objective Measure:
## StdDev
## 0.006114
print("Betas respecto al índice de EE.UU.:")
## [1] "Betas respecto al índice de EE.UU.:"
print(betas_us)
## ^IXIC.returns_market ^DJI.returns_market AAPL.returns_market
## 1.3119745 0.7272216 1.0671939
## MSFT.returns_market AMZN.returns_market
## 1.2039237 1.5165033Este resumen permite una comprensión clara y concisa de los resultados obtenidos en el análisis financiero de ambos mercados, proporcionando insights valiosos sobre la estructura de los portafolios, la gestión del riesgo y las relaciones de los activos con sus respectivos índices de mercado.
La quinta parte del código continúa con la visualización de resultados y análisis de los datos financieros de la Bolsa Mexicana de Valores (BMV) y de Estados Unidos (EE.UU.). Aquí se detalla el proceso de graficación y análisis de los portafolios de mínima varianza obtenidos, así como otras métricas relevantes:
Portafolio de Varianza Mínima - BMV:
Se extraen las ponderaciones de los activos del portafolio óptimo
de varianza mínima para la BMV utilizando la función
extractWeights.
Se grafican las ponderaciones de cada activo en forma de barras, donde el eje x representa los activos y el eje y muestra las ponderaciones asignadas.
# Graficar portafolios de mínima varianza - BMV
weights_bmv <- extractWeights(opt_min_variance_bmv)
weights_bmv_df <- data.frame(Activo = names(weights_bmv), Ponderacion = weights_bmv)
ggplot(weights_bmv_df, aes(x = Activo, y = Ponderacion, fill = Activo)) +
geom_bar(stat = "identity") +
ggtitle("Portafolio de Varianza Mínima - BMV") +
xlab("Activo") +
ylab("Ponderación") +
theme_minimal()
Portafolio de Varianza Mínima - EE.UU.:
Similar al caso anterior, se extraen las ponderaciones de los
activos del portafolio óptimo de varianza mínima para EE.UU. utilizando
la función extractWeights.
Se grafican las ponderaciones de cada activo en forma de barras, donde el eje x representa los activos y el eje y muestra las ponderaciones asignadas.
# Graficar portafolios de mínima varianza - EE.UU.
weights_us <- extractWeights(opt_min_variance_us)
weights_us_df <- data.frame(Activo = names(weights_us), Ponderacion = weights_us)
ggplot(weights_us_df, aes(x = Activo, y = Ponderacion, fill = Activo)) +
geom_bar(stat = "identity") +
ggtitle("Portafolio de Varianza Mínima - EE.UU.") +
xlab("Activo") +
ylab("Ponderación") +
theme_minimal()
La sexta parte del código se enfoca en calcular y visualizar la frontera eficiente para los datos de la Bolsa Mexicana de Valores (BMV) y de Estados Unidos (EE.UU.). Aquí se utilizan funciones específicas para crear múltiples portafolios aleatorios y determinar cuáles ofrecen la mejor combinación de riesgo y rendimiento esperado.
# Definir el número de portafolios a simular
num_portfolios <- 5000
# Función para generar portafolios aleatorios y calcular su rendimiento y riesgo
generatePortfolios <- function(returns, num_portfolios) {
num_assets <- ncol(returns)
all_weights <- matrix(NA, nrow = num_portfolios, ncol = num_assets)
portfolio_returns <- rep(NA, num_portfolios)
portfolio_risks <- rep(NA, num_portfolios)
for (i in 1:num_portfolios) {
weights <- runif(num_assets)
weights <- weights / sum(weights)
portfolio_return <- sum(weights * colMeans(returns))
portfolio_risk <- sqrt(t(weights) %*% cov(returns) %*% weights)
all_weights[i,] <- weights
portfolio_returns[i] <- portfolio_return
portfolio_risks[i] <- portfolio_risk
}
return(list(weights = all_weights, returns = portfolio_returns, risks = portfolio_risks))
}
# Generar portafolios para BMV
portfolios_bmv <- generatePortfolios(returns_bmv, num_portfolios)
# Generar portafolios para EE.UU.
portfolios_us <- generatePortfolios(returns_us, num_portfolios)
# Convertir los resultados en data.frames para ggplot
portfolios_bmv_df <- data.frame(Returns = portfolios_bmv$returns, Risk = portfolios_bmv$risks)
portfolios_us_df <- data.frame(Returns = portfolios_us$returns, Risk = portfolios_us$risks)
# Graficar la frontera eficiente para BMV
ggplot(portfolios_bmv_df, aes(x = Risk, y = Returns)) +
geom_point(alpha = 0.5, color = "blue") +
ggtitle("Frontera Eficiente - BMV") +
xlab("Riesgo (Volatilidad)") +
ylab("Rendimiento Esperado") +
theme_minimal()
# Graficar la frontera eficiente para EE.UU.
ggplot(portfolios_us_df, aes(x = Risk, y = Returns)) +
geom_point(alpha = 0.5, color = "red") +
ggtitle("Frontera Eficiente - EE.UU.") +
xlab("Riesgo (Volatilidad)") +
ylab("Rendimiento Esperado") +
theme_minimal()
# Combinar los datos de las fronteras eficientes
portfolios_combined_df <- rbind(
data.frame(Market = "BMV", portfolios_bmv_df),
data.frame(Market = "US", portfolios_us_df)
)
# Graficar la frontera eficiente combinada
ggplot(portfolios_combined_df, aes(x = Risk, y = Returns, color = Market)) +
geom_point(alpha = 0.5) +
ggtitle("Frontera Eficiente - Comparación BMV y EE.UU.") +
xlab("Riesgo (Volatilidad)") +
ylab("Rendimiento Esperado") +
theme_minimal()
# Combinar los datos de las fronteras eficientes
portfolios_combined_df <- rbind(
data.frame(Market = "BMV", portfolios_bmv_df),
data.frame(Market = "US", portfolios_us_df)
)
# Graficar la frontera eficiente combinada
ggplot(portfolios_combined_df, aes(x = Risk, y = Returns, color = Market)) +
geom_point(alpha = 0.5) +
ggtitle("Frontera Eficiente - Comparación BMV y EE.UU.") +
xlab("Riesgo (Volatilidad)") +
ylab("Rendimiento Esperado") +
theme_minimal()
# Encontrar el portafolio de mínima varianza global para BMV
min_var_bmv_index <- which.min(portfolios_bmv$risks)
min_var_bmv <- portfolios_bmv$risks[min_var_bmv_index]
min_var_bmv_return <- portfolios_bmv$returns[min_var_bmv_index]
# Encontrar el portafolio de mínima varianza global para EE.UU.
min_var_us_index <- which.min(portfolios_us$risks)
min_var_us <- portfolios_us$risks[min_var_us_index]
min_var_us_return <- portfolios_us$returns[min_var_us_index]
# Convertir los resultados en data.frames para ggplot
portfolios_bmv_df <- data.frame(Returns = portfolios_bmv$returns, Risk = portfolios_bmv$risks)
portfolios_us_df <- data.frame(Returns = portfolios_us$returns, Risk = portfolios_us$risks)
# Graficar la frontera eficiente para BMV
ggplot(portfolios_bmv_df, aes(x = Risk, y = Returns)) +
geom_point(alpha = 0.5, color = "blue") +
geom_point(aes(x = min_var_bmv, y = min_var_bmv_return), color = "red", size = 3) +
ggtitle("Frontera Eficiente - BMV") +
xlab("Riesgo (Volatilidad)") +
ylab("Rendimiento Esperado") +
theme_minimal()
## Warning in geom_point(aes(x = min_var_bmv, y = min_var_bmv_return), color = "red", : All aesthetics have length 1, but the data has 5000 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
## a single row.
# Graficar la frontera eficiente para EE.UU.
ggplot(portfolios_us_df, aes(x = Risk, y = Returns)) +
geom_point(alpha = 0.5, color = "blue") +
geom_point(aes(x = min_var_us, y = min_var_us_return), color = "red", size = 3) +
ggtitle("Frontera Eficiente - EE.UU.") +
xlab("Riesgo (Volatilidad)") +
ylab("Rendimiento Esperado") +
theme_minimal()
## Warning in geom_point(aes(x = min_var_us, y = min_var_us_return), color = "red", : All aesthetics have length 1, but the data has 5000 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
## a single row.
Primero, se definen los datos para dos mercados distintos, la Bolsa Mexicana de Valores (BMV) y el mercado de Estados Unidos (EE.UU.), cada uno con puntos que representan diferentes niveles de riesgo y retorno.
Se define una función generate_curve que ajusta una
parábola a los puntos dados utilizando regresión lineal y devuelve los
puntos ajustados que forman la frontera eficiente.
Se utilizan gráficos para visualizar los puntos de datos originales y las fronteras eficientes ajustadas para cada mercado.
# Datos
points_bmv <- data.frame(
Risk = c(0.1, 0.2, 0.3, 0.4, 0.5),
Return = c(0.05, 0.10, 0.15, 0.18, 0.19)
)
points_us <- data.frame(
Risk = c(0.1, 0.2, 0.3, 0.4, 0.5),
Return = c(0.04, 0.08, 0.14, 0.16, 0.17)
)
# Función para ajustar una parábola y generar puntos
generate_curve <- function(data) {
fit <- lm(Return ~ poly(Risk, 2, raw = TRUE), data = data)
coeffs <- coef(fit)
risk_range <- seq(min(data$Risk), max(data$Risk), length.out = 100)
return_range <- coeffs[1] + coeffs[2] * risk_range + coeffs[3] * risk_range^2
data.frame(Risk = risk_range, Return = return_range)
}
# Generar curvas ajustadas
frontier_bmv <- generate_curve(points_bmv)
frontier_us <- generate_curve(points_us)
# Graficar puntos y fronteras eficientes
ggplot() +
geom_point(data = points_bmv, aes(x = Risk, y = Return), color = "blue") +
geom_line(data = frontier_bmv, aes(x = Risk, y = Return), color = "blue", linetype = "dashed") +
geom_point(data = points_us, aes(x = Risk, y = Return), color = "red") +
geom_line(data = frontier_us, aes(x = Risk, y = Return), color = "red", linetype = "dashed") +
labs(title = "Frontera Eficiente para BMV y EE.UU.",
x = "Riesgo",
y = "Retorno") +
theme_minimal()
# Graficar puntos y fronteras eficientes
ggplot() +
geom_point(data = points_bmv, aes(x = Risk, y = Return), color = "blue") +
geom_line(data = frontier_bmv, aes(x = Risk, y = Return), color = "blue", linetype = "dashed") +
labs(title = "Frontera Eficiente para BMV",
x = "Riesgo",
y = "Retorno") +
theme_minimal()
# Graficar puntos y fronteras eficientes
ggplot() +
geom_point(data = points_us, aes(x = Risk, y = Return), color = "red") +
geom_line(data = frontier_us, aes(x = Risk, y = Return), color = "red", linetype = "dashed") +
labs(title = "Frontera Eficiente para EE.UU.",
x = "Riesgo",
y = "Retorno") +
theme_minimal()
################
# Función para ajustar una parábola y obtener la frontier eficiente
obtener_frontier_eficiente <- function(points) {
# Ajustar una parábola a los puntos
fit <- lm(Return ~ poly(Risk, 2, raw = TRUE), data = points)
# Crear un rango de riesgos para graficar la parábola
risk_range <- seq(min(points$Risk), max(points$Risk), length.out = 100)
# Generar los retornos esperados usando la función de predicción
coef <- coef(fit)
expected_returns <- coef[1] + coef[2] * risk_range + coef[3] * risk_range^2
# Crear un data frame para la frontier eficiente
frontier <- data.frame(Risk = risk_range, Return = expected_returns)
return(frontier)
}
# Verificar la estructura de los datos
print("Estructura de points_bmv:")
## [1] "Estructura de points_bmv:"
str(points_bmv)
## 'data.frame': 5 obs. of 2 variables:
## $ Risk : num 0.1 0.2 0.3 0.4 0.5
## $ Return: num 0.05 0.1 0.15 0.18 0.19
print("Estructura de points_us:")
## [1] "Estructura de points_us:"
str(points_us)
## 'data.frame': 5 obs. of 2 variables:
## $ Risk : num 0.1 0.2 0.3 0.4 0.5
## $ Return: num 0.04 0.08 0.14 0.16 0.17
# Obtener las fronteras eficientes
frontier_bmv <- obtener_frontier_eficiente(points_bmv)
frontier_us <- obtener_frontier_eficiente(points_us)
# Verificar los primeros elementos de las fronteras eficientes
print("Frontier BMV:")
## [1] "Frontier BMV:"
print(head(frontier_bmv))
## Risk Return
## 1 0.1000000 0.04771429
## 2 0.1040404 0.05031157
## 3 0.1080808 0.05288554
## 4 0.1121212 0.05543618
## 5 0.1161616 0.05796350
## 6 0.1202020 0.06046750
print("Frontier EE.UU.:")
## [1] "Frontier EE.UU.:"
print(head(frontier_us))
## Risk Return
## 1 0.1000000 0.03571429
## 2 0.1040404 0.03823076
## 3 0.1080808 0.04072392
## 4 0.1121212 0.04319376
## 5 0.1161616 0.04564027
## 6 0.1202020 0.04806346
# Función para extraer datos de la frontier eficiente de manera segura
extract_frontier_data <- function(frontier) {
if (is.null(frontier) || !is.data.frame(frontier)) {
stop("El objeto frontier no es un data.frame o es nulo.")
}
# Verificar si las columnas 'Risk' y 'Return' existen
if (!all(c("Risk", "Return") %in% colnames(frontier))) {
stop("Las columnas necesarias 'Risk' y 'Return' no están presentes.")
}
data <- data.frame(
StdDev = frontier$Risk,
mean = frontier$Return
)
return(data)
}
# Intentar extraer los datos de la frontier eficiente
try({
opt_portfolios_bmv <- extract_frontier_data(frontier_bmv)
print(head(opt_portfolios_bmv)) # Mostrar los primeros registros para verificar
}, silent = FALSE)
## StdDev mean
## 1 0.1000000 0.04771429
## 2 0.1040404 0.05031157
## 3 0.1080808 0.05288554
## 4 0.1121212 0.05543618
## 5 0.1161616 0.05796350
## 6 0.1202020 0.06046750
# Verificar si los datos de la frontier eficiente fueron extraídos correctamente
if (exists("opt_portfolios_bmv")) {
# Encontrar el portafolio de mínima varianza
min_var_index_bmv <- which.min(opt_portfolios_bmv$StdDev)
min_var_portfolio_bmv <- opt_portfolios_bmv[min_var_index_bmv, ]
# Graficar los rendimientos y riesgos de los portafolios óptimos
p <- ggplot(opt_portfolios_bmv, aes(x = StdDev, y = mean)) +
geom_point(color = 'blue') +
geom_point(data = min_var_portfolio_bmv, aes(x = StdDev, y = mean), color = 'red', size = 3) +
ggtitle("Rendimientos y Riesgos de Portafolios Óptimos - BMV") +
xlab("Riesgo (Desviación Estándar)") +
ylab("Retorno Esperado") +
theme_minimal()
print(p)
} else {
print("No se pudieron extraer los datos de la frontier eficiente.")
}
# Comparación de fronteras eficientes
ggplot() +
geom_line(data = frontier_bmv, aes(x = Risk, y = Return), color = 'blue') +
geom_line(data = frontier_us, aes(x = Risk, y = Return), color = 'red') +
ggtitle("Comparación de Fronteras Eficientes - BMV vs EE.UU.") +
xlab("Riesgo (Desviación Estándar)") +
ylab("Retorno Esperado") +
theme_minimal()
frontier_bmvPrimero, vamos a verificar la estructura de frontier_bmv
utilizando str().
Vamos a corregir la creación de los data frames
frontier_bmv_df y frontier_us_df.
Para visualizar la distribución de los retornos, ajustaremos el
código para reflejar correctamente los nombres de los data frames de
retornos (returns_df_bmv y returns_df_us).
# También, verifica la estructura y contenido de frontier_bmv con str()
str(frontier_bmv)
## 'data.frame': 100 obs. of 2 variables:
## $ Risk : num 0.1 0.104 0.108 0.112 0.116 ...
## $ Return: num 0.0477 0.0503 0.0529 0.0554 0.058 ...
# Comparación de Fronteras Eficientes
frontier_bmv_df <- data.frame(
Risk = frontier_bmv$frontier[, "Risk"],
Return = frontier_bmv$frontier[, "Return"]
)
frontier_us_df <- data.frame(
Risk = frontier_us$frontier[, "Risk"],
Return = frontier_us$frontier[, "Return"]
)
# Distribución de Retornos
returns_df_bmv <- data.frame(Date = index(returns_bmv), coredata(returns_bmv))
returns_df_us <- data.frame(Date = index(returns_us), coredata(returns_us))
returns_melt_bmv <- melt(returns_df_bmv, id = "Date")
returns_melt_us <- melt(returns_df_us, id = "Date")
ggplot(returns_melt_bmv, aes(x = value, fill = variable)) +
geom_histogram(bins = 30, alpha = 0.5, position = "identity") +
ggtitle("Distribución de Retornos - BMV") +
xlab("Retornos Diarios") +
ylab("Frecuencia") +
theme_minimal()
ggplot(returns_melt_us, aes(x = value, fill = variable)) +
geom_histogram(bins = 30, alpha = 0.5, position = "identity") +
ggtitle("Distribución de Retornos - EE.UU.") +
xlab("Retornos Diarios") +
ylab("Frecuencia") +
theme_minimal()
Primero, definimos la función getCapitalMarketLine que
calculará los coeficientes del Capital Market Line (CML) utilizando los
retornos de los activos, el retorno del mercado y la tasa libre de
riesgo.
# Función para obtener los coeficientes del CML
getCapitalMarketLine <- function(returns_assets, returns_market, risk_free_rate) {
betas <- calculateCAPMBetas(returns_assets, returns_market)
expected_returns_assets <- apply(returns_assets, 2, mean)
market_return <- mean(returns_market)
cml <- data.frame(Asset = names(betas), Beta = betas, Expected_Return = risk_free_rate + betas * (market_return - risk_free_rate))
return(cml)
}
Luego, utilizamos esta función para obtener los coeficientes del CML
tanto para BMV como para EE.UU. Los datos de
aligned_returns_bmv,
aligned_returns_index_bmv, aligned_returns_us,
y aligned_returns_index_us deben ser los retornos de los
activos y del mercado alineados correctamente.
# Obtener el coeficiente del CML para la BMV y EE.UU.
risk_free_rate <- 0.05 # Tasa libre de riesgo hipotética del 5%
cml_bmv <- getCapitalMarketLine(aligned_returns_bmv, aligned_returns_index_bmv, risk_free_rate)
cml_us <- getCapitalMarketLine(aligned_returns_us, aligned_returns_index_us, risk_free_rate)
# Visualizar los resultados del CML
print("Coeficiente del CML - BMV:")
## [1] "Coeficiente del CML - BMV:"
print(cml_bmv)
## Asset Beta Expected_Return
## FEMSAUBD.MX.returns_market FEMSAUBD.MX.returns_market 0.7555859 0.012226922
## CEMEXCPO.MX.returns_market CEMEXCPO.MX.returns_market 1.1236303 -0.006172268
## GMEXICOB.MX.returns_market GMEXICOB.MX.returns_market 1.2701705 -0.013498074
print("Coeficiente del CML - EE.UU.:")
## [1] "Coeficiente del CML - EE.UU.:"
print(cml_us)
## Asset Beta Expected_Return
## ^IXIC.returns_market ^IXIC.returns_market 1.3119745 -0.014337561
## ^DJI.returns_market ^DJI.returns_market 0.7272216 0.014337976
## AAPL.returns_market AAPL.returns_market 1.0671939 -0.002333833
## MSFT.returns_market MSFT.returns_market 1.2039237 -0.009038887
## AMZN.returns_market AMZN.returns_market 1.5165033 -0.024367398
Si no dispones de datos reales para la CML, puedes generar datos
simulados para visualizar la línea. Aquí creamos datos simulados
cml_bmv y cml_us que representan la CML para
BMV y EE.UU. Esto se puede reemplazar con datos reales cuando los tengas
disponibles.
# Datos simulados para la Línea de Mercado de Capitales (CML) - deberías reemplazar con tus datos reales
cml_bmv <- data.frame(Risk = seq(-1, 0.3, length.out = 100), Return = seq(0.05, 0.25, length.out = 100))
cml_us <- data.frame(Risk = seq(-1, 0.3, length.out = 100), Return = seq(0.07, 0.27, length.out = 100))
Finalmente, podemos graficar la Frontera Eficiente junto con la CML
para BMV y EE.UU. Utilizaremos ggplot2 para realizar estas
visualizaciones.
# Graficar puntos y fronteras eficientes junto con CML para BMV
ggplot() +
geom_line(data = cml_bmv, aes(x = Risk, y = Return), color = 'blue', linetype = 'dashed') +
geom_line(data = frontier_bmv, aes(x = Risk, y = Return), color = "blue", linetype = "dashed") +
labs(title = "Frontera Eficiente y CML - BMV",
x = "Riesgo",
y = "Retorno") +
theme_minimal()
# Graficar puntos y fronteras eficientes junto con CML para EE.UU.
ggplot() +
geom_line(data = cml_us, aes(x = Risk, y = Return), color = 'red', linetype = 'dashed') +
geom_line(data = frontier_us, aes(x = Risk, y = Return), color = "red", linetype = "dashed") +
labs(title = "Frontera Eficiente y CML - EE.UU.",
x = "Riesgo",
y = "Retorno") +
theme_minimal()
Primero definimos la función calculateSharpeRatio que
calculará el Ratio de Sharpe para cada activo en base a sus retornos y
la tasa libre de riesgo.
Luego, calculamos el Ratio de Sharpe para los retornos de la BMV
(returns_bmv) y EE.UU. (returns_us),
utilizando una tasa libre de riesgo hipotética del 5%
(risk_free_rate).
Definimos la función plotSharpeRatio que permite
visualizar la relación entre el Ratio de Sharpe y la volatilidad para
diferentes mercados.
Finalmente, utilizamos la función plotSharpeRatio para
graficar el Ratio de Sharpe vs. la volatilidad para la BMV y EE.UU.,
utilizando los resultados calculados previamente.
#Función para calcular el Ratio de Sharpe
calculateSharpeRatio <- function(returns, risk_free_rate) {
expected_returns <- apply(returns, 2, mean)
volatilities <- apply(returns, 2, sd)
sharpe_ratios <- (expected_returns - risk_free_rate) / volatilities
return(sharpe_ratios)
}
# Calcular el Ratio de Sharpe para la BMV y EE.UU.
risk_free_rate <- 0.05 # Tasa libre de riesgo hipotética del 5%
sharpe_bmv <- calculateSharpeRatio(returns_bmv, risk_free_rate)
sharpe_us <- calculateSharpeRatio(returns_us, risk_free_rate)
# Mostrar resultados del Ratio de Sharpe
print("Ratio de Sharpe - BMV:")
## [1] "Ratio de Sharpe - BMV:"
print(sharpe_bmv)
## FEMSAUBD.MX CEMEXCPO.MX GMEXICOB.MX
## -2.973542 -2.600136 -2.377272
print("Ratio de Sharpe - EE.UU.:")
## [1] "Ratio de Sharpe - EE.UU.:"
print(sharpe_us)
## ^IXIC ^DJI AAPL MSFT AMZN
## -4.965479 -8.046563 -3.578982 -3.821820 -2.785942
# Función para graficar la relación entre el Ratio de Sharpe y la volatilidad
plotSharpeRatio <- function(sharpe_ratios, volatilities, market) {
df <- data.frame(Sharpe_Ratio = sharpe_ratios, Volatility = volatilities, Market = market)
ggplot(df, aes(x = Volatility, y = Sharpe_Ratio, color = Market)) +
geom_point() +
ggtitle("Ratio de Sharpe vs. Volatilidad") +
xlab("Volatilidad (Desviación Estándar)") +
ylab("Ratio de Sharpe")
}
# Graficar el Ratio de Sharpe vs. volatilidad para la BMV y EE.UU.
sharpe_bmv_df <- data.frame(Sharpe_Ratio = sharpe_bmv, Volatility = apply(returns_bmv, 2, sd), Market = "BMV")
sharpe_us_df <- data.frame(Sharpe_Ratio = sharpe_us, Volatility = apply(returns_us, 2, sd), Market = "US")
sharpe_combined_df <- rbind(sharpe_bmv_df, sharpe_us_df)
ggplot(sharpe_combined_df, aes(x = Volatility, y = Sharpe_Ratio, color = Market)) +
geom_point() +
ggtitle("Ratio de Sharpe vs. Volatilidad") +
xlab("Volatilidad (Desviación Estándar)") +
ylab("Ratio de Sharpe")
Para ilustrar varios análisis financieros con datos simulados, comenzamos generando un conjunto de datos de retornos diarios para dos acciones ficticias en el mercado BMV. Los datos abarcan del 1 de enero de 2020 al 1 de enero de 2023.
set.seed(123)
dates <- seq(as.Date("2020-01-01"), as.Date("2023-01-01"), by = "day")
returns_bmv <- data.frame(
Date = dates,
Stock1 = rnorm(length(dates), mean = 0.001, sd = 0.02),
Stock2 = rnorm(length(dates), mean = 0.0015, sd = 0.025)
)
returns_bmv <- returns_bmv[-1, ] # Eliminar primera fila para evitar NA
Para entender la relación entre los activos, calculamos y visualizamos la matriz de correlación entre las acciones.
# Calcular la matriz de correlación
correlation_matrix <- cor(returns_bmv[, -1])
correlation_melt <- melt(correlation_matrix)
# Graficar el heatmap de correlación
ggplot(correlation_melt, aes(Var1, Var2, fill = value)) +
geom_tile() +
scale_fill_gradient2(low = "blue", high = "red", mid = "white",
midpoint = 0, limit = c(-1,1), space = "Lab",
name="Correlation") +
ggtitle("Heatmap de Correlación - Ejemplo") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, vjust = 1, size = 8, hjust = 1))
Para visualizar cómo han evolucionado los retornos de las acciones a lo largo del tiempo, calculamos y graficamos los rendimientos acumulados.
# Calcular los rendimientos acumulados
cumulative_returns <- cumprod(1 + returns_bmv[, -1]) - 1
cumulative_returns <- cbind(returns_bmv$Date, cumulative_returns)
colnames(cumulative_returns) <- c("Date", "Stock1", "Stock2")
melted_returns <- melt(cumulative_returns, id.vars = "Date")
# Graficar los rendimientos acumulados
ggplot(melted_returns, aes(x = Date, y = value, color = variable)) +
geom_line() +
ggtitle("Rendimientos Acumulados - Ejemplo") +
xlab("Fecha") +
ylab("Rendimiento Acumulado") +
theme_minimal()
Para analizar la distribución de los retornos diarios de las acciones, creamos histogramas.
# Transformar los datos para el histograma
returns_melt_bmv <- melt(returns_bmv, id.vars = "Date")
# Graficar el histograma de rendimientos
ggplot(returns_melt_bmv, aes(x = value, fill = variable)) +
geom_histogram(bins = 30, alpha = 0.5, position = "identity") +
ggtitle("Distribución de Rendimientos - Ejemplo") +
xlab("Rendimientos Diarios") +
ylab("Frecuencia") +
theme_minimal()
Para explorar la relación lineal entre los rendimientos de las dos acciones, realizamos un análisis de regresión.
# Realizar un análisis de regresión
model <- lm(Stock1 ~ Stock2, data = returns_bmv)
# Graficar el análisis de regresión
ggplot(returns_bmv, aes(x = Stock2, y = Stock1)) +
geom_point() +
geom_smooth(method = "lm", color = "blue") +
ggtitle("Análisis de Regresión Lineal - Ejemplo") +
xlab("Rendimientos del Activo 2") +
ylab("Rendimientos del Activo 1") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
Se ajustaron curvas parabólicas para generar las fronteras eficientes de los portafolios en el mercado BMV y el mercado de EE.UU. Estas fronteras eficientes ayudan a identificar las combinaciones óptimas de riesgo y retorno para la diversificación del portafolio.
La Línea de Mercado de Capitales (CML) y el análisis de Betas proporcionaron una comprensión adicional de cómo se espera que los activos rindan en relación con el mercado, considerando una tasa libre de riesgo.
Este proyecto demuestra cómo diversas técnicas de análisis financiero pueden aplicarse para evaluar y optimizar portafolios de inversión. Desde la generación y análisis de datos simulados hasta la aplicación de conceptos teóricos como la frontera eficiente y el Ratio de Sharpe, se han cubierto múltiples aspectos esenciales en la gestión de inversiones.
Los métodos y visualizaciones presentados aquí proporcionan herramientas poderosas para inversores y analistas financieros, permitiendo una mejor comprensión del comportamiento del mercado y una toma de decisiones más informada. La adaptabilidad del código a datos reales amplía su aplicabilidad, ofreciendo una base sólida para futuros análisis y estudios en el campo de las finanzas.
Este proyecto subraya la importancia de un enfoque cuantitativo y sistemático en el análisis financiero, destacando cómo las técnicas estadísticas y econométricas pueden mejorar significativamente la gestión del riesgo y la optimización del retorno en los portafolios de inversión.