Análisis a activos de BMV y de EE.UU

Introducción

Objetivo del Proyecto

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.

Contexto

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.

Metodología

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:

  1. Recolección de Datos: Obtención de precios históricos de las acciones seleccionadas.

  2. Cálculo de Retornos: Cálculo de los retornos diarios a partir de los precios históricos.

  3. Optimización de Portafolios: Utilización de técnicas de optimización de portafolios para construir las fronteras eficientes para ambos mercados.

  4. Análisis de la Frontera Eficiente: Identificación de portafolios de mínima varianza y máximo Sharpe.

  5. Comparación de Fronteras: Comparación visual y cuantitativa de las fronteras eficientes de BMV y EE.UU.

  6. Análisis Adicional: Inclusión de la Línea del Mercado de Capitales (CML) y evaluación de ratios de Sharpe.

Importancia del Estudio

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.

Primera Parte del Código: Recolección y Preparación de Datos

Objetivo

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.

Instalación y Carga de Paquetes

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.

Definición de Activos

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"

Recolección de Datos

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.

Inspección de Datos

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

Combinación de Datos

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.

Verificación y Cálculo de Retornos

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.

Segunda Parte del Código: Análisis de Rendimientos y Optimización de Portafolios

Cálculo de Rendimientos Diarios

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"))

Estadísticas Descriptivas

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.

Correlación entre Activos

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

Cálculo de Estadísticas del Portafolio

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)
}

Optimización del Portafolio de Varianza Mínima

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:

  1. 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")
  2. 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")
  3. 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.006114

En 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):

Función para Calcular el CAPM y Betas

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)
}

Cálculo de Betas

  1. 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.2701705
  2. Para 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.5165033

La 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:

  1. 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.2701705
    1. Resumen 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.5165033

Este 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:

Graficar Portafolios de Mínima Varianza

  1. 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()

  2. 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.

Función para Calcular la Frontera Eficiente

# 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.

Definición de Datos

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.

Función para Generar la Frontera Eficiente

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.

Visualización de los Resultados

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()

Verificación de la Estructura de frontier_bmv

Primero, vamos a verificar la estructura de frontier_bmv utilizando str().

Comparación de Fronteras Eficientes

Vamos a corregir la creación de los data frames frontier_bmv_df y frontier_us_df.

Distribución de Retornos

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()

Función para obtener los coeficientes del CML

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)
}

Obtención de los coeficientes del CML para BMV y EE.UU.

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

Datos simulados para la Línea de Mercado de Capitales (CML)

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))

Graficar la Frontera Eficiente junto con la CML

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()

Función para calcular el Ratio de Sharpe

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.

Calcular el Ratio de Sharpe para la BMV y EE.UU.

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).

Función para graficar la relación entre el Ratio de Sharpe y la volatilidad

Definimos la función plotSharpeRatio que permite visualizar la relación entre el Ratio de Sharpe y la volatilidad para diferentes mercados.

Graficar el Ratio de Sharpe vs. volatilidad para la BMV y EE.UU.

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")

Generación de Datos Simulados

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

1. Heatmap de Correlación

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))

2. Rendimientos Acumulados

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()

3. Histograma de Rendimientos

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()

4. Análisis de Regresión

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'

1. Generación de Datos y Simulaciones

  • Se generaron datos simulados de retornos diarios para dos acciones ficticias en el mercado BMV. Esta simulación permitió crear un entorno controlado para aplicar y demostrar diversas técnicas de análisis financiero.

2. Análisis de Correlación

  • La matriz de correlación y su visualización en un heatmap proporcionaron una visión clara de la relación entre las diferentes acciones. Las correlaciones ayudan a entender cómo los activos se mueven en relación unos con otros, lo que es fundamental para la diversificación del portafolio.

3. Rendimientos Acumulados

  • La gráfica de rendimientos acumulados mostró cómo han evolucionado los retornos de las acciones a lo largo del tiempo. Esta visualización es útil para evaluar el desempeño de los activos en el largo plazo y tomar decisiones informadas sobre la gestión del portafolio.

4. Distribución de Rendimientos

  • Los histogramas de los rendimientos diarios permitieron analizar la distribución de los retornos, proporcionando información sobre la volatilidad y la posible presencia de retornos extremos. Este análisis es esencial para evaluar el riesgo asociado con cada activo.

5. Análisis de Regresión

  • El análisis de regresión entre los rendimientos de las dos acciones ofreció insights sobre la relación lineal entre los activos. Este tipo de análisis es útil para entender cómo un activo puede predecir el comportamiento de otro, facilitando la construcción de modelos de riesgo y retorno.

6. Fronteras Eficientes y Línea de Mercado de Capitales (CML)

  • 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.

7. Ratio de Sharpe

  • El cálculo y la visualización del Ratio de Sharpe para los portafolios en BMV y EE.UU. ofrecieron una métrica para evaluar el rendimiento ajustado por riesgo. Este ratio es crucial para comparar la eficiencia de diferentes portafolios.

Reflexiones Finales

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.