2 votos

Replica de la varianza mínima de la cartera mediante la simulación de muchas carteras aleatorias en R

He calculado la cartera teórica de mínima varianza utilizando los 30 valores del Dow. La fórmula utilizada es:

$$\underset{N\times 1}{\omega_{mvp}}=\frac{\lambda}{2}\cdot \Sigma^{-1}\iota=\frac{\Sigma^{-1}\iota}{\iota'\Sigma^{-1}\iota}$$

Dónde $\iota$ es un $N\times 1$ vector que contiene 1's.

Para los datos descargados obtengo aproximadamente 0,0002712748, que llamo Sigma_mvp en el script.

A continuación, genero un millón de vectores diferentes que contienen 30 pesos cada uno para los activos. Las ponderaciones pueden ser negativas, y me aseguro de que sumen uno dividiendo con la suma de la columna.

Mi problema es : La menor varianza que consigo con estos pesos aleatorios es de 0,0004467729, así que algo debe estar mal.

¿Alguna idea? Espero que la pregunta esté clara.

Mi código se proporciona a continuación:

library(tidyquant)
library(tidyverse)

############ Getting Data for DOW ##############

tickers <- tq_index("DOW")

N <- length(tickers$symbol) # number of assets = 30

ones <- as.matrix(rep(1,N), ncol = 1) # one vector for later use

data <- tickers %>% tq_get(get = "stock.prices")

# calculate weekly returns

returns <- data %>% 
    group_by(symbol) %>% 
    tq_transmute(select = adjusted,
                 mutate_fun = to.weekly,
                 indexAt = "lastof") %>% 
    mutate(return = (log(adjusted) - log(lag(adjusted)))) %>% 
    na.omit()

# mean return vector

asset_returns <- returns %>% group_by(symbol) %>% 
  summarise(expected_return = mean(return)) %>% 
  select(expected_return) %>% as.matrix()

rownames(asset_returns) <- tickers$symbol %>% sort()

# create covariance matrix

Sigma <- returns %>%
  select(-adjusted) %>%
  pivot_wider(names_from = symbol, values_from = return) %>% # reorder data to a T x N matrix
   na.omit() %>% # remove NA that got generated by "DOW"
  select(-date) %>%
  cov(use = "pairwise.complete.obs")

Sigma <- Sigma[rownames(asset_returns),rownames(asset_returns)] # reorder matrix to match asset_return vector sequence

############## Generating random portfolios ###################

# random weights

w_rdm <- matrix(runif(n = 1000000 * N, min = -3, max = 3), nrow = N)

w_rdm <- apply(w_rdm,2,function(x){x/sum(x)})

# Create points

eff_frontier_rdm <- matrix(0, nrow = 1000000, ncol = 2)

for(i in 1:ncol(w_rdm)){

  eff_frontier_rdm[i,1] <- t(w_rdm[,i, drop = F]) %*% asset_returns

  eff_frontier_rdm[i,2] <- t(w_rdm[,i, drop = F]) %*% Sigma %*% w_rdm[,i, drop = F]

}

colnames(eff_frontier_rdm) <- c("return", "variance")

eff_frontier_rdm <- eff_frontier_rdm %>% as_tibble()

# smallest variance achieved with random portoflios

min(eff_frontier_rdm$variance)

# Computing the minimum variance portfolio

lambda <- 2 / as.numeric((t(ones) %*% solve(Sigma) %*% ones))

w_mvp <- (solve(Sigma) %*% ones) * lambda/2

Sigma_mvp <- t(w_mvp) %*% Sigma %*% w_mvp

# theoretical min variance portoflio

Sigma_mvp

He añadido una imagen de las carteras simuladas con el código de abajo, con la frontera eficiente teóricamente correcta.

enter image description here

Basándome en las respuestas, he conseguido crear lo siguiente

Gracias por las diferentes sugerencias. Basado en las respuestas anteriores, resolví mi problema con el siguiente procedimiento:

Dada una matriz de covarianza , y un vector de retorno esperado, que llamo asset_returns, utilicé los siguientes pasos:

Utilice el teorema de los dos fondos mutuos para elegir alguna matriz de pesos aleatoria, de una cartera situada en la frontera. Añade algo de ruido a cada peso, extrayéndolo de una normal estándar. Normalice el vector creado dividiéndolo por la suma. Calcule la varianza de la cartera y la rentabilidad esperada con el vector de pesos creado. Después de crear 1 millón de estas ponderaciones aleatorias, consigo rellenar la zona de la frontera. Creando más puntos se llenaría todo.

La solución se basa en las respuestas que obtuve aquí en el post.

eff_frontier_rdm <- matrix(0, nrow = 1000000, ncol = 2)

for(i in 1:nrow(eff_frontier_rdm)){

  c <- runif(1, min = -4, max = 4) # draw random number

  w = c * w_mvp + (1-c) * port_2$w_eff # create weight

  eps <- matrix(rnorm(N, mean = 0, sd = 0.1), ncol = 1)

  w = w + eps

  w = w / sum(w)

  eff_frontier_rdm[i,1] <- t(w) %*% asset_returns

  eff_frontier_rdm[i,2] <- t(w) %*% Sigma %*% w

}

enter image description here

1voto

BigCanOfTuna Puntos 210

Es normal que se necesite muy de acercarse a la la frontera eficiente con carteras aleatorias.

La rapidez con la que te acerques estará fuertemente influenciada por la forma en que muestres las carteras. En su código, usted muestreo uniforme. Es posible que desee ver las distribuciones de peso peso de las carteras en la frontera, y luego considerar qué probabilidad hay de llegar a tales carteras a través de su procedimiento de muestreo.

Patrick Burns ( https://www.burns-stat.com/ , https://papers.ssrn.com/sol3/cf_dev/AbsByAuth.cfm?per_id=59330 ) ha escrito muchas cosas interesantes sobre las carteras aleatorias; también sobre cómo construirlas.

0voto

user847095 Puntos 21

¿Por qué esperaba alcanzar la cartera de varianza mínima en sus simulaciones?

Existen infinitos vectores de tamaño Nx1, tales que la suma de sus elementos suma 1. Incluso con 1 millón de simulaciones, es muy difícil dar con el vector exacto de asignación de varianza mínima.

Además, sus simulaciones podrían haber dado con algún vector de asignación "muy cercano" al de mínima varianza (muy cercano significa un valor bajo de la norma de la diferencia de vectores). Si su matriz de covarianza está mal condicionada, entonces el vector de asignación que está "muy cerca" de la varianza mínima podría dar lugar a una cartera simulada con una varianza significativamente mayor que la óptima.

0voto

Akash Puntos 8

No estoy seguro de por qué querrías dar con esto a través de un muestreo de prueba y error en primer lugar.

Por definición, la cartera MinVar es la cartera tangente / MaxSharpe si se supone que todos los rendimientos son constantes/iguales. Véanse las páginas 7-10 de, por ejemplo https://faculty.washington.edu/ezivot/econ424/portfolioTheoryMatrix.pdf

0voto

Corey Goldberg Puntos 15625

Creo que entiendo tu problema. Sus pesos no están distribuidos uniformemente en el espacio deseado. En su lugar, los pesos están agrupados, hay menos pesos extremos (pesos cercanos a 1) de los que debería haber.

Por ejemplo, consideremos con qué frecuencia el primer peso (o cualquier otro peso) debe estar entre 0,8 y 1,0. Dado que la longitud del intervalo [0,8,1,0] es la décima parte del intervalo [-1,0,1,0], el diez por ciento de los vectores generados debería tener un primer peso entre 0,8 y 1,0. (¿De acuerdo?). Si pruebas tus vectores generados aleatoriamente, creo que encontrarás que mucho menos del 10% de tus primeros pesos están en este intervalo (quizás ninguno).

Cómo puede ser esto, se preguntarán, dado que en el primer paso se generan pesos al azar entre -1 y 1. El problema viene en el segundo paso, donde se divide por la suma de pesos. Como dice un refrán japonés: "Cuanto más largo es un clavo, más se martilla". Si uno (o más) de los pesos aleatorios está cerca de 1, la suma de pesos será grande y la división "martilleará" el peso grande en consecuencia. Resultado: muy pocos pesos grandes. Pero no te fíes de mi intuición, comprueba los datos generados.

¿Cuál es la solución? ¿Cómo se generan las ponderaciones de la cartera de manera uniforme? El sitio web de Patrick Burns enlazado por el Sr. Schumann puede ser útil. Personalmente descubrí este problema en un contexto en el que tenía que generar pesos entre 0 y 1. Me resultó útil esta pregunta de CS StackExchange https://cs.stackexchange.com/questions/3227/uniform-sampling-from-a-simplex . Incluso escribí uno de los algoritmos aquí Carteras aleatorias frente a la frontera eficiente (Creo que las imágenes de este enlace te resultarán familiares, muy pocos puntos cerca de la frontera). Tu problema es un poco diferente, ya que permites posiciones cortas por lo que tus pesos tienen que estar entre -1 y +1. Los algoritmos tendrán que ser modificados en consecuencia.

Mi idea al respecto es que, dado que una cartera larga/corta se compone de una cartera larga y otra corta, se podrían generar las ponderaciones positivas y negativas por separado. Pero no he concretado exactamente cómo funcionaría esto. Espero que mis observaciones anteriores ayuden algo.

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X