Portfolio Optimize in R with ONLY a vector of mean returns and covariance matrix

ε祈祈猫儿з 提交于 2021-01-29 14:20:09

问题


Every package that I look at seems to require time series returns for my assets.

For example I like the PortfolioAnalytics package, and I require many of the constraints offered (box constraints, group constraints, etc.). However, as far as I can tell it requires some sort of time series of returns, even if I specify my own moments (I could be wrong).

All I have are the expected returns of each of my 14 assets and the covariance matrix.

How can I do various forms of optimizations with that as my starting point? Ultimately I'd like to build a full efficient frontier as well as be able to maximize return at a given level of risk (standard deviation) given my constraints. If I had a time series this wouldn't be a problem...but alas I do not.

Thanks. I feel like this should be quite easy but I've been running in circles.

Worst case scenario is I could build a fake time series that fits the parameters of the E(R) and covariance matrix..if you think this is my solution can you offer me an easy way to do that...but that is why I am here :)


回答1:


How about this?

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)
  )

This should help as well.

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




回答2:


If you want to use a particular package, and that particular package allows only time-series, then yes, the only way for you to use that particular package is to create time-series that match your means and variance-covariance-matrix. (But you might want to check the way the package computes the means/variance-covariance-matrix from these time-series.) See https://stackoverflow.com/questions/58293991 for how to create such series.

For mean-variance optimisation, requiring time-series (and not providing an alternative, overriding method) would be a bad design choice on part of a package. (And I find it hard to believe that PortfolioAnalytics should not offer such a mechanism.) The input for mean-variance optimisation is a forecast of the means and a forecast of the variance-covariance matrix. Such forecasts may be informed by, or based on, historical data. But even then there are many different possibilities to compute such quantities, e.g. shrinkage.

In any case, the NMOF package, which I maintain, has functions minvar and mvPortfolio for computing minimum-variance and mean-variance-efficient portfolios based on mean vectors and variance-covariance matrices. In the development of version of NMOF, those function also allow the specification of group constraints.



来源:https://stackoverflow.com/questions/60199112/portfolio-optimize-in-r-with-only-a-vector-of-mean-returns-and-covariance-matrix

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!