Estadística y Machine Learning en economía y finanzas:

el caso de selección de carteras

Prof. Carlos Trucíos
ctrucios@unicamp.br

Instituto de Matemática, Estatística e Computação Científica (IMECC),
Universidade Estadual de Campinas (UNICAMP).

¿Un estadístico trabajando con alocación de carteras?

Todo tiene un comienzo

Todo tiene un comienzo

Todo tiene un comienzo

Introducción

Introducción

Introducción

  • Supongamos que tenemos dos activos, \(A\) y \(B\), en los que estamos interesados en invertir. ¿Cómo asignaría sus recursos en esta inversión?
  • Supongamos que tenemos dos activos, \(A\) y \(B\), con rendimientos esperados de \(3\) y \(5\), y varianzas de \(2\) y \(4\), respectivamente. ¿Cómo asignaría sus recursos para maximizar su rendimiento esperado y minimizar su riesgo?
  • Supongamos que tenemos dos activos, \(A\) y \(B\), con rendimientos esperados de \(3\) y \(5\), varianzas de \(2\) y \(4\), respectivamente, y una correlación igual a \(0.5\). ¿Cómo asignaría sus recursos para maximizar su rendimiento esperado y minimizar su riesgo?
  • Sea \(\boldsymbol{\omega}\) y \(\boldsymbol{\mu}\) los vectores columna de pesos y rendimientos esperados, respectivamente, y sea \(\boldsymbol{\Sigma}\) la matriz de covarianza asociada (riesgo). Queremos maximizar \[ \boldsymbol{\mu}^\top \boldsymbol{\omega} - \delta \, \boldsymbol{\omega}^\top \boldsymbol{\Sigma} \, \boldsymbol{\omega},\] donde \(\delta\) es el parámetro de aversión al riesgo (cuanto mayor, más adversos al riesgo).

Markowitz

Markowitz (1952)

Markowitz

Cuando \(\delta\) es grande, el problema a resolver se convierte, aproximadamente, en minimizar
\[ \boldsymbol{\omega}^\top \boldsymbol{\Sigma} \, \boldsymbol{\omega}, \]

Portafolio conocido como portafolio de varianza mínima.
  • Vamos a suponer que todo nuestro capital será asignado, es decir, \(\displaystyle \sum_{i = 1}^N \omega_i = 1\)
  • Entonces, queremos minimizar con restricción

Markowitz

Sea un portafolio con \(N\) activos y matriz de covarianza \(\Sigma\). Queremos minimizar
\[ L(\boldsymbol{\omega}, \lambda) = \boldsymbol{\omega}^\top \Sigma \, \boldsymbol{\omega} + \lambda \, (\boldsymbol{1}^\top \boldsymbol{\omega} - 1), \quad \text{donde} \quad \boldsymbol{1} = [1, 1, \cdots, 1]^\top. \]

Derivando w.r.t. \(\boldsymbol{\omega}\) y \(\lambda\)

Recuerde que

  • \(\dfrac{\partial \textbf{x}'A \textbf{x}}{\partial \textbf{x}} = (A + A') \textbf{x}\)
  • \(\dfrac{\partial \textbf{x}' \textbf{a}}{\partial \textbf{x}} = \dfrac{\partial \textbf{a}' \textbf{x}}{\partial \textbf{x}} = a\)
  • \(\dfrac{\partial^2 \textbf{x}'A \textbf{x}}{\partial \textbf{x} \partial \textbf{x}'} = A' + A\)
  • \(\dfrac{\partial L}{\partial \boldsymbol{\omega}} = 2 \Sigma \boldsymbol{\omega} + \lambda \boldsymbol{1}\)
  • \(\dfrac{\partial L}{\partial \lambda} = \boldsymbol{1}' \boldsymbol{\omega} - 1\)

Igualando a cero, \(\Sigma \boldsymbol{\omega} = - \dfrac{\lambda \boldsymbol{1}}{2} \rightarrow \boldsymbol{\omega} = \dfrac{-\lambda}{2} \Sigma^{-1} \boldsymbol{1}.\)

Markowitz

Igualando a cero \(\dfrac{\partial L}{\partial \lambda} = \boldsymbol{1}' \boldsymbol{\omega} - 1\), tenemos:

\[1 = \boldsymbol{1}' \boldsymbol{\omega} = \dfrac{-\lambda}{2} \boldsymbol{1}' \Sigma^{-1} \boldsymbol{1} \rightarrow \lambda = \dfrac{-2}{\boldsymbol{1}' \Sigma^{-1} \boldsymbol{1}}.\]

Luego,

\[\boldsymbol{\omega} = \dfrac{-\lambda}{2} \Sigma^{-1} \boldsymbol{1} = \dfrac{\Sigma^{-1} \boldsymbol{1}}{\boldsymbol{1}' \Sigma^{-1} \boldsymbol{1}},\] son los pesos optimos de la cartera de mínima varianza.

En la práctica, \(\Sigma\) no es conocido y debe ser estimado con los datos (\(\hat{\Sigma}\)).

Hands-On I

Hands-On I

Usando los retornos mensuales de las acciones en la B3, calcularemos los pesos para el portafolio de varianza mínima. Utilizaremos los paquetes de R yfR, RiskPortfolios, HierPortfolios, tidyr y dplyr.

Code
library(yfR)
library(dplyr)
library(tidyr)
# Lista de acciones que forman el índice Ibovespa
acoes <- yf_index_composition("IBOV")
Error in dplyr::rename(., ticker = Ticker, company = Company, industry = Industry) : 
  Can't rename columns that don't exist.
✖ Column `Ticker` doesn't exist.
Code
acoes$ticker
 [1] "ALPA4"  "ABEV3"  "AMER3"  "AZUL4"  "B3SA3"  "BBAS3"  "BBSE3"  "BBDC3" 
 [9] "BBDC4"  "BIDI11" "BPAN4"  "BRAP4"  "BRML3"  "BRKM5"  "BRFS3"  "BPAC11"
[17] "CRFB3"  "CCRO3"  "CVCB3"  "CMIG4"  "CIEL3"  "COGN3"  "CPLE6"  "CSAN3" 
[25] "CPFE3"  "CSNA3"  "CYRE3"  "DXCO3"  "ECOR3"  "ENBR3"  "ELET3"  "ELET6" 
[33] "EMBR3"  "ENGI11" "ENEV3"  "EGIE3"  "EQTL3"  "EZTC3"  "GGBR4"  "GOLL4" 
[41] "PCAR3"  "SOMA3"  "FLRY3"  "HAPV3"  "HYPE3"  "IGTI11" "IRBR3"  "ITUB4" 
[49] "ITSA4"  "JBSS3"  "JHSF3"  "KLBN11" "RENT3"  "LWSA3"  "LREN3"  "MGLU3" 
[57] "MRFG3"  "CASH3"  "GOAU4"  "BEEF3"  "MRVE3"  "MULT3"  "NTCO3"  "PETR3" 
[65] "PETR4"  "VBBR3"  "PRIO3"  "PETZ3"  "QUAL3"  "RADL3"  "RDOR3"  "RAIL3" 
[73] "SBSP3"  "SANB11" "ASAI3"  "SULA11" "SUZB3"  "TAEE11" "VIVT3"  "TIMS3" 
[81] "TOTS3"  "UGPA3"  "LCAM3"  "USIM5"  "VALE3"  "VIIA3"  "YDUQ3"  "WEGE3" 

Hands-On I

Code
tickers <- paste0(acoes$ticker, ".SA")
# Bajando datos
precios <- yf_get(tickers = tickers, 
                 first_date = "2015-01-01",
                 last_date  = "2025-06-30", 
                 freq_data = "monthly")
glimpse(precios)
Rows: 8,135
Columns: 11
$ ticker                 <chr> "ABEV3.SA", "ABEV3.SA", "ABEV3.SA", "ABEV3.SA",…
$ ref_date               <date> 2015-01-02, 2015-02-02, 2015-03-02, 2015-04-01…
$ volume                 <dbl> 262525100, 193123300, 252616400, 218542400, 205…
$ price_open             <dbl> 17.44, 18.31, 18.40, 18.75, 18.35, 19.00, 19.02…
$ price_high             <dbl> 17.87, 18.88, 18.97, 19.69, 20.29, 19.24, 19.89…
$ price_low              <dbl> 15.54, 17.16, 17.35, 18.42, 18.15, 18.09, 18.39…
$ price_close            <dbl> 17.69, 18.31, 18.48, 18.95, 18.53, 18.99, 19.47…
$ price_adjusted         <dbl> 11.96004, 12.37922, 12.55587, 12.87520, 12.5898…
$ ret_adjusted_prices    <dbl> NA, 0.035047889, 0.014270430, 0.025432663, -0.0…
$ ret_closing_prices     <dbl> NA, 0.035047988, 0.009284548, 0.025432967, -0.0…
$ cumret_adjusted_prices <dbl> 1.0000000, 1.0350479, 1.0498185, 1.0765181, 1.0…

Hands-On I

Code
# Estimamos la matriz de covariancia
Sigma <- precios |> 
  select(ref_date, ticker, ret_adjusted_prices) |> 
  pivot_wider(id_cols = ref_date, values_from = ret_adjusted_prices, names_from = ticker) |> 
  drop_na() |> 
  select(-ref_date) |> 
  cov()

Hands-On I

Code
n <- ncol(Sigma)
ones <- matrix(1, ncol = 1, nrow = n)
w <- as.numeric(1/(t(ones) %*% solve(Sigma) %*% ones)) * solve(Sigma) %*% ones
round(w, 4)
             [,1]
ABEV3.SA   0.0068
ALPA4.SA   0.0160
AMER3.SA   0.0234
AZUL4.SA   0.0197
B3SA3.SA   0.0081
BBAS3.SA   0.0633
BBDC3.SA  -0.4578
BBDC4.SA   0.5790
BBSE3.SA   0.0394
BEEF3.SA  -0.0013
BPAC11.SA -0.0429
BPAN4.SA   0.0134
BRAP4.SA  -0.3239
BRFS3.SA  -0.0972
BRKM5.SA  -0.0476
CMIG4.SA  -0.0833
COGN3.SA  -0.0222
CPFE3.SA   0.2003
CPLE6.SA   0.0180
CSAN3.SA  -0.0426
CSNA3.SA  -0.0363
CVCB3.SA  -0.0857
CYRE3.SA   0.3347
DXCO3.SA  -0.0035
ECOR3.SA  -0.1126
EGIE3.SA   0.1548
ELET3.SA  -0.4170
ELET6.SA   0.4861
EMBR3.SA   0.0045
ENEV3.SA   0.0760
ENGI11.SA  0.0518
EQTL3.SA  -0.0670
EZTC3.SA  -0.1610
FLRY3.SA   0.0854
GGBR4.SA   0.0713
HYPE3.SA  -0.0785
ITSA4.SA  -0.2431
ITUB4.SA   0.1369
JHSF3.SA  -0.0974
KLBN11.SA  0.0201
LREN3.SA   0.0470
MGLU3.SA  -0.0551
MRFG3.SA   0.1199
MRVE3.SA  -0.0834
MULT3.SA  -0.2157
PCAR3.SA  -0.0327
PETR3.SA  -0.0203
PETR4.SA   0.0489
PRIO3.SA  -0.0123
QUAL3.SA   0.0272
RADL3.SA   0.1453
RAIL3.SA   0.2454
RENT3.SA   0.0143
SANB11.SA -0.1211
SBSP3.SA  -0.0451
SUZB3.SA  -0.0399
TAEE11.SA  0.2554
TIMS3.SA  -0.0016
TOTS3.SA  -0.0690
UGPA3.SA   0.0770
USIM5.SA   0.0377
VALE3.SA   0.4567
VIVT3.SA   0.1878
WEGE3.SA   0.0557
YDUQ3.SA  -0.0103

\[\boldsymbol{\omega} = \dfrac{\Sigma^{-1} \boldsymbol{1}}{\boldsymbol{1}' \Sigma^{-1} \boldsymbol{1}},\]

Hands-On I

Code
# Calculamos los pesos optimos
library(RiskPortfolios)
omega <- optimalPortfolio(Sigma, control = list(type = "minvol"))
cbind(w, omega)
                              omega
ABEV3.SA   0.006760879  0.006760879
ALPA4.SA   0.016006470  0.016006470
AMER3.SA   0.023413634  0.023413634
AZUL4.SA   0.019726839  0.019726839
B3SA3.SA   0.008080406  0.008080406
BBAS3.SA   0.063340382  0.063340382
BBDC3.SA  -0.457793091 -0.457793091
BBDC4.SA   0.579026521  0.579026521
BBSE3.SA   0.039399864  0.039399864
BEEF3.SA  -0.001255193 -0.001255193
BPAC11.SA -0.042854614 -0.042854614
BPAN4.SA   0.013434218  0.013434218
BRAP4.SA  -0.323884664 -0.323884664
BRFS3.SA  -0.097181251 -0.097181251
BRKM5.SA  -0.047632442 -0.047632442
CMIG4.SA  -0.083288349 -0.083288349
COGN3.SA  -0.022206103 -0.022206103
CPFE3.SA   0.200308533  0.200308533
CPLE6.SA   0.017978591  0.017978591
CSAN3.SA  -0.042571171 -0.042571171
CSNA3.SA  -0.036290233 -0.036290233
CVCB3.SA  -0.085675428 -0.085675428
CYRE3.SA   0.334674494  0.334674494
DXCO3.SA  -0.003456292 -0.003456292
ECOR3.SA  -0.112573289 -0.112573289
EGIE3.SA   0.154807659  0.154807659
ELET3.SA  -0.416957220 -0.416957220
ELET6.SA   0.486077361  0.486077361
EMBR3.SA   0.004539365  0.004539365
ENEV3.SA   0.076033083  0.076033083
ENGI11.SA  0.051794816  0.051794816
EQTL3.SA  -0.067006671 -0.067006671
EZTC3.SA  -0.161017473 -0.161017473
FLRY3.SA   0.085416134  0.085416134
GGBR4.SA   0.071279116  0.071279116
HYPE3.SA  -0.078487566 -0.078487566
ITSA4.SA  -0.243109206 -0.243109206
ITUB4.SA   0.136902676  0.136902676
JHSF3.SA  -0.097351802 -0.097351802
KLBN11.SA  0.020137864  0.020137864
LREN3.SA   0.046970965  0.046970965
MGLU3.SA  -0.055065020 -0.055065020
MRFG3.SA   0.119850337  0.119850337
MRVE3.SA  -0.083384582 -0.083384582
MULT3.SA  -0.215728546 -0.215728546
PCAR3.SA  -0.032695807 -0.032695807
PETR3.SA  -0.020311500 -0.020311500
PETR4.SA   0.048863015  0.048863015
PRIO3.SA  -0.012303629 -0.012303629
QUAL3.SA   0.027173974  0.027173974
RADL3.SA   0.145255924  0.145255924
RAIL3.SA   0.245351740  0.245351740
RENT3.SA   0.014299539  0.014299539
SANB11.SA -0.121145373 -0.121145373
SBSP3.SA  -0.045129950 -0.045129950
SUZB3.SA  -0.039873448 -0.039873448
TAEE11.SA  0.255375056  0.255375056
TIMS3.SA  -0.001585105 -0.001585105
TOTS3.SA  -0.069031032 -0.069031032
UGPA3.SA   0.076964370  0.076964370
USIM5.SA   0.037724003  0.037724003
VALE3.SA   0.456696820  0.456696820
VIVT3.SA   0.187833318  0.187833318
WEGE3.SA   0.055668978  0.055668978
YDUQ3.SA  -0.010320892 -0.010320892

Hands-On I

  • En la práctica, \(\Sigma\) no es conocido y debe ser estimado con los datos (\(\hat{\Sigma}\)).
  • Utilizar \(\hat{\Sigma}\) en lugar de \(\Sigma\) implica un error de estimación.
  • Esto provoca que los pesos se asignen a pocos activos, exista poca diversificación y el rendimiento fuera de la muestra sea pobre 🙍
  • Para abordar este problema, se han propuesto diversas metodologías.

Observación:

  • En la práctica, es muy difícil estimar \(\mu\). Por eso, los portafolios basados en riesgo (\(\Sigma\)) son preferidos.
  • Es común imponer la restricción de que \(\omega_i \geq 0\) (no-short-selling constraints o restricción de no venta en corto).

Hands-On I

Code
omega <- optimalPortfolio(Sigma, control = list(type = "minvol", constraint = "lo"))
round(omega, 4)
 [1] 0.0000 0.0044 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.1112 0.0000
[11] 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0302 0.0000 0.0000
[21] 0.0000 0.0000 0.0000 0.0000 0.0000 0.0317 0.0000 0.0000 0.0116 0.0000
[31] 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.1484
[41] 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000
[51] 0.0465 0.0085 0.0000 0.0000 0.0000 0.0211 0.1478 0.0000 0.0000 0.0000
[61] 0.0000 0.1435 0.2678 0.0272 0.0000

Otros portafolios basados en riesgo

Otros portafolios basados en riesgo

Pesos iguales

  • También llamada estrategia ingenua o \(1/N\).
  • Es la estrategia más simple y no requiere cálculos difíciles ni resolver problemas de optimización.
  • Para un conjunto de \(N\) activos financieros, los pesos se obtienen como
    \[ \omega_i = 1/N, \quad \forall i = 1, \cdots, N. \]
  • A pesar de su simplicidad, diversos autores mencionan que el desempeño fuera de la muestra de esta estrategia difícilmente es superado por métodos más complejos (DeMiguel et al. 2009).

Otros portafolios basados en riesgo

Volatilidad inversa

Propuesta por Leote De Carvalho et al. (2012), esta estrategia no toma en cuenta las covarianzas, sino únicamente las varianzas. Los pesos se obtienen como:

\[\boldsymbol{\omega} = \Big( \dfrac{1/\sigma_1}{ \displaystyle \sum_{j = 1}^N 1/\sigma_j}, \cdots, \dfrac{1/\sigma_N}{ \displaystyle \sum_{j = 1}^N 1/\sigma_j} \Big)'\]

En R

optimalPortfolio(Sigma, control = list(type = 'invvol', constraint = 'lo'))

Otros portafolios basados en riesgo

Diversificación máxima

Propuesta por Choueifaty y Coignard (2008), el objetivo es maximizar la razón
\[ DR = \dfrac{\boldsymbol{\omega}^\top \boldsymbol{\sigma}}{\sqrt{\boldsymbol{\omega}^\top \Sigma \, \boldsymbol{\omega}}}, \]
sujeto a la restricción de que \(\boldsymbol{1}^\top \boldsymbol{\omega} = 1\) y \(\omega_i \geq 0\), y donde \(\boldsymbol{\sigma} = \sqrt{\text{diag}(\Sigma)}\).

Nótese que, en el caso extremo de que el portafolio esté formado por un solo activo, \(DR = 1\), lo que implica un portafolio pobremente diversificado.

En R

optimalPortfolio(Sigma, control = list(type = 'maxdiv', constraint = 'lo'))

Otros portafolios basados en riesgo

Igual contribución al riesgo

Popularizada por Qian (2005), la idea de esta estrategia es que cada uno de los activos tenga la misma contribución marginal al riesgo (volatilidad) del portafolio, es decir, que la proporción de la contribución al riesgo de cada activo sea \(1/N\). Los activos con poco riesgo recibirán pesos mayores y los activos con mucho riesgo recibirán pesos menores.

Los pesos se obtienen minimizando
\[ \displaystyle \sum_{i = 1}^N (\%RC_i - 1/N)^2, \]
sujeto a la restricción de que \(\boldsymbol{1}^\top \boldsymbol{\omega} = 1\), donde
\(\%RC_i = \omega_i [\Sigma \boldsymbol{\omega}]_i / \boldsymbol{\omega}^\top \Sigma \boldsymbol{\omega}\)
es el porcentaje de riesgo con el que el activo \(i\) contribuye al riesgo total.

En R

optimalPortfolio(Sigma, control = list(type = 'erc', constraint = 'lo'))

Outros portfolios basados en riesgo

Máxima decorrelación

Proposto por Christoffersen et al. (2012), esta estratégia pode ser vista como um caso particular do portfolio de variância mínima mas com \(\rho\) (matriz de correlação) em lugar de \(\Sigma\) (matriz de covariância). Assim, queremos minimizar \[\boldsymbol{\omega} \rho \boldsymbol{\omega},\] sujeito á restrição de que \(\boldsymbol{1}' \boldsymbol{\omega} = 1\)

No R

optimalPortfolio(Sigma, control = list(type = 'maxdec', constraint = 'lo'))

Hands-On II

Hands-On II

Utilizando los datos anteriores, calcularemos los pesos óptimos utilizando las estrategias vistas anteriormente.

Code
omega_invol <- optimalPortfolio(Sigma, control = list(type = 'invvol', constraint = 'lo'))
omega_erc <- optimalPortfolio(Sigma, control = list(type = 'erc', constraint = 'lo'))
omega_maxdiv <- optimalPortfolio(Sigma, control = list(type = 'maxdiv', constraint = 'lo'))
omega_maxdec <- optimalPortfolio(Sigma, control = list(type = 'maxdec', constraint = 'lo'))

Hands-On II

Code
pesos <- cbind(omega, omega_invol, omega_erc, omega_maxdiv, omega_maxdec)
colnames(pesos) <- c("MV","IV", "ERC","MaxDiv", "MaxDec")
pesos
                    MV          IV         ERC       MaxDiv       MaxDec
ABEV3.SA  0.000000e+00 0.022769963 0.022344181 1.352484e-16 7.099076e-18
ALPA4.SA  4.445503e-03 0.013120455 0.014115983 2.542815e-02 2.097542e-02
AMER3.SA  1.475349e-18 0.006738349 0.012032911 5.449133e-02 8.752230e-02
AZUL4.SA  1.850113e-17 0.007715655 0.007659298 0.000000e+00 0.000000e+00
B3SA3.SA  8.213835e-17 0.016160073 0.012499347 0.000000e+00 9.282757e-17
BBAS3.SA  1.951884e-16 0.016071791 0.013882840 2.769844e-15 0.000000e+00
BBDC3.SA  0.000000e+00 0.016895574 0.011896462 0.000000e+00 0.000000e+00
BBDC4.SA  0.000000e+00 0.016528216 0.011804452 0.000000e+00 0.000000e+00
BBSE3.SA  1.111933e-01 0.024603062 0.026839776 5.192129e-02 2.284026e-02
BEEF3.SA  2.769987e-18 0.012014085 0.014018450 1.822282e-15 2.112108e-18
BPAC11.SA 7.347572e-17 0.012960718 0.009816228 0.000000e+00 0.000000e+00
BPAN4.SA  4.925073e-19 0.007695599 0.009770167 3.203140e-02 4.504829e-02
BRAP4.SA  3.338350e-16 0.017186756 0.020231412 4.833818e-16 1.603095e-16
BRFS3.SA  1.953990e-18 0.011119392 0.010762209 0.000000e+00 2.557112e-19
BRKM5.SA  0.000000e+00 0.011449489 0.013009321 0.000000e+00 2.667878e-18
CMIG4.SA  0.000000e+00 0.016469303 0.015521370 1.447054e-15 0.000000e+00
COGN3.SA  7.268050e-17 0.010049809 0.007475772 0.000000e+00 0.000000e+00
CPFE3.SA  3.022052e-02 0.023973793 0.021496245 1.970715e-15 5.319611e-18
CPLE6.SA  5.895855e-17 0.018930692 0.017429167 1.664487e-15 2.274051e-17
CSAN3.SA  1.533275e-17 0.016546251 0.012978340 0.000000e+00 0.000000e+00
CSNA3.SA  0.000000e+00 0.011092936 0.011012036 0.000000e+00 2.138496e-17
CVCB3.SA  4.106824e-17 0.009397455 0.006964266 0.000000e+00 0.000000e+00
CYRE3.SA  0.000000e+00 0.012445967 0.009019952 0.000000e+00 0.000000e+00
DXCO3.SA  1.443013e-17 0.013792280 0.012952849 8.529584e-16 0.000000e+00
ECOR3.SA  0.000000e+00 0.012699125 0.009849182 0.000000e+00 0.000000e+00
EGIE3.SA  3.170476e-02 0.026893497 0.022663894 6.673012e-16 0.000000e+00
ELET3.SA  3.442483e-17 0.011908324 0.010830267 1.109482e-04 1.008356e-04
ELET6.SA  0.000000e+00 0.012963221 0.011670328 3.455990e-15 2.012005e-16
EMBR3.SA  1.157529e-02 0.012795693 0.023665371 6.282443e-02 5.313853e-02
ENEV3.SA  0.000000e+00 0.020098752 0.017996565 1.295895e-15 2.563380e-17
ENGI11.SA 1.459452e-16 0.021149122 0.015563978 0.000000e+00 0.000000e+00
EQTL3.SA  9.701516e-17 0.021364678 0.015350912 0.000000e+00 0.000000e+00
EZTC3.SA  1.277672e-16 0.012537939 0.009904118 1.185616e-15 0.000000e+00
FLRY3.SA  0.000000e+00 0.021086082 0.019133251 3.204064e-16 4.040364e-18
GGBR4.SA  1.782787e-16 0.015693051 0.014810444 0.000000e+00 1.076825e-16
HYPE3.SA  5.994554e-17 0.020251344 0.017287479 5.219941e-16 0.000000e+00
ITSA4.SA  5.256239e-16 0.020531479 0.014345241 0.000000e+00 0.000000e+00
ITUB4.SA  5.772894e-17 0.019369052 0.014252925 0.000000e+00 0.000000e+00
JHSF3.SA  4.277622e-17 0.010709220 0.008499998 0.000000e+00 0.000000e+00
KLBN11.SA 1.483814e-01 0.022652662 0.028256708 0.000000e+00 2.601815e-16
LREN3.SA  1.128836e-17 0.014081349 0.010689209 0.000000e+00 6.039562e-17
MGLU3.SA  3.342276e-18 0.008250023 0.008715577 0.000000e+00 1.154097e-18
MRFG3.SA  2.758720e-19 0.011045551 0.015459722 4.790320e-02 4.693771e-02
MRVE3.SA  2.323910e-18 0.012530145 0.010297825 0.000000e+00 0.000000e+00
MULT3.SA  0.000000e+00 0.019431998 0.014310149 0.000000e+00 1.340695e-16
PCAR3.SA  0.000000e+00 0.006636988 0.010855822 3.933291e-02 6.414013e-02
PETR3.SA  0.000000e+00 0.014534472 0.013637580 1.128367e-15 0.000000e+00
PETR4.SA  0.000000e+00 0.015018852 0.013475469 7.727441e-16 1.926970e-16
PRIO3.SA  1.327502e-18 0.009746289 0.010082212 0.000000e+00 7.503729e-17
QUAL3.SA  6.269829e-17 0.010972740 0.011433607 2.301022e-02 2.269605e-02
RADL3.SA  4.653543e-02 0.020833611 0.024985831 9.699217e-02 5.038681e-02
RAIL3.SA  8.538291e-03 0.020667339 0.021101922 1.710239e-16 6.029241e-17
RENT3.SA  0.000000e+00 0.014566381 0.010770519 0.000000e+00 0.000000e+00
SANB11.SA 1.196025e-16 0.018478264 0.014145954 0.000000e+00 1.333909e-16
SBSP3.SA  0.000000e+00 0.015715278 0.013549950 1.445985e-16 0.000000e+00
SUZB3.SA  2.112739e-02 0.015506551 0.039199564 1.256911e-01 8.772716e-02
TAEE11.SA 1.478009e-01 0.027951581 0.024646023 1.856027e-16 5.039417e-17
TIMS3.SA  9.944333e-20 0.001407344 0.005804365 2.844725e-02 2.187684e-01
TOTS3.SA  1.899829e-18 0.015962069 0.014392327 8.614484e-17 0.000000e+00
UGPA3.SA  2.587944e-17 0.010904852 0.015230262 1.632577e-01 1.620312e-01
USIM5.SA  0.000000e+00 0.012251851 0.011168348 0.000000e+00 0.000000e+00
VALE3.SA  1.434755e-01 0.019827043 0.035034013 1.031677e-01 5.631583e-02
VIVT3.SA  2.678450e-01 0.028047166 0.040487342 1.216167e-01 4.692985e-02
WEGE3.SA  2.715678e-02 0.017817025 0.023341716 2.377349e-02 1.444117e-02
YDUQ3.SA  4.668109e-17 0.009384336 0.007570999 0.000000e+00 0.000000e+00

Portafolios basados en riesgo con Machine Learning (ML)

Portafolios basados en riesgo con ML

  • Recientemente, han surgido en la literatura nuevas estrategias de asignación de portafolios basadas en machine learning.
  • Algunas de estas estrategias utilizan algoritmos de agrupamiento jerárquico (HRP, HCAA, HERC, DHRP).
  • Estas estrategias surgen para superar algunas de las limitaciones de la estrategia de Markowitz, así como para incorporar la idea de que “los sistemas complejos, como el mercado financiero, están organizados de forma jerárquica”.

Portafolios basados en riesgo con ML

Hierarchical Risk Parity (HRP)

  • Proposta por Lopez de Prado (2016)
  • Surge como uma alternativa para evitar os problemas observados da optimização de Markowitz.
  • A ideia básica do algoritmo é transformar a matriz de covariância em matriz de distâncias, aplicar um método de agrupamento hierárquico, fazer bissecções e calcular os pesos através da estratégia de volatilidade inversa.

Portafolios basados en riesgo con ML

Hierarchical Risk Parity (HRP)

  • La matriz de distancias utilizada en el método de agrupamiento jerárquico se denota por \(\tilde{D}\), cuyos elementos \({\tilde{d}_{ij}}\) se obtienen como
    \[\tilde{d}_{ij} = \sqrt{\displaystyle \sum_{k = 1}^N (d_{ki} - d_{kj})^2},\]
    donde \(N\) es el número de activos y \(d_{ij} = \sqrt{0.5 \times (1 - \rho_{ij})}\), con \(\rho_{ij}\) siendo la correlación entre los activos \(i\) y \(j\).

Portafolios basados en riesgo con ML

Hierarchical Risk Parity (HRP)

Portafolios basados en riesgo con ML

Hierarchical Risk Parity (HRP)

  • Inicialice todos los pesos en \(\omega_i = 1\).
  • Dentro de cada grupo, el vector de pesos previos del grupo \(k\) (\(k = 1, 2\)) se obtiene mediante el método de volatilidad inversa,
    \[\boldsymbol{\omega}_{aux}^{(k)} = \dfrac{1}{\mathrm{Trace}(\mathrm{Diag}(\Sigma^{(k)})^{-1})} \times \mathrm{Diag}(\Sigma^{(k)})^{-1},\]
    donde \(\Sigma^{(k)}\) es la matriz de covarianza de los activos en el grupo \(k\).
  • Con los pesos obtenidos, calculamos la varianza de cada grupo como
    \(V^{(k)} = \boldsymbol{\omega}_{aux}^{(k)} \Sigma^{(k)} \boldsymbol{\omega}_{aux}^{(k) \prime},\)
    y, finalmente, \(\alpha = 1 - \frac{V^{(1)}}{V^{(1)} + V^{(2)}}\), que es un factor de ponderación que actualizará el peso de cada activo.
  • Los pesos finales se actualizan a
    \(\boldsymbol{\omega}^{(1)} = \alpha \boldsymbol{\omega}^{(1)}\)
    y
    \(\boldsymbol{\omega}^{(2)} = (1 - \alpha) \boldsymbol{\omega}^{(2)}\).
  • El proceso se repite hasta que cada grupo tenga solamente un activo.

Portafolios basados en riesgo con ML

Hierarchical Risk Parity (HRP)

Portafolios basados en riesgo con ML

Hierarchical Risk Parity (HRP)

No R

Code
library(HierPortfolios)
omega_hrp <- HRP_Portfolio(Sigma)

Portafolios basados en riesgo con ML

Hierarchical Risk Parity (HRP)

  • Una de las críticas a HRP es que el método no utiliza la clusterización, sino apenas el orden.
  • Algunas modificaciones del algoritmo fueron apareciendo en la literatura:

Portafolios basados en riesgo con ML

A Constrained Hierarchical Risk Parity Algorithm with Cluster-based Capital Allocation (DHRP)

  • Con el objetivo de incorporar una mayor parte de la información extraída a partir de la agrupación, así como incluir algunas prácticas habituales del mercado financiero, Pfitzinger et al. (2019) proponen tres modificaciones a la propuesta de Lopez de Prado (2016):
    • La primera modificación consiste en utilizar un algoritmo divisivo en lugar de un algoritmo aglomerativo, como sugiere Lopez de Prado (2016).
    • Permite la inclusión de restricciones en los pesos, y
    • Utilizando un parámetro \(\tau\), es posible aprovechar toda la estructura jerárquica obtenida en la agrupación (\(\tau = 1\)), parte de ella (\(\tau \in (0, 1)\)) o solamente el ordenamiento (\(\tau = 0\)).

No R

Code
omega_dhrp <- DHRP_Portfolio(Sigma, tau = 1)

Portafolios basados en riesgo con ML

Hierarchical Clustering-Based Asset Allocation (HCAA)

  • HRP y DHRP no tienen en cuenta el número de clústeres que se van a formar.
  • HCAA considera este aspecto y, tras seleccionar el número de grupos a formar, los pesos se calculan entre los grupos y dentro de los grupos.
  • La idea es distribuir el capital total a invertir de forma igual entre los clústeres jerárquicamente (de esta manera, los activos correlacionados que forman un clúster reciben el mismo peso total que un activo no correlacionado, logrando diversificación).
  • Dentro de cada clúster, los pesos se calculan mediante la estrategia de pesos iguales.

Portafolios basados en riesgo con ML

Hierarchical Clustering-Based Asset Allocation (HCAA)

Exemplo: 3 clusters

Portafolios basados en riesgo con ML

Hierarchical Clustering-Based Asset Allocation (HCAA)

No R

Code
omega_hacc <- HCAA_Portfolio(Sigma)
[1] "Number of clusters: 4"

Portafolios basados en riesgo con ML

Hierarchical Equal Risk Contribution (HERC)

  • HRP realiza las bisecciones considerando únicamente el orden del dendrograma y no el dendrograma per se.
  • Similar a HACC, pero en lugar de calcular los pesos de forma que el total a invertir se divida equitativamente entre clústeres, calcula los pesos de manera que la contribución al riesgo sea la misma dentro de cada clúster.
  • Dentro de cada clúster, se utiliza el método de volatilidad inversa.

Portafolios basados en riesgo con ML

Hierarchical Equal Risk Contribution (HERC)

No R

Code
omega_herc <- HERC_Portfolio(Sigma)

Portafolios basados en riesgo con ML

Hierarchical Equal Risk Contribution (HERC)

  • Realizar un agrupamiento jerárquico, Raffinot (2018) sugiere utilizar el enlace ward, pero podría emplearse cualquier otro tipo de enlace.
  • Seleccionar el número de clústeres a utilizar según algún criterio, Raffinot (2018) sugiere emplear el índice Gap.
  • Dentro de cada clúster, calcular los pesos (iniciales) mediante el método Naive Risk Parity.
  • Utilizando los pesos obtenidos en el paso anterior, calcular el riesgo de cada clúster (y en cada jerarquía).
  • En cada jerarquía, calcular los pesos como \(\omega^{(1)} = \dfrac{RC_2}{RC_1 + RC_2}\) y \(\omega^{(2)} = \dfrac{RC_1}{RC_1 + RC_2}\), donde RC es el riesgo en el clúster. Por último, los pesos iniciales se actualizarán utilizando los diversos \(\omega^{(1)}\) y \(\omega^{(2)}\) obtenidos.

Portafolios basados en riesgo con ML

Hierarchical Equal Risk Contribution (HERC)

Code
omega_herc <- HERC_Portfolio(Sigma, graph = TRUE)

Portafolios basados en riesgo con ML

Code
pesos <- round(cbind(omega, omega_invol, omega_maxdec, omega_maxdiv, omega_erc, omega_hrp, omega_dhrp, omega_hacc, omega_herc), 3)
colnames(pesos) <- c("MV", "IV", "MaxDec", "MaxDiv", "ERC", "HRP", "DHRP", "HACC", "HERC")
pesos
             MV    IV MaxDec MaxDiv   ERC   HRP  DHRP  HACC  HERC
ABEV3.SA  0.000 0.023  0.000  0.000 0.022 0.036 0.035 0.016 0.026
ALPA4.SA  0.004 0.013  0.021  0.025 0.014 0.009 0.012 0.011 0.019
AMER3.SA  0.000 0.007  0.088  0.054 0.012 0.005 0.015 0.050 0.025
AZUL4.SA  0.000 0.008  0.000  0.000 0.008 0.004 0.003 0.011 0.007
B3SA3.SA  0.000 0.016  0.000  0.000 0.012 0.010 0.001 0.012 0.007
BBAS3.SA  0.000 0.016  0.000  0.000 0.014 0.011 0.012 0.016 0.013
BBDC3.SA  0.000 0.017  0.000  0.000 0.012 0.009 0.001 0.012 0.008
BBDC4.SA  0.000 0.017  0.000  0.000 0.012 0.008 0.001 0.012 0.008
BBSE3.SA  0.111 0.025  0.023  0.052 0.027 0.042 0.041 0.016 0.031
BEEF3.SA  0.000 0.012  0.000  0.000 0.014 0.005 0.013 0.011 0.016
BPAC11.SA 0.000 0.013  0.000  0.000 0.010 0.006 0.000 0.012 0.005
BPAN4.SA  0.000 0.008  0.045  0.032 0.010 0.006 0.012 0.011 0.007
BRAP4.SA  0.000 0.017  0.000  0.000 0.020 0.018 0.022 0.011 0.032
BRFS3.SA  0.000 0.011  0.000  0.000 0.011 0.006 0.012 0.011 0.014
BRKM5.SA  0.000 0.011  0.000  0.000 0.013 0.013 0.014 0.011 0.014
CMIG4.SA  0.000 0.016  0.000  0.000 0.016 0.011 0.009 0.016 0.014
COGN3.SA  0.000 0.010  0.000  0.000 0.007 0.004 0.000 0.012 0.003
CPFE3.SA  0.030 0.024  0.000  0.000 0.021 0.026 0.012 0.016 0.029
CPLE6.SA  0.000 0.019  0.000  0.000 0.017 0.016 0.007 0.016 0.018
CSAN3.SA  0.000 0.017  0.000  0.000 0.013 0.013 0.006 0.016 0.014
CSNA3.SA  0.000 0.011  0.000  0.000 0.011 0.007 0.011 0.011 0.014
CVCB3.SA  0.000 0.009  0.000  0.000 0.007 0.003 0.001 0.012 0.002
CYRE3.SA  0.000 0.012  0.000  0.000 0.009 0.005 0.000 0.012 0.004
DXCO3.SA  0.000 0.014  0.000  0.000 0.013 0.010 0.010 0.011 0.021
ECOR3.SA  0.000 0.013  0.000  0.000 0.010 0.006 0.001 0.012 0.005
EGIE3.SA  0.032 0.027  0.000  0.000 0.023 0.035 0.015 0.016 0.037
ELET3.SA  0.000 0.012  0.000  0.000 0.011 0.010 0.003 0.016 0.007
ELET6.SA  0.000 0.013  0.000  0.000 0.012 0.009 0.004 0.016 0.009
EMBR3.SA  0.012 0.013  0.053  0.063 0.024 0.026 0.060 0.050 0.091
ENEV3.SA  0.000 0.020  0.000  0.000 0.018 0.019 0.017 0.016 0.020
ENGI11.SA 0.000 0.021  0.000  0.000 0.016 0.014 0.002 0.012 0.013
EQTL3.SA  0.000 0.021  0.000  0.000 0.015 0.014 0.002 0.012 0.013
EZTC3.SA  0.000 0.013  0.000  0.000 0.010 0.005 0.000 0.012 0.004
FLRY3.SA  0.000 0.021  0.000  0.000 0.019 0.021 0.009 0.011 0.049
GGBR4.SA  0.000 0.016  0.000  0.000 0.015 0.013 0.022 0.011 0.027
HYPE3.SA  0.000 0.020  0.000  0.000 0.017 0.019 0.007 0.012 0.012
ITSA4.SA  0.000 0.021  0.000  0.000 0.014 0.013 0.001 0.012 0.012
ITUB4.SA  0.000 0.019  0.000  0.000 0.014 0.011 0.001 0.012 0.011
JHSF3.SA  0.000 0.011  0.000  0.000 0.008 0.004 0.000 0.012 0.003
KLBN11.SA 0.148 0.023  0.000  0.000 0.028 0.049 0.104 0.050 0.286
LREN3.SA  0.000 0.014  0.000  0.000 0.011 0.007 0.003 0.012 0.006
MGLU3.SA  0.000 0.008  0.000  0.000 0.009 0.005 0.006 0.011 0.007
MRFG3.SA  0.000 0.011  0.047  0.048 0.015 0.004 0.011 0.011 0.013
MRVE3.SA  0.000 0.013  0.000  0.000 0.010 0.006 0.000 0.012 0.004
MULT3.SA  0.000 0.019  0.000  0.000 0.014 0.014 0.003 0.012 0.011
PCAR3.SA  0.000 0.007  0.064  0.039 0.011 0.007 0.006 0.011 0.005
PETR3.SA  0.000 0.015  0.000  0.000 0.014 0.007 0.005 0.016 0.011
PETR4.SA  0.000 0.015  0.000  0.000 0.013 0.008 0.005 0.016 0.011
PRIO3.SA  0.000 0.010  0.000  0.000 0.010 0.006 0.022 0.011 0.010
QUAL3.SA  0.000 0.011  0.023  0.023 0.011 0.007 0.004 0.011 0.013
RADL3.SA  0.047 0.021  0.050  0.097 0.025 0.044 0.040 0.011 0.048
RAIL3.SA  0.009 0.021  0.000  0.000 0.021 0.031 0.050 0.016 0.022
RENT3.SA  0.000 0.015  0.000  0.000 0.011 0.008 0.000 0.012 0.006
SANB11.SA 0.000 0.018  0.000  0.000 0.014 0.012 0.004 0.012 0.010
SBSP3.SA  0.000 0.016  0.000  0.000 0.014 0.011 0.008 0.016 0.013
SUZB3.SA  0.021 0.016  0.088  0.126 0.039 0.025 0.049 0.050 0.134
TAEE11.SA 0.148 0.028  0.000  0.000 0.025 0.038 0.039 0.016 0.040
TIMS3.SA  0.000 0.001  0.219  0.028 0.006 0.000 0.001 0.050 0.001
TOTS3.SA  0.000 0.016  0.000  0.000 0.014 0.012 0.005 0.011 0.028
UGPA3.SA  0.000 0.011  0.162  0.163 0.015 0.014 0.013 0.011 0.013
USIM5.SA  0.000 0.012  0.000  0.000 0.011 0.009 0.011 0.011 0.017
VALE3.SA  0.143 0.020  0.056  0.103 0.035 0.022 0.029 0.011 0.043
VIVT3.SA  0.268 0.028  0.047  0.122 0.040 0.118 0.158 0.011 0.086
WEGE3.SA  0.027 0.018  0.014  0.024 0.023 0.030 0.029 0.011 0.035
YDUQ3.SA  0.000 0.009  0.000  0.000 0.008 0.003 0.000 0.012 0.002

Evaluando Portafolios

Medidas de desempeño

Sea \(k\) el tamaño del período fuera de muestra (consideraresmos datos mensuales)

  • Average (AV): \[AV = 12\frac{\displaystyle\sum_{i = 1}^{k}R_{i}}{p},\] donde \(R_{i}\) son los retornos fuera de muestra. AV calcula el promedio anualizado, el cual se multiplica por 12. Cuanto mayor AV, mejor el desempeño de la cartera.
  • Standard Deviation (SD): \[SD = \sqrt{12}\hat{\sigma}_{p},\] donde \(\hat{\sigma}_{p}\) es la desviación estándar anualizada de los retornos fuera de muestra. Cuanto menor SD, menor es el riesgo y mejor es el desempeño de la cartera.

Medidas de desempeño

  • Sharpe Ratio (SR): \[SR = \frac{\bar{R}_{p} - \bar{R}_{f}}{\bar{\sigma}_{p-f}},\] donde \(R_{f}\) es la tasa libre de riesgo, \(\bar{R}_{p}\) es el promedio de los retornos fuera de muestra y \(\bar{\sigma}_{p-f}\) es la desviación estándar estimada del exceso de retorno. Cuanto mayor SR, mejor el desempeño de la cartera.
  • Adjusted Sharpe Ratio (ASR): \[SR = SR\left(1 + \left(\frac{\mu_{3}}{6}\right)SR - \left(\frac{\mu_{4}-3}{24}\right)SR^2\right),\] donde \(\mu_{3}\) es la asimetría, \(\mu_{4}\) es la curtosis y \(SR\) es el Sharpe Ratio definido anteriormente. Esta métrica ajusta el Sharpe Ratio incluyendo el tercer y cuarto momento muestral. Cuanto mayor ASR, mejor el desempeño de la cartera.

Medidas de desempeño

  • Sortino Ratio (SO): \[SO = \frac{\bar{R}_{p}}{\sqrt{\frac{\sum_{i=1}^{K}min(0,R_{p,i} - MAR)^2}{K}}},\] donde MAR es el retorno mínimo aceptado, el cual es igual a la tasa libre de riesgo mensual. Cuanto mayor SO, mejor el desempeño del portafolio.

Aplicación

Aplicación

Code
library(yfR)
library(dplyr)
library(tidyr)
library(RiskPortfolios)
library(HierPortfolios)


acoes <- yf_index_composition("IBOV")
Error in dplyr::rename(., ticker = Ticker, company = Company, industry = Industry) : 
  Can't rename columns that don't exist.
✖ Column `Ticker` doesn't exist.
Code
ibov_tickers <- paste0(acoes$ticker, ".SA")

retornos <- yf_get(tickers = ibov_tickers, 
                 first_date = "2010-01-01",
                 last_date  = "2025-06-30", 
                 freq_data = "monthly") |> 
  select(ref_date, ticker, ret_adjusted_prices) |> 
  pivot_wider(id_cols = ref_date, values_from = ret_adjusted_prices, names_from = ticker) |> 
  drop_na()
retornos[, -1] <- retornos[, -1]*100
glimpse(retornos)
Rows: 146
Columns: 62
$ ref_date  <date> 2013-05-02, 2013-06-03, 2013-07-01, 2013-08-01, 2013-09-02,…
$ ABEV3.SA  <dbl> 0.3056168, 1.0115736, 3.7524136, -2.8956906, 2.1994234, -1.4…
$ ALPA4.SA  <dbl> 13.7846801, -4.1860458, -2.8432371, -10.9171146, 14.8029227,…
$ AMER3.SA  <dbl> -13.1533087, -33.4001995, 59.6385516, 28.4905626, 4.0381733,…
$ B3SA3.SA  <dbl> 1.3353951, -12.0628146, -0.1622583, -3.3900006, 5.5413459, 1…
$ BBAS3.SA  <dbl> 0.9717961, -12.0879138, 2.7651635, 5.4268182, 13.6212622, 15…
$ BBDC3.SA  <dbl> 3.0777593, -13.7108681, 1.0421151, 2.3265905, 9.2100969, 4.1…
$ BBDC4.SA  <dbl> 4.253785, -15.585169, -3.582840, 0.289580, 9.519015, 6.09504…
$ BBSE3.SA  <dbl> 8.328420, -4.710329, 4.772727, 6.763616, 13.357592, 12.19625…
$ BEEF3.SA  <dbl> -7.4561264, -1.6113874, -12.3314046, 16.7032983, -4.8964333,…
$ BPAN4.SA  <dbl> -6.916422, -17.182659, 13.271025, -13.201328, -1.140670, 1.5…
$ BRAP4.SA  <dbl> -13.3883125, -8.8395309, 11.3873830, 10.1339283, -0.2837217,…
$ BRFS3.SA  <dbl> 1.56663092, -2.90465211, 1.12834948, 13.45678699, -2.0674725…
$ BRKM5.SA  <dbl> -4.3503317, -1.3165647, 6.6100661, 0.3412937, 0.6235933, 11.…
$ CMIG4.SA  <dbl> 2.2411527, -8.4986429, 5.2999715, -9.9231547, 2.3950012, 3.7…
$ COGN3.SA  <dbl> 11.6607691, -0.8373428, 5.5537329, -0.8642014, -1.9296559, 4…
$ CPFE3.SA  <dbl> 4.07975347, -7.75055272, 1.93143491, -5.68101498, -0.7168624…
$ CPLE6.SA  <dbl> -7.8903001, -14.6453666, 0.5755222, 2.2532402, 10.0034636, -…
$ CSAN3.SA  <dbl> -0.63026735, -8.45664886, -1.82446857, -0.18059887, 2.692314…
$ CSNA3.SA  <dbl> -16.434891, -9.833581, 10.234907, 32.312441, 11.294090, 29.4…
$ CYRE3.SA  <dbl> -4.4920007, -9.4117404, 5.7792244, -2.4554962, 5.4122033, 0.…
$ DXCO3.SA  <dbl> -3.642383, -11.821334, 2.999816, -6.738118, 8.292290, 5.9135…
$ ECOR3.SA  <dbl> -0.5578940, -7.6106032, 2.4904061, -4.6728980, -0.9150331, 0…
$ EGIE3.SA  <dbl> 3.6465865, -6.1705145, 4.9898619, -2.9983617, 7.2934990, 4.0…
$ ELET3.SA  <dbl> 12.780505, -18.197869, -1.079912, 8.733639, 25.501965, 13.60…
$ ELET6.SA  <dbl> 14.570997, -13.465344, -4.805484, 9.615374, 14.802651, 12.51…
$ EMBR3.SA  <dbl> 11.4131822, 4.7134135, -4.9951073, 1.4432852, -9.2505574, -8…
$ ENEV3.SA  <dbl> 10.081107, -20.526314, -5.752292, -29.064750, 6.490872, -14.…
$ ENGI11.SA <dbl> 6.1543192, -7.4672549, 1.9966570, 0.9500764, -8.1632449, 8.4…
$ EQTL3.SA  <dbl> -0.7626084, -11.7787555, 0.7567878, 7.5643813, 4.7381355, 10…
$ EZTC3.SA  <dbl> 8.3272793, -8.6941794, 1.0661503, -3.0556615, 14.1088306, 8.…
$ FLRY3.SA  <dbl> 4.8167693, -9.0909027, 6.5933923, -3.4449147, -0.5420055, -5…
$ GGBR4.SA  <dbl> -16.3298575, -3.7547732, 16.1624423, 18.0784800, -3.2069808,…
$ GOAU4.SA  <dbl> -18.39929612, -2.73720619, 14.00876931, 16.78334136, -0.0472…
$ HYPE3.SA  <dbl> 7.6836941, -15.4025648, 13.8621044, -1.3931055, 9.8280148, 9…
$ ITSA4.SA  <dbl> 4.5962132, -12.5205388, 1.9488618, 0.8599676, 7.7191175, 7.2…
$ ITUB4.SA  <dbl> 5.8642657, -11.1695218, 1.3398785, 0.6446509, 8.4324742, 10.…
$ JHSF3.SA  <dbl> -5.4925463, -8.5546031, -8.8709507, 15.9292370, -2.2900814, …
$ LREN3.SA  <dbl> -2.7415026, -14.0792491, -5.4772886, -4.9834518, 10.8849349,…
$ MGLU3.SA  <dbl> 13.8268514, -33.9877239, -5.0185929, 12.3287785, 31.5330857,…
$ MRFG3.SA  <dbl> 10.6881625, -2.1164171, -2.5675584, -15.3952845, -0.8196796,…
$ MRVE3.SA  <dbl> -20.1779658, -1.3636448, -0.3071923, 28.6594493, 9.1018157, …
$ MULT3.SA  <dbl> -1.7546483, -7.3276623, -2.4975420, -4.8054312, 10.5548756, …
$ PCAR3.SA  <dbl> 1.076900, 0.000000, 0.000000, 1.076874, 0.000000, 1.076896, …
$ PETR3.SA  <dbl> -1.1464296, -21.9821065, 3.9189227, 4.3563141, 5.6697842, 15…
$ PETR4.SA  <dbl> -0.1493007, -19.3918325, 0.7420910, 4.2971660, 8.0635654, 10…
$ PRIO3.SA  <dbl> -46.651269, 12.121214, -34.749033, -11.834318, -22.147654, -…
$ QUAL3.SA  <dbl> -2.9306122, -10.6991389, -0.9490091, 10.7784350, 9.4594715, …
$ RADL3.SA  <dbl> 5.8498750, -6.2498347, -10.2325311, -12.5389014, 8.6919015, …
$ RENT3.SA  <dbl> -3.44587845, -3.56604731, 2.95971261, -3.10767135, 4.5729341…
$ SANB11.SA <dbl> 4.6939009, -11.4283284, 1.1895991, 0.2204392, 10.4820754, 3.…
$ SBSP3.SA  <dbl> -4.6808484, -15.7366129, 3.3112663, -16.2820549, 10.4645110,…
$ SUZB3.SA  <dbl> 0.4344108, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.000…
$ TAEE11.SA <dbl> 5.5645274, -7.8879208, 6.8319861, -3.6355415, -3.1818400, 2.…
$ TIMS3.SA  <dbl> -4.12250928, -0.85995964, 5.08055699, 10.84905300, 9.3616933…
$ TOTS3.SA  <dbl> -0.1322666, -7.3112651, 2.8865378, 4.0717553, 0.4286171, 1.3…
$ UGPA3.SA  <dbl> 0.6743211, -1.3953476, 2.1697964, -2.4180052, 4.7327020, 9.2…
$ USIM5.SA  <dbl> -9.6446782, -15.9550487, 16.4438293, 19.2881902, 1.2512091, …
$ VALE3.SA  <dbl> -11.1986096, -5.0574510, 7.2985075, 10.7027711, 0.3494311, 6…
$ VIVT3.SA  <dbl> -1.498979, -2.173853, -2.533342, -6.520765, 5.129618, 3.3087…
$ WEGE3.SA  <dbl> 8.0121763, -0.3461561, 0.1347254, 0.0000000, -3.3027354, 7.7…
$ YDUQ3.SA  <dbl> 5.30808759, -3.84385567, 10.05622696, -0.11351016, -2.159073…

Aplicación

Code
n_obs <- nrow(retornos)
ins <- 120  
oos <- n_obs - ins
Rp <- matrix(NA, ncol = 10, nrow = oos)

for (i in 1:oos) {
  r <- retornos[i:(i + ins  - 1), -1]  
  Sigma <- cov(r)
  w_mv <- optimalPortfolio(Sigma, control = list(type = 'minvol', constraint = 'lo'))
  w_iv <- optimalPortfolio(Sigma, control = list(type = 'invvol', constraint = 'lo'))
  w_erc <- optimalPortfolio(Sigma, control = list(type = 'erc', constraint = 'lo'))
  w_md <- optimalPortfolio(Sigma, control = list(type = 'maxdiv', constraint = 'lo'))
  w_mdec <- optimalPortfolio(Sigma, control = list(type = 'maxdec', constraint = 'lo'))
  w_hrp <- HRP_Portfolio(Sigma)$w
  w_dhrp <- DHRP_Portfolio(Sigma)$w
  w_hcaa <- HCAA_Portfolio(Sigma)$w
  w_herc <- HERC_Portfolio(Sigma)$w
  Rp[i, ] <- c(mean(as.numeric(retornos[i + ins, -1])),
               sum(w_mv * retornos[i + ins, -1]),
               sum(w_iv * retornos[i + ins, -1]),
               sum(w_erc * retornos[i + ins, -1]),
               sum(w_md * retornos[i + ins, -1]),
               sum(w_mdec * retornos[i + ins, -1]),
               sum(w_hrp * retornos[i + ins, -1]),
               sum(w_dhrp * retornos[i + ins, -1]),
               sum(w_hcaa * retornos[i + ins, -1]),
               sum(w_herc * retornos[i + ins, -1]))
}
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 7"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 6"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 5"
[1] "Number of clusters: 7"
[1] "Number of clusters: 7"
[1] "Number of clusters: 8"
[1] "Number of clusters: 6"
[1] "Number of clusters: 6"
Code
colnames(Rp) <- c("EW", "Min Var", "Inv Vol", "ERC", "Max Div", "Max Dec", "HRP", "DHRP", "HCAA", "HERC")

Aplicación

Code
medidas <- function(x) {
  # Annualized Average
  AV <- mean(x)
  # Annualized SD
  SD <- sd(x)
  # Information (or Sharpe) Ratio
  SR <- mean(x)/sd(x)
  # Adjusted Sharpe Ratio
  ASR <- SR*(1 + (moments::skewness(x)/6)*SR - ((moments::kurtosis(x) - 3)/24)*SR^2)
  # Sortino Ratio
  SO <- mean(x)/sqrt(mean(ifelse(x < 0, 0, x^2)))
  output <- c(12*AV, sqrt(12)*SD, sqrt(12)*SR, sqrt(12)*ASR, sqrt(12)*SO)
  return(output)
}

Aplicación

Code
oos_table <- t(apply(Rp, 2, medidas))
colnames(oos_table) <- c("AV","SD", "SR", "ASR", "SO")
oos_table
              AV       SD        SR       ASR        SO
EW      14.45465 21.23668 0.6806455 0.6888845 0.8044590
Min Var 16.08747 14.58714 1.1028533 1.1245302 1.2067818
Inv Vol 13.84745 20.10744 0.6886730 0.6986633 0.8069384
ERC     14.61644 19.21489 0.7606830 0.7713146 0.8882399
Max Div 20.93918 17.84473 1.1734097 1.1999324 1.2845236
Max Dec 34.74333 28.19992 1.2320366 1.3356879 1.2475420
HRP     13.61572 17.58033 0.7744857 0.7860333 0.9005227
DHRP    14.25424 16.47468 0.8652210 0.8763874 1.0011150
HCAA    12.63425 18.50603 0.6827098 0.6954696 0.7964021
HERC    23.19181 30.46670 0.7612184 0.7768012 0.8745532

Temas de investigación

Temas de investigación

  • Costos de transacción / Optimización
  • Otros estimadores de la matriz de covarianza
  • Varianza (covarianza) condicional
  • Datos de alta dimensión
  • Datos de alta frecuencia
  • Metodologías híbridas
¿Ya conocen el CAREFS??]{style=“color:red;”}