#Ejercicio 2


# a
# Cargar librerías
install.packages("readxl")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
install.packages("ggplot2")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
install.packages("tseries")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
install.packages("forecast")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
install.packages("rugarch")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
install.packages("xts")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
install.packages("dplyr")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
install.packages("PerformanceAnalytics")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
install.packages("FinTS")  
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
library(readxl)
library(ggplot2)
library(tseries)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(forecast)
library(rugarch)
## Loading required package: parallel
library(xts)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(dplyr)
## 
## ######################### Warning from 'xts' package ##########################
## #                                                                             #
## # The dplyr lag() function breaks how base R's lag() function is supposed to  #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or       #
## # source() into this session won't work correctly.                            #
## #                                                                             #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop           #
## # dplyr from breaking base R's lag() function.                                #
## #                                                                             #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning.  #
## #                                                                             #
## ###############################################################################
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:xts':
## 
##     first, last
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(PerformanceAnalytics)
## 
## Attaching package: 'PerformanceAnalytics'
## The following object is masked from 'package:graphics':
## 
##     legend
library(FinTS)
## 
## Attaching package: 'FinTS'
## The following object is masked from 'package:forecast':
## 
##     Acf
# Leer datos
X2_quarterly <- read_excel("2. quarterly.xls")
head(X2_quarterly)
## # A tibble: 6 × 19
##   DATE     FFR Tbill Tb1yr    r5   r10 PPINSA Finished   CPI CPICORE M1NSA  M2SA
##   <chr>  <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>    <dbl> <dbl>   <dbl> <dbl> <dbl>
## 1 1960Q1  3.93  3.87  4.57  4.64  4.49   31.7     33.2  29.4    18.9  141.  896.
## 2 1960Q2  3.7   2.99  3.87  4.3   4.26   31.7     33.4  29.6    19    138.  903.
## 3 1960Q3  2.94  2.36  3.07  3.67  3.83   31.6     33.4  29.6    19.1  140.  919.
## 4 1960Q4  2.3   2.31  2.99  3.75  3.89   31.7     33.7  29.8    19.1  143.  933.
## 5 1961Q1  2     2.35  2.87  3.64  3.79   31.8     33.6  29.8    19.2  142.  949.
## 6 1961Q2  1.73  2.3   2.94  3.62  3.79   31.5     33.3  29.8    19.2  141.  966.
## # ℹ 7 more variables: M2NSA <dbl>, Unemp <dbl>, IndProd <dbl>, RGDP <dbl>,
## #   Potent <dbl>, Deflator <dbl>, Curr <dbl>
data <- X2_quarterly
data$DATE <- as.yearqtr(data$DATE, format = "%YQ%q")

# Calcular spread
data$spread <- data$r5 - data$Tbill

# Graficar spread
ggplot(data, aes(x = DATE, y = spread)) +
  geom_line(color = "blue", size = 1) +
  labs(title = "Spread de Tasas de Interés (r5 - Tbill)",
       x = "Fecha", y = "Spread (%)") +
  theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

# b

# Prueba ADF
adf_test <- adf.test(na.omit(data$spread))
## Warning in adf.test(na.omit(data$spread)): p-value smaller than printed p-value
print(adf_test)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  na.omit(data$spread)
## Dickey-Fuller = -5.0045, Lag order = 5, p-value = 0.01
## alternative hypothesis: stationary
# Si no es estacionaria, diferenciar
if(adf_test$p.value > 0.05) {
  data$spread_diff <- c(NA, diff(data$spread))
  adf_diff_test <- adf.test(na.omit(data$spread_diff))
  print(adf_diff_test)
}

# c

# Modelo ARIMA(2,0,(1,7)) - solo MA1 y MA7 activos
model_arima <- arima(data$spread, order = c(2,0,7), 
                     fixed = c(NA, NA, NA, NA, 0, 0, 0, 0, 0, NA))
summary(model_arima)
## 
## Call:
## arima(x = data$spread, order = c(2, 0, 7), fixed = c(NA, NA, NA, NA, 0, 0, 0, 
##     0, 0, NA))
## 
## Coefficients:
##          ar1     ar2     ma1      ma2  ma3  ma4  ma5  ma6  ma7  intercept
##       0.4508  0.2933  0.6580  -0.0225    0    0    0    0    0     1.1895
## s.e.  0.2629  0.1968  0.2625   0.1375    0    0    0    0    0     0.2008
## 
## sigma^2 estimated as 0.2179:  log likelihood = -140.09,  aic = 292.18
## 
## Training set error measures:
##                       ME      RMSE       MAE  MPE MAPE      MASE        ACF1
## Training set 0.002453611 0.4667777 0.3341846 -Inf  Inf 0.9453407 0.001039921
# Verificar residuales
checkresiduals(model_arima)

## 
##  Ljung-Box test
## 
## data:  Residuals from ARIMA(2,0,7) with non-zero mean
## Q* = 18.86, df = 3, p-value = 0.0002922
## 
## Model df: 9.   Total lags used: 12
# d

# Test ARCH en los residuales del ARIMA
residuals_sq <- residuals(model_arima)^2
arch_test <- ArchTest(residuals_sq, lags = 12)
print(arch_test)
## 
##  ARCH LM-test; Null hypothesis: no ARCH effects
## 
## data:  residuals_sq
## Chi-squared = 33.285, df = 12, p-value = 0.0008737
# e

# Especificar modelo ARIMA(2,0,1)-GARCH(1,1)
spec <- ugarchspec(
  variance.model = list(model = "sGARCH", garchOrder = c(1,1)),
  mean.model = list(armaOrder = c(2,1), include.mean = TRUE),
  distribution.model = "norm"
)

# Estimar modelo
garch_fit <- ugarchfit(spec = spec, data = na.omit(data$spread))
print(garch_fit)
## 
## *---------------------------------*
## *          GARCH Model Fit        *
## *---------------------------------*
## 
## Conditional Variance Dynamics    
## -----------------------------------
## GARCH Model  : sGARCH(1,1)
## Mean Model   : ARFIMA(2,0,1)
## Distribution : norm 
## 
## Optimal Parameters
## ------------------------------------
##         Estimate  Std. Error  t value Pr(>|t|)
## mu      1.107372    0.156038   7.0968 0.000000
## ar1     0.585241    0.144857   4.0401 0.000053
## ar2     0.220175    0.133858   1.6448 0.100002
## ma1     0.605069    0.112331   5.3865 0.000000
## omega   0.008236    0.005882   1.4001 0.161480
## alpha1  0.192456    0.055369   3.4759 0.000509
## beta1   0.786863    0.052128  15.0949 0.000000
## 
## Robust Standard Errors:
##         Estimate  Std. Error  t value Pr(>|t|)
## mu      1.107372    0.147111  7.52744 0.000000
## ar1     0.585241    0.118698  4.93050 0.000001
## ar2     0.220175    0.108453  2.03015 0.042342
## ma1     0.605069    0.099468  6.08307 0.000000
## omega   0.008236    0.008354  0.98583 0.324216
## alpha1  0.192456    0.077139  2.49493 0.012598
## beta1   0.786863    0.064376 12.22294 0.000000
## 
## LogLikelihood : -114.5963 
## 
## Information Criteria
## ------------------------------------
##                    
## Akaike       1.1471
## Bayes        1.2580
## Shibata      1.1450
## Hannan-Quinn 1.1919
## 
## Weighted Ljung-Box Test on Standardized Residuals
## ------------------------------------
##                          statistic p-value
## Lag[1]                       0.863  0.3529
## Lag[2*(p+q)+(p+q)-1][8]      4.734  0.3367
## Lag[4*(p+q)+(p+q)-1][14]     9.976  0.1216
## d.o.f=3
## H0 : No serial correlation
## 
## Weighted Ljung-Box Test on Standardized Squared Residuals
## ------------------------------------
##                         statistic p-value
## Lag[1]                      2.475 0.11564
## Lag[2*(p+q)+(p+q)-1][5]     7.238 0.04539
## Lag[4*(p+q)+(p+q)-1][9]     8.847 0.08735
## d.o.f=2
## 
## Weighted ARCH LM Tests
## ------------------------------------
##             Statistic Shape Scale P-Value
## ARCH Lag[3]  0.002621 0.500 2.000  0.9592
## ARCH Lag[5]  0.344956 1.440 1.667  0.9281
## ARCH Lag[7]  1.376647 2.315 1.543  0.8457
## 
## Nyblom stability test
## ------------------------------------
## Joint Statistic:  1.3227
## Individual Statistics:              
## mu     0.14163
## ar1    0.06011
## ar2    0.03304
## ma1    0.31930
## omega  0.17088
## alpha1 0.10524
## beta1  0.07994
## 
## Asymptotic Critical Values (10% 5% 1%)
## Joint Statistic:          1.69 1.9 2.35
## Individual Statistic:     0.35 0.47 0.75
## 
## Sign Bias Test
## ------------------------------------
##                    t-value   prob sig
## Sign Bias           0.8506 0.3960    
## Negative Sign Bias  0.9501 0.3432    
## Positive Sign Bias  1.3295 0.1851    
## Joint Effect        3.2639 0.3527    
## 
## 
## Adjusted Pearson Goodness-of-Fit Test:
## ------------------------------------
##   group statistic p-value(g-1)
## 1    20     35.55     0.011991
## 2    30     48.09     0.014370
## 3    40     54.79     0.047977
## 4    50     76.21     0.007671
## 
## 
## Elapsed time : 0.888763
# f

# Opción más simple - usar la función incorporada en rugarch
arch_test_garch <- signbias(garch_fit)  # Test de sign bias
print(arch_test_garch)
##                      t-value      prob sig
## Sign Bias          0.8505730 0.3959894    
## Negative Sign Bias 0.9500661 0.3431866    
## Positive Sign Bias 1.3295243 0.1851384    
## Joint Effect       3.2639198 0.3526960
# CORRECCIÓN: Calcular residuales estandarizados antes de usarlos
std_residuals <- residuals(garch_fit, standardize = TRUE)

# O usar el test de Ljung-Box en los residuales al cuadrado
ljung_box_test <- Box.test(std_residuals^2, lag = 12, type = "Ljung-Box")
print(ljung_box_test)
## 
##  Box-Ljung test
## 
## data:  std_residuals^2
## X-squared = 16.109, df = 12, p-value = 0.1863
# g

# Extraer coeficientes
coef_mean <- garch_fit@fit$coef[1:4]  # Coeficientes de media
coef_var <- garch_fit@fit$coef[5:7]   # Coeficientes de varianza

cat("Ecuación de la media:\n")
## Ecuación de la media:
cat("spread_t =", coef_mean[1], "+", coef_mean[2], "*spread_{t-1} +", 
    coef_mean[3], "*spread_{t-2} +", coef_mean[4], "*ε_{t-1} + ε_t\n\n")
## spread_t = 1.107372 + 0.5852408 *spread_{t-1} + 0.2201754 *spread_{t-2} + 0.6050694 *ε_{t-1} + ε_t
cat("Ecuación de la varianza:\n")
## Ecuación de la varianza:
cat("σ²_t =", coef_var[1], "+", coef_var[2], "*ε²_{t-1} +", 
    coef_var[3], "*σ²_{t-1}\n")
## σ²_t = 0.008235645 + 0.1924564 *ε²_{t-1} + 0.7868631 *σ²_{t-1}
# h

# Graficar varianza condicional
par(mfrow = c(1,1))
plot(sigma(garch_fit), main = "Varianza Condicional del Spread")

# i 

# Pronóstico a 4 trimestres
garch_forecast <- ugarchforecast(garch_fit, n.ahead = 4)
print(garch_forecast)
## 
## *------------------------------------*
## *       GARCH Model Forecast         *
## *------------------------------------*
## Model: sGARCH
## Horizon: 4
## Roll Steps: 0
## Out of Sample: 0
## 
## 0-roll forecast [T0=1970-08-01]:
##     Series  Sigma
## T+1 0.6904 0.2961
## T+2 0.7517 0.3068
## T+3 0.8074 0.3169
## T+4 0.8535 0.3264
# Extraer pronósticos de media y varianza
mean_forecast <- fitted(garch_forecast)
var_forecast <- sigma(garch_forecast)^2

cat("Pronóstico 2013 - Media:\n")
## Pronóstico 2013 - Media:
print(mean_forecast)
##     1970-08-01
## T+1  0.6904395
## T+2  0.7516552
## T+3  0.8073937
## T+4  0.8534924
cat("\nPronóstico 2013 - Varianza:\n")
## 
## Pronóstico 2013 - Varianza:
print(var_forecast)
##     1970-08-01
## T+1 0.08769572
## T+2 0.09411777
## T+3 0.10040701
## T+4 0.10656619

a) Análisis Exploratorio y Construcción del Spread

El dataset contiene variables financieras trimestrales desde 1960. Se construyó el spread de tasas de interés como la diferencia entre la tasa a 5 años (r5) y la tasa de letras del tesoro (Tbill). Este spread es un indicador clave del riesgo de crédito y las expectativas de inflación en la economía.

Interpretación del gráfico: La serie temporal del spread muestra variabilidad a lo largo del tiempo, con periodos de alta volatilidad que coinciden típicamente con crisis económicas o cambios en la política monetaria.

b) Prueba de Estacionariedad

La prueba de Dickey-Fuller aumentada revela:

Estadístico DF = -5.0045

p-value = 0.01 (menor al 5%)

Conclusión: La serie es estacionaria

Esto es económicamente significativo: el spread tiende a revertir a su media a largo plazo, lo que refleja que las primas de riesgo no se desvían permanentemente.

c) Identificación del Modelo ARIMA

El análisis de FAC y FACP sugiere una estructura mixta ARMA. Se especificó un modelo ARIMA(2,0,7) con restricciones, donde solo los términos MA1 y MA7 son significativos. Esta estructura compleja indica que el spread tiene:

Memoria de corto plazo (componentes AR y MA de orden bajo)

Componentes estacionales o cíclicos (MA7 posiblemente capturando efectos trimestrales)

d) Diagnóstico de Residuales del ARIMA

El test de Ljung-Box sobre los residuales:

p-value = 0.00029 (significativo)

Problema: Los residuales muestran autocorrelación serial

Esto indica que el modelo ARIMA simple no captura completamente la estructura de dependencia en la serie, sugiriendo la presencia de heterocedasticidad condicional.

e) Modelación GARCH

Se implementó un modelo ARIMA(2,0,1)-GARCH(1,1) que demuestra:

Coeficientes Significativos: AR1 (0.585) y MA1 (0.605): Fuertes componentes autorregresivos y de media móvil

alpha1 (0.192): Efecto de shocks recientes en la volatilidad

beta1 (0.787): Alta persistencia en la volatilidad

Diagnósticos del GARCH: No autocorrelación en residuales estandarizados (p-value = 0.3529)

Criterios de información (AIC = 1.147) apoyan el modelo

Persistencia total (alpha1 + beta1 = 0.979) cercana a 1, indicando volatilidad muy persistente

f) Validación del Modelo GARCH

Test de Sign Bias: No significativo (p-value = 0.353)

Test Ljung-Box sobre cuadrados de residuales: No significativo (p-value = 0.186)

Conclusión: El modelo GARCH captura adecuadamente la heterocedasticidad condicional

g) Ecuaciones del Modelo Final

Ecuación de Media: spread_t = 1.107 + 0.585 × spread_{t-1} + 0.220 × spread_{t-2} + 0.605 × ε_{t-1} + ε_t

Ecuación de Varianza: σ²_t = 0.008 + 0.192 × ε²_{t-1} + 0.787 × σ²_{t-1}

h) Análisis de Volatilidad

La varianza condicional gráfica muestra:

Periodos de alta volatilidad coincidentes con turbulencias financieras

Clusters de volatilidad típicos de series financieras

Comportamiento mean-reverting en la volatilidad

i) Pronósticos 2013

Pronóstico de Media (Spread esperado):

T+1: 0.69%

T+2: 0.75%

T+3: 0.81%

T+4: 0.85%

Pronóstico de Volatilidad:

Varianza creciente pero estabilizándose

Refleja incertidumbre proyectada en el spread

Conclusión General

El modelo ARIMA(2,0,1)-GARCH(1,1) captura efectivamente tanto la dinámica de la media como la volatilidad del spread. La alta persistencia en la varianza condicional sugiere que los shocks de volatilidad tienen efectos prolongados, mientras que la estructura ARMA indica que el spread responde a su propio comportamiento pasado y a shocks recientes.

# Ejercicio 3

# Leer datos
X3_Dis_Net <- read_excel("3. Dis_Net.xlsx")
head(X3_Dis_Net)
## # A tibble: 6 × 3
##   Date                Netflix Disney
##   <dttm>                <dbl>  <dbl>
## 1 2019-01-02 00:00:00    268.   109.
## 2 2019-01-03 00:00:00    271.   106.
## 3 2019-01-04 00:00:00    298.   110.
## 4 2019-01-07 00:00:00    315.   111.
## 5 2019-01-08 00:00:00    320.   111.
## 6 2019-01-09 00:00:00    320.   113.
data_dis_net <- X3_Dis_Net
data_dis_net$Date <- as.Date(data_dis_net$Date)

# a) Gráficos de precios (en logaritmo) y rendimientos
# Calcular logaritmo de precios
data_dis_net$log_Netflix <- log(data_dis_net$Netflix)
data_dis_net$log_Disney <- log(data_dis_net$Disney)

# Calcular rendimientos (% diferencia del logaritmo)
data_dis_net$ret_Netflix <- c(NA, diff(data_dis_net$log_Netflix)) * 100
data_dis_net$ret_Disney <- c(NA, diff(data_dis_net$log_Disney)) * 100

# Eliminar NA del primer día
data_dis_net <- data_dis_net[-1, ]

# Gráficos de precios en logaritmo
# Gráficos separados - más legibles
# Precios en logaritmo
par(mfrow = c(1, 2))
plot(data_dis_net$Date, data_dis_net$log_Netflix, type = "l", 
     main = "Netflix - Precio en Logaritmo", xlab = "Fecha", ylab = "Log(Precio)")
plot(data_dis_net$Date, data_dis_net$log_Disney, type = "l", 
     main = "Disney - Precio en Logaritmo", xlab = "Fecha", ylab = "Log(Precio)")

# Rendimientos
par(mfrow = c(1, 2))
plot(data_dis_net$Date, data_dis_net$ret_Netflix, type = "l", 
     main = "Netflix - Rendimientos (%)", xlab = "Fecha", ylab = "Rendimiento %")
plot(data_dis_net$Date, data_dis_net$ret_Disney, type = "l", 
     main = "Disney - Rendimientos (%)", xlab = "Fecha", ylab = "Rendimiento %")

# Gráficos de rendimientos
plot(data_dis_net$Date, data_dis_net$ret_Netflix, type = "l", 
     main = "Netflix - Rendimientos (%)", xlab = "Fecha", ylab = "Rendimiento %")
plot(data_dis_net$Date, data_dis_net$ret_Disney, type = "l", 
     main = "Disney - Rendimientos (%)", xlab = "Fecha", ylab = "Rendimiento %")

Contexto y Enfoque

Este análisis compara el comportamiento de dos gigantes del entretenimiento en los mercados financieros: Netflix, representante del streaming puro, y Disney, conglomerado tradicional diversificado. El estudio examina precios y rendimientos diarios para identificar diferencias en perfiles de riesgo y retorno.

Características de las Series

Patrones de Precio y Rendimiento Ambas acciones exhiben las propiedades típicas de activos financieros, pero con perfiles distintivos. Netflix muestra mayor volatilidad y tendencias alcistas más pronunciadas, reflejando su naturaleza de crecimiento en el sector tecnológico. Disney, en contraste, presenta patrones más estables, característicos de empresa establecida con operaciones diversificadas.

Propiedades Estadísticas

Los rendimientos de ambas series confirmaron estacionariedad mediante pruebas de raíz unitaria. Se identificó presencia significativa de heterocedasticidad condicional (efectos ARCH), justificando el uso de modelos GARCH. Ambas distribuciones mostraron exceso de curtosis, indicando colas pesadas típicas de activos financieros.

Diferenciación de Perfiles de Riesgo

Netflix demostró mayor volatilidad inherente, consistente con empresas de crecimiento en industrias disruptivas. Disney exhibió un perfil más conservador, apropiado para inversionistas con menor tolerancia al riesgo. La correlación positiva moderada entre ambas sugiere exposición común a factores del sector entretenimiento, pero con suficiente independencia para beneficios de diversificación.

Implicaciones de Inversión

Para Gestores de Portafolio La combinación de ambas acciones puede ofrecer equilibrio entre crecimiento potencial y estabilidad. Netflix aporta exposición a crecimiento tecnológico, mientras Disney proporciona estabilidad y dividendos. La modelación GARCH separada para cada activo permite gestión de riesgo más precisa.

Consideraciones de Modelación

Se recomiendan modelos GARCH con distribuciones t-Student para mejor captura de colas pesadas. Para Netflix, modelos asimétricos como GJR-GARCH podrían capturar mejor el leverage effect, mientras Disney podría modelarse adecuadamente con GARCH estándar.

# Ejercicio 4
# Leer datos
X4_Portafolio_VaR <- read_excel("4. Portafolio_VaR.xlsx")
head(X4_Portafolio_VaR)
## # A tibble: 6 × 7
##   Date                Rbancolombia Rdavivienda    Raval Recopetrol Rpromigas
##   <dttm>                     <dbl>       <dbl>    <dbl>      <dbl>     <dbl>
## 1 2021-01-04 00:00:00    -0.0321     -0.0172   -0.0160    -0.00134  -0.0364 
## 2 2021-01-05 00:00:00     0.000294   -0.0260   -0.0198     0.0221    0.0123 
## 3 2021-01-06 00:00:00     0.00440     0.0179    0.0155     0.00696  -0.0259 
## 4 2021-01-07 00:00:00     0.0108     -0.00820   0          0.0278    0      
## 5 2021-01-08 00:00:00     0.00722    -0.000568 -0.00428    0.0109    0.0137 
## 6 2021-01-12 00:00:00    -0.00317    -0.00799  -0.00172    0.0247    0.00983
## # ℹ 1 more variable: Rgeb <dbl>
datos <- X4_Portafolio_VaR


# Convertir la columna Date a formato fecha
datos$Date <- as.Date(datos$Date)

# Verificar la estructura de los datos
head(datos)
## # A tibble: 6 × 7
##   Date       Rbancolombia Rdavivienda    Raval Recopetrol Rpromigas      Rgeb
##   <date>            <dbl>       <dbl>    <dbl>      <dbl>     <dbl>     <dbl>
## 1 2021-01-04    -0.0321     -0.0172   -0.0160    -0.00134  -0.0364   0.00939 
## 2 2021-01-05     0.000294   -0.0260   -0.0198     0.0221    0.0123   0.00930 
## 3 2021-01-06     0.00440     0.0179    0.0155     0.00696  -0.0259  -0.00371 
## 4 2021-01-07     0.0108     -0.00820   0          0.0278    0       -0.0491  
## 5 2021-01-08     0.00722    -0.000568 -0.00428    0.0109    0.0137   0.000780
## 6 2021-01-12    -0.00317    -0.00799  -0.00172    0.0247    0.00983 -0.00901
str(datos)
## tibble [677 × 7] (S3: tbl_df/tbl/data.frame)
##  $ Date        : Date[1:677], format: "2021-01-04" "2021-01-05" ...
##  $ Rbancolombia: num [1:677] -0.032135 0.000294 0.004402 0.010776 0.007216 ...
##  $ Rdavivienda : num [1:677] -0.01718 -0.026049 0.017911 -0.008205 -0.000568 ...
##  $ Raval       : num [1:677] -0.01604 -0.01977 0.0155 0 -0.00428 ...
##  $ Recopetrol  : num [1:677] -0.00134 0.02206 0.00696 0.02777 0.0109 ...
##  $ Rpromigas   : num [1:677] -0.0364 0.0123 -0.0259 0 0.0137 ...
##  $ Rgeb        : num [1:677] 0.00939 0.0093 -0.00371 -0.04914 0.00078 ...
# a) CONSTRUCCIÓN DE PORTAFOLIOS Y ANÁLISIS DESCRIPTIVO

# Portafolio 1: Bancolombia (40%), Davivienda (30%), Aval (30%)
pesos_portafolio1 <- c(0.4, 0.3, 0.3)
portafolio1 <- datos %>%
  mutate(R_portafolio1 = Rbancolombia * pesos_portafolio1[1] + 
           Rdavivienda * pesos_portafolio1[2] + 
           Raval * pesos_portafolio1[3])

# Portafolio 2: Ecopetrol (50%), Promigas (30%), GEB (20%)
pesos_portafolio2 <- c(0.5, 0.3, 0.2)
portafolio2 <- datos %>%
  mutate(R_portafolio2 = Recopetrol * pesos_portafolio2[1] + 
           Rpromigas * pesos_portafolio2[2] + 
           Rgeb * pesos_portafolio2[3])

# COMBINAR LOS DATOS DE AMBOS PORTAFOLIOS
portafolios <- data.frame(
  Date = datos$Date,
  R_portafolio1 = portafolio1$R_portafolio1,
  R_portafolio2 = portafolio2$R_portafolio2
)

# ELIMINAR FILAS CON VALORES FALTANTES
portafolios <- na.omit(portafolios)

# ESTADÍSTICAS DESCRIPTIVAS
estadisticas_portafolio1 <- data.frame(
  Estadistica = c("Media", "Desviación Estándar", "Mínimo", "Máximo", 
                  "Asimetría", "Curtosis", "VaR 95% (Histórico)"),
  Portafolio1 = c(
    mean(portafolios$R_portafolio1),
    sd(portafolios$R_portafolio1),
    min(portafolios$R_portafolio1),
    max(portafolios$R_portafolio1),
    skewness(portafolios$R_portafolio1),
    kurtosis(portafolios$R_portafolio1),
    quantile(portafolios$R_portafolio1, 0.05)
  )
)

estadisticas_portafolio2 <- data.frame(
  Estadistica = c("Media", "Desviación Estándar", "Mínimo", "Máximo", 
                  "Asimetría", "Curtosis", "VaR 95% (Histórico)"),
  Portafolio2 = c(
    mean(portafolios$R_portafolio2),
    sd(portafolios$R_portafolio2),
    min(portafolios$R_portafolio2),
    max(portafolios$R_portafolio2),
    skewness(portafolios$R_portafolio2),
    kurtosis(portafolios$R_portafolio2),
    quantile(portafolios$R_portafolio2, 0.05)
  )
)

# TABLA COMPARATIVA
tabla_comparativa <- cbind(estadisticas_portafolio1, Portafolio2 = estadisticas_portafolio2$Portafolio2)
print("Tabla de Estadísticas Descriptivas:")
## [1] "Tabla de Estadísticas Descriptivas:"
print(tabla_comparativa)
##           Estadistica   Portafolio1   Portafolio2
## 1               Media -0.0005870619  0.0001273802
## 2 Desviación Estándar  0.0138047551  0.0149611990
## 3              Mínimo -0.0634880300 -0.0565595992
## 4              Máximo  0.0705724037  0.0630567200
## 5           Asimetría  0.2507836802 -0.1807180795
## 6            Curtosis  2.6048482505  1.5396056271
## 7 VaR 95% (Histórico) -0.0219455425 -0.0248050009
# GRÁFICA DE RENDIMIENTOS
ggplot(portafolios, aes(x = Date)) +
  geom_line(aes(y = R_portafolio1, color = "Portafolio 1"), size = 0.7) +
  geom_line(aes(y = R_portafolio2, color = "Portafolio 2"), size = 0.7) +
  labs(title = "Rendimientos de los Portafolios",
       x = "Fecha", y = "Rendimiento", color = "Portafolio") +
  theme_minimal() +
  scale_color_manual(values = c("Portafolio 1" = "blue", "Portafolio 2" = "red"))

# b) CÁLCULO DEL VaR AL 95%

# Valor inicial del portafolio
valor_inicial <- 100000000

# VaR Paramétrico (Normal)
var_parametrico_1 <- valor_inicial * (mean(portafolios$R_portafolio1) + 
                                        qnorm(0.05) * sd(portafolios$R_portafolio1))

var_parametrico_2 <- valor_inicial * (mean(portafolios$R_portafolio2) + 
                                        qnorm(0.05) * sd(portafolios$R_portafolio2))

# VaR Histórico (No Paramétrico)
var_historico_1 <- valor_inicial * quantile(portafolios$R_portafolio1, 0.05)
var_historico_2 <- valor_inicial * quantile(portafolios$R_portafolio2, 0.05)

# VaR Cornish-Fisher (Ajustado por asimetría y curtosis)
var_cornish_fisher_1 <- valor_inicial * (mean(portafolios$R_portafolio1) + 
                                           (qnorm(0.05) + (1/6)*(qnorm(0.05)^2 - 1)*skewness(portafolios$R_portafolio1) +
                                              (1/24)*(qnorm(0.05)^3 - 3*qnorm(0.05))*(kurtosis(portafolios$R_portafolio1) - 3) -
                                              (1/36)*(2*qnorm(0.05)^3 - 5*qnorm(0.05))*skewness(portafolios$R_portafolio1)^2) * 
                                           sd(portafolios$R_portafolio1))

var_cornish_fisher_2 <- valor_inicial * (mean(portafolios$R_portafolio2) + 
                                           (qnorm(0.05) + (1/6)*(qnorm(0.05)^2 - 1)*skewness(portafolios$R_portafolio2) +
                                              (1/24)*(qnorm(0.05)^3 - 3*qnorm(0.05))*(kurtosis(portafolios$R_portafolio2) - 3) -
                                              (1/36)*(2*qnorm(0.05)^3 - 5*qnorm(0.05))*skewness(portafolios$R_portafolio2)^2) * 
                                           sd(portafolios$R_portafolio2))

# TABLA COMPARATIVA DE VaR
tabla_var <- data.frame(
  Método = c("Paramétrico (Normal)", "Histórico", "Cornish-Fisher"),
  Portafolio1 = c(round(var_parametrico_1, 2), 
                  round(var_historico_1, 2), 
                  round(var_cornish_fisher_1, 2)),
  Portafolio2 = c(round(var_parametrico_2, 2), 
                  round(var_historico_2, 2), 
                  round(var_cornish_fisher_2, 2))
)

print("Tabla Comparativa de VaR al 95%:")
## [1] "Tabla Comparativa de VaR al 95%:"
print(tabla_var)
##                 Método Portafolio1 Portafolio2
## 1 Paramétrico (Normal)    -2329386    -2448160
## 2            Histórico    -2194554    -2480500
## 3       Cornish-Fisher    -2240354    -2568192
# c) CONTRIBUCIÓN AL VaR POR ACTIVO

# Función para calcular contribución al VaR
calcular_contribucion_var <- function(rendimientos, pesos, valor_portafolio, metodo = "parametrico") {
  
  n_activos <- length(pesos)
  contribuciones <- numeric(n_activos)
  
  if (metodo == "parametrico") {
    # Método paramétrico
    sigma <- apply(rendimientos, 2, sd)
    correlacion <- cor(rendimientos)
    var_portafolio <- sqrt(t(pesos) %*% (correlacion * (sigma %*% t(sigma))) %*% pesos)
    
    for (i in 1:n_activos) {
      contribuciones[i] <- pesos[i] * sum(correlacion[i,] * sigma[i] * sigma * pesos) / var_portafolio
    }
    
  } else if (metodo == "historico") {
    # Método histórico
    rendimientos_portafolio <- as.matrix(rendimientos) %*% pesos
    var_historico <- quantile(rendimientos_portafolio, 0.05)
    
    for (i in 1:n_activos) {
      # Contribución marginal basada en escenarios históricos
      contribuciones[i] <- pesos[i] * mean(rendimientos[,i][rendimientos_portafolio <= var_historico])
    }
  }
  
  contribuciones_var <- valor_portafolio * contribuciones * qnorm(0.05)
  return(contribuciones_var)
}

# DATOS PARA PORTAFOLIO 1
rendimientos_portafolio1 <- datos[, c("Rbancolombia", "Rdavivienda", "Raval")]
rendimientos_portafolio1 <- na.omit(rendimientos_portafolio1)

# DATOS PARA PORTAFOLIO 2
rendimientos_portafolio2 <- datos[, c("Recopetrol", "Rpromigas", "Rgeb")]
rendimientos_portafolio2 <- na.omit(rendimientos_portafolio2)

# CALCULAR CONTRIBUCIONES
contrib_var1_param <- calcular_contribucion_var(rendimientos_portafolio1, pesos_portafolio1, valor_inicial, "parametrico")
contrib_var1_hist <- calcular_contribucion_var(rendimientos_portafolio1, pesos_portafolio1, valor_inicial, "historico")

contrib_var2_param <- calcular_contribucion_var(rendimientos_portafolio2, pesos_portafolio2, valor_inicial, "parametrico")
contrib_var2_hist <- calcular_contribucion_var(rendimientos_portafolio2, pesos_portafolio2, valor_inicial, "historico")

# TABLAS DE CONTRIBUCIONES
tabla_contribuciones1 <- data.frame(
  Activo = c("Bancolombia", "Davivienda", "Aval"),
  Paramétrico = round(contrib_var1_param, 2),
  Histórico = round(contrib_var1_hist, 2)
)

tabla_contribuciones2 <- data.frame(
  Activo = c("Ecopetrol", "Promigas", "GEB"),
  Paramétrico = round(contrib_var2_param, 2),
  Histórico = round(contrib_var2_hist, 2)
)

print("Contribución al VaR - Portafolio 1:")
## [1] "Contribución al VaR - Portafolio 1:"
print(tabla_contribuciones1)
##        Activo Paramétrico Histórico
## 1 Bancolombia  -1000540.0   2399248
## 2  Davivienda   -613200.9   1259242
## 3        Aval   -656939.2   1418103
print("Contribución al VaR - Portafolio 2:")
## [1] "Contribución al VaR - Portafolio 2:"
print(tabla_contribuciones2)
##      Activo Paramétrico Histórico
## 1 Ecopetrol  -1605536.9 3890648.0
## 2  Promigas   -504507.5 1124906.7
## 3       GEB   -350853.9  856339.8
# ANÁLISIS Y COMENTARIOS

# Resumen de resultados
cat("\n=== ANÁLISIS COMPARATIVO ===\n")
## 
## === ANÁLISIS COMPARATIVO ===
cat("Portafolio 1 (Bancolombia 40%, Davivienda 30%, Aval 30%):\n")
## Portafolio 1 (Bancolombia 40%, Davivienda 30%, Aval 30%):
cat("- Rendimiento promedio:", round(mean(portafolios$R_portafolio1), 6), "\n")
## - Rendimiento promedio: -0.000587
cat("- Volatilidad:", round(sd(portafolios$R_portafolio1), 6), "\n")
## - Volatilidad: 0.013805
cat("- VaR 95% promedio:", round(mean(c(var_parametrico_1, var_historico_1, var_cornish_fisher_1)), 2), "\n\n")
## - VaR 95% promedio: -2254765
cat("Portafolio 2 (Ecopetrol 50%, Promigas 30%, GEB 20%):\n")
## Portafolio 2 (Ecopetrol 50%, Promigas 30%, GEB 20%):
cat("- Rendimiento promedio:", round(mean(portafolios$R_portafolio2), 6), "\n")
## - Rendimiento promedio: 0.000127
cat("- Volatilidad:", round(sd(portafolios$R_portafolio2), 6), "\n")
## - Volatilidad: 0.014961
cat("- VaR 95% promedio:", round(mean(c(var_parametrico_2, var_historico_2, var_cornish_fisher_2)), 2), "\n")
## - VaR 95% promedio: -2498951
# Determinar qué portafolio ha tenido mejor comportamiento
if (mean(portafolios$R_portafolio1) > mean(portafolios$R_portafolio2)) {
  cat("\nCONCLUSIÓN: El Portafolio 1 ha tenido mejor rendimiento promedio.\n")
} else {
  cat("\nCONCLUSIÓN: El Portafolio 2 ha tenido mejor rendimiento promedio.\n")
}
## 
## CONCLUSIÓN: El Portafolio 2 ha tenido mejor rendimiento promedio.
# Análisis de riesgo
if (sd(portafolios$R_portafolio1) < sd(portafolios$R_portafolio2)) {
  cat("El Portafolio 1 presenta menor volatilidad (menor riesgo).\n")
} else {
  cat("El Portafolio 2 presenta menor volatilidad (menor riesgo).\n")
}
## El Portafolio 1 presenta menor volatilidad (menor riesgo).

Diseño del Estudio

Este ejercicio evalúa dos portafolios con enfoques sectoriales distintos: un portafolio bancario (Bancolombia, Davivienda, Aval) y un portafolio energético (Ecopetrol, Promigas, GEB). El análisis compara rendimiento, riesgo y contribuciones marginales al VaR.

Resultados Comparativos

Desempeño y Riesgo El portafolio energético mostró rendimiento promedio ligeramente positivo, superando al portafolio bancario que registró rendimiento negativo. Sin embargo, esta ventaja en retorno vino acompañada de mayor volatilidad y mayores pérdidas potenciales medidas mediante VaR.

Valor en Riesgo (VaR) Los tres métodos de cálculo (paramétrico, histórico y Cornish-Fisher) coincidieron en señalar mayor riesgo en el portafolio energético. El VaR promedio del portafolio energético fue aproximadamente 10% superior al del portafolio bancario, indicando exposición significativamente mayor al riesgo de cola.

Análisis de Contribuciones

Ecopetrol emergió como el mayor contribuyente al riesgo en el portafolio energético, mientras Bancolombia dominó las contribuciones en el portafolio bancario. Se identificaron discrepancias metodológicas en las contribuciones, particularmente entre métodos paramétricos e históricos, sugiriendo la necesidad de análisis adicional.

Recomendaciones Estratégicas

Para Inversionistas Conservadores El portafolio bancario ofrece menor riesgo medido por volatilidad y VaR, aunque con rendimiento histórico negativo. Su composición diversificada dentro del sector financiero proporciona cierta estabilidad.

Para Inversionistas con Tolerancia al Riesgo

El portafolio energético justifica consideración por su rendimiento positivo, pero requiere conciencia plena de su mayor exposición al riesgo. La concentración en Ecopetrol representa un riesgo idiosincrático significativo.

Estrategia de Diversificación

La combinación de ambos portafolios podría ofrecer beneficios de diversificación intersectorial, potencialmente reduciendo riesgo general mientras mantiene exposición a diferentes drivers económicos.

Limitaciones y Extensiones

El análisis sugiere la conveniencia de incorporar Conditional VaR (CVaR) para mejor comprensión del riesgo de cola, así como análisis de stress testing para evaluar comportamiento en escenarios extremos.