Оптимизация портфеля в R с ТОЛЬКО вектором средней доходности и ковариационной матрицей - PullRequest
0 голосов
/ 13 февраля 2020

Кажется, что каждый пакет, на который я смотрю, требует возврата временных рядов для моих активов.

Например, мне нравится пакет PortfolioAnalytics, и мне требуются многие из предложенных ограничений (ограничения блока, ограничения группы и т. Д. c.). Однако, насколько я могу судить, это требует некоторого временного ряда возвратов, даже если я указываю свои собственные моменты (я могу ошибаться).

Все, что у меня есть, - это ожидаемая доходность каждого из моих 14 активов и ковариационная матрица.

Как я могу проводить различные формы оптимизации с этим в качестве отправной точки ? В конечном счете, я хотел бы построить полную эффективную границу, а также иметь возможность максимизировать доходность при данном уровне риска (стандартное отклонение) с учетом моих ограничений. Если бы у меня был временной ряд, это не было бы проблемой ... но, увы, нет.

Спасибо. Я чувствую, что это должно быть довольно легко, но я бегаю кругами.

В худшем случае я мог бы построить фиктивный временной ряд, который соответствует параметрам E (R) и ковариационной матрицы ... если вы думаете, что это мое решение, вы можете предложить мне простой способ сделать это. ..но вот почему я здесь :)

Ответы [ 2 ]

0 голосов
/ 15 февраля 2020

Как насчет этого?

library(stockPortfolio)
library(quadprog)
library(ggplot2)
stocks <- c("SPY",  "EFA",  "IWM",  "VWO",  "LQD",  "HYG")

returns <- getReturns(stocks, freq = "week")

eff.frontier <-  function (returns,
                           short = "no",
                           max.allocation = NULL,
                           risk.premium.up = .5,
                           risk.increment = .005) {
  covariance <- cov(returns)
  print(covariance)
  n <- ncol(covariance)

  # Create initial Amat and bvec assuming only equality constraint (short-selling is allowed, no allocation constraints)
  Amat <- matrix (1, nrow = n)
  bvec <- 1
  meq <- 1

  # Then modify the Amat and bvec if short-selling is prohibited
  if (short == "no") {
    Amat <- cbind(1, diag(n))
    bvec <- c(bvec, rep(0, n))
  }

  # And modify Amat and bvec if a max allocation (concentration) is specified
  if (!is.null(max.allocation)) {
    if (max.allocation > 1 | max.allocation < 0) {
      stop("max.allocation must be greater than 0 and less than 1")
    }
    if (max.allocation * n < 1) {
      stop("Need to set max.allocation higher; not enough assets to add to 1")
    }
    Amat <- cbind(Amat, -diag(n))
    bvec <- c(bvec, rep(-max.allocation, n))
  }

  # Calculate the number of loops based on how high to vary the risk premium and by what increment
  loops <- risk.premium.up / risk.increment + 1
  loop <- 1

  # Initialize a matrix to contain allocation and statistics
  # This is not necessary, but speeds up processing and uses less memory
  eff <- matrix(nrow = loops, ncol = n + 3)
  # Now I need to give the matrix column names
  colnames(eff) <-
    c(colnames(returns), "Std.Dev", "Exp.Return", "sharpe")

  # Loop through the quadratic program solver
  for (i in seq(from = 0, to = risk.premium.up, by = risk.increment)) {
    dvec <-
      colMeans(returns) * i # This moves the solution up along the efficient frontier
    sol <-
      solve.QP(
        covariance,
        dvec = dvec,
        Amat = Amat,
        bvec = bvec,
        meq = meq
      )
    eff[loop, "Std.Dev"] <-
      sqrt(sum(sol$solution * colSums((
        covariance * sol$solution
      ))))
    eff[loop, "Exp.Return"] <-
      as.numeric(sol$solution %*% colMeans(returns))
    eff[loop, "sharpe"] <-
      eff[loop, "Exp.Return"] / eff[loop, "Std.Dev"]
    eff[loop, 1:n] <- sol$solution
    loop <- loop + 1
  }

  return(as.data.frame(eff))
}

eff <-
  eff.frontier(
    returns = returns$R,
    short = "yes",
    max.allocation = .45,
    risk.premium.up = .5,
    risk.increment = .001
  )


eff.optimal.point <- eff[eff$sharpe == max(eff$sharpe),]

ealred  <- "#7D110C"
ealtan  <- "#CDC4B6"
eallighttan <- "#F7F6F0"
ealdark  <- "#423C30"
ggplot(eff, aes(x = Std.Dev, y = Exp.Return)) + geom_point(alpha = .1, color =
                                                             ealdark) +
  geom_point(
    data = eff.optimal.point,
    aes(x = Std.Dev, y = Exp.Return, label = sharpe),
    color = ealred,
    size = 5
  ) +
  annotate(
    geom = "text",
    x = eff.optimal.point$Std.Dev,
    y = eff.optimal.point$Exp.Return,
    label = paste(
      "Risk: ",
      round(eff.optimal.point$Std.Dev * 100, digits = 3),
      "\nReturn: ",
      round(eff.optimal.point$Exp.Return * 100, digits =
              4),
      "%\nSharpe: ",
      round(eff.optimal.point$sharpe * 100, digits = 2),
      "%",
      sep = ""
    ),
    hjust = 0,
    vjust = 1.2
  ) +
  ggtitle("Efficient Frontier\nand Optimal Portfolio") + labs(x = "Risk (standard deviation of portfolio variance)", y =
                                                                "Return") +
  theme(
    panel.background = element_rect(fill = eallighttan),
    text = element_text(color = ealdark),
    plot.title = element_text(size = 24, color = ealred)
  )

Это также должно помочь.

https://www.r-bloggers.com/a-gentle-introduction-to-finance-using-r-efficient-frontier-and-capm-part-1/

0 голосов
/ 13 февраля 2020

Если вы хотите использовать конкретный пакет, и этот конкретный пакет допускает только временные ряды, то да, единственный способ для вас использовать этот конкретный пакет - это создать временные ряды, которые соответствуют вашим средствам и дисперсии-ковариации- матрица. (Но вы, возможно, захотите проверить способ, которым пакет вычисляет средство / дисперсию-ковариацию-матрицу из этих временных рядов.) См. { ссылка }, чтобы узнать, как создать такой ряд.

Для оптимизации среднего отклонения требование временных рядов (и не предоставление альтернативного, переопределяющего метода) было бы плохим выбором дизайна для части пакета. (И мне трудно поверить, что PortfolioAnalytics не должен предлагать такой механизм.) Вход для оптимизации средней дисперсии - это прогноз средних значений и прогноз матрицы дисперсии-ковариации. Такие прогнозы могут основываться или основываться на исторических данных. Но даже тогда есть много различных возможностей для вычисления таких величин, например, усадка.

В любом случае, пакет NMOF , который, как я утверждаю, имеет функции minvar и mvPortfolio для вычисления портфеля с минимальной дисперсией и средней дисперсией ios на основе средних векторов и матриц дисперсии-ковариации. При разработке версии NMOF эти функции также позволяют задавать групповые ограничения.

...