Оптимизация портфеля в R с ТОЛЬКО вектором средней доходности и ковариационной матрицей

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

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

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

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

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

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


person theimmortal1    schedule 13.02.2020    source источник
comment
может быть актуально: cvxr.rbind.io/cvxr_examples/cvxr_portfolio-optimization   -  person chinsoon12    schedule 13.02.2020


Ответы (2)


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

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/

person ASH    schedule 15.02.2020

Если вы хотите использовать определенный пакет, и этот конкретный пакет допускает только временные ряды, тогда да, единственный способ использовать этот конкретный пакет — создать временные ряды, соответствующие вашим средним значениям и матрице дисперсии-ковариации. (Но вы можете проверить, как пакет вычисляет матрицу средних/вариаций-ковариаций из этих временных рядов.) См. https://stackoverflow.com/questions/58293991/how-to-use-fportfolio-package-in-r-for-non-time-series-input/58302451#58302451, чтобы узнать, как создавать такие серии.

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

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

person Enrico Schumann    schedule 13.02.2020
comment
Потрясающий! Фантастический пакет. Я не женат на каком-то конкретном пакете, поэтому я обязательно возьму ваш на тест-драйв. Из того, что я могу сказать, вы не предлагаете групповые ограничения, только минимальные/максимальные значения для активов. Есть планы на этот счет? Также вы заставляете его полностью вкладываться (суммировать до 1), я тоже ничего не видел по этому поводу. Спасибо еще раз! - person theimmortal1; 13.02.2020
comment
Групповое ограничение — потенциальный убийца сделки. Например, около половины моих активов — это акции, а другая половина — фиксированный доход. Общий капитал ограничен 60–80% и фиксирован на уровне 20–40%. Индивидуальных ограничений недостаточно для достижения этого ограничения. Как я могу сделать это в вашем пакете? Если нет, есть планы добавить? - person theimmortal1; 13.02.2020
comment
Спасибо. Портфели всегда полностью инвестированы. Групповые ограничения не реализованы. Но я только посмотрел на функции, и добавить их не должно быть слишком сложно. Если бы вы захотели их протестировать, я мог бы реализовать такие ограничения. (Последняя версия NMOF находится по адресу github.com/enricoschumann/NMOF .) - person Enrico Schumann; 14.02.2020
comment
К сведению, групповые ограничения теперь доступны в разрабатываемой версии NMOF. Я обновил ответ. - person Enrico Schumann; 17.02.2020