Skip to content

1 hidden cell

Obtener la data de Yahoo

  • Se obtuvo información de los tickers SPX, SHY y SHV, esto para aprovechar las funcionalidades del código y realizar distintos análisis al mismo tiempo.
  • El SHV representa el índice que invierte en bonos a corto plazo y el SHY el índice que invierte en bonos de 1 a 3 años.
  • Al pensar en un portafolio a largo plazo se obtuvo toda la información que se pudo, desde enero 2007 (que es donde el SHV comienza a operar), hasta el primer dato de septiembre 2024
  • La data extraída fue información diaria pero se hizo una transformación para usar solamente la información del primer día disponible de cada mes.
start <- as.Date("1962-01-01")
end <- today()

tickers = c('^SPX','SHY','SHV')


Data <- c()
for (i in 1:length(tickers)) {
  
  data <- getSymbols(tickers[i], src = "yahoo", from = start, to = end, auto.assign = FALSE)[,6]
  Data <- merge.xts(Data, data)
  
}
Data <- as.data.frame(Data)

data<- Data %>% 
  rownames_to_column() %>%   drop_na() %>%   mutate(fecha=as.POSIXct(rowname), month=yearmon(fecha)) %>% 
  group_by(month)%>%   dplyr::filter(fecha==min(fecha)) %>%  rename_with(~str_remove(., '.Adjusted')) %>%  ungroup() %>% 
  select(-month, -rowname, -fecha) %>% 
	mutate(across(
    where(is.numeric), 
    ~ c(NA, diff(.) / lag(.)[-1]), 
    .names = "{.col}.returns"
  ))

cumulative_value <- Data %>%  rownames_to_column() %>%   drop_na() %>%   mutate(fecha=as.POSIXct(rowname),month=yearmon(fecha)) %>% 
  group_by(month)%>%  dplyr::filter(fecha==min(fecha)) %>% rename_with(~str_remove(., '.Adjusted')) %>% 
  ungroup() %>%  select(-rowname,-month)

cumulative_value<- cumulative_value[,1:(length(tickers)+1)] %>% 
  mutate(across(1:length(tickers), ~ . / first(.))*100)

cumulative_value %>%  pivot_longer(-fecha,names_to = "asset", values_to="value") %>% 
  ggplot(aes(fecha,value,color=asset,fill=asset,group=asset))+
  geom_line(linewidth=1)+geom_point()+ labs(title = "Valor de los activos con el paso del tiempo (Base 100)")

returns<-data %>%
  select(ends_with(".returns")) %>% 
  drop_na()

for (i in 1:length(names(returns))) {
  
  column_name <- names(returns)[i] 
  
  print(
    returns %>%
      ggplot(aes(x = .data[[column_name]])) + 
      geom_histogram() +
      labs(title = paste("Histogram of", column_name))
  )
}

Se muestran los resultados de cada activo

  • SPX muestra el más alto rendimiento anual con un 7.98%, después viene SHY con 1.73% y SHV con 1.32%
  • Los bonos menores a 1 año son el instrumento más confiable, presenta una stdev menor al 1%, mientras que el SPX tiene una de 17.77%

Para ver el código que hice, dar click en "Hidden code" en cada módulo

Hidden code

Se generan los portafolios de dos activos, SPX y uno de los bonos

  • En lugar de generar una optimización, se generaron 100 posibilidades para cada portafolio donde el peso en SPX varió de 0% a 100%
  • Se utilizó una tasa libre de riesgo de 2% para el Sharpe Ratio

risk_free <-0.02

peso_spx <- seq(0, 1 , by = 0.01)

sharpe_ratio_final <-   c()
max_drawdowns_final <-   c()
annual_stdev_final <-   c()
annual_compounded_returns_final <-  c()



for (peso in peso_spx) {
  


weighted_returns_principal <- returns[,1] * peso
weighted_returns_others <- returns[,-1] * (1 - peso)  

weighted_returns <- weighted_returns_others %>%
  mutate(across(everything(), ~ .x + weighted_returns_principal[[1]])) %>% 
  rename_with(~str_remove(., '.returns')) 

weighted_returns_1 <- weighted_returns + 1

annual_compounded_returns <- weighted_returns_1  %>% 
  summarize( across(everything(), prod) ** (12 / nrow(weighted_returns)) - 1)

annual_stdev <- weighted_returns %>% 
        summarize( across(everything(), sd) * (12**0.5))

sharpe_ratio <-( ( annual_compounded_returns - risk_free ) / annual_stdev ) %>% 
  mutate(SPX_weight = peso)

initial_value <- 100
portfolio_value <- weighted_returns_1 %>% 
  mutate(across(everything(), ~ cumprod(.) * initial_value))

# Function to calculate maximum drawdown
max_drawdown <- function(x) {
  cummax_x <- cummax(x)                    # Cumulative max
  drawdown <- (x - cummax_x) / cummax_x     # Calculate drawdown as percentage
  return(min(drawdown))                     # Return the maximum drawdown (most negative value)
}

# Apply the function to each column of portfolio_values
max_drawdowns <- portfolio_value %>%
  summarise(across(everything(), max_drawdown))  %>% 
  mutate(SPX_weight = peso)

sharpe_ratio_final <-   rbind(sharpe_ratio_final,sharpe_ratio)
max_drawdowns_final <-   rbind(max_drawdowns_final,max_drawdowns)
annual_compounded_returns_final <-   rbind(annual_compounded_returns_final,annual_compounded_returns)
annual_stdev_final <-   rbind(annual_stdev_final,annual_stdev)
}

Se muestran los resultados de las simulaciones

  • Al tener más peso en los activos que siguen a los bonos el MaxDrawDown disminuye, los mínimos se encuentran cuando no se invierte nada en el SPX.
  • Con los bonos entre 1 y 3 años el mayor Sharpe Ratio se encuentra donde se invierte 63% en ellos, mientras que para los bonos a corto plazo es donde se invierte 34% en ellos.
  • Como se podría pensar, entre más se invierta en el SPX, el riesgo y los rendimientos son mayores
Hidden code
Hidden code

Nos centraremos en el portafolio con activo SHV

  • El activo con madurez a corto plazo tiene un menor riesgo que el de 1-3 años con una stdev de 0.6% vs 1.6%
  • Filtrando las columnas nos damos cuenta que:
    • El portafolio con 0% SPX y 100% SHV tiene el menor DrawDown de todos con un -0.3%
      • Tiene un rendimiento de 1.32% y una desviación estándar de 0.56%
    • El portafolio con 66% SPX y 34% SHV tiene el mayor Sharpe Ratio posible con un 0.3471
      • Tiene un rendimiento de 6.06% y una desviación estándar de 11.71%
    • El portafolio de 100% SPX maximiza el retorno con un 7.98%
    • El portafolio con 0% SPX minimiza la desviación estándar al 0.56%
Hidden code