[R-SIG-Finance] Using optimize.portfolio

Roger Bos roger@bo@ @end|ng |rom gm@||@com
Mon Jun 8 02:54:22 CEST 2020


Thank you Alexios.  That is very helpful.

On Sun, Jun 7, 2020 at 8:44 PM alexios galanos <alexios using 4dscape.com> wrote:

> Roger,
>
> The portfolio.optim function calculates the minimum risk portfolio given
> a desired level of portfolio return (the default pm input is mean(x)).
> Here is an example versus parma:
>
> LB <- rep(0, ncol(returns))
> UB <- rep(1, ncol(returns))
> popt <- portfolio.optim(x = returns, reslow = LB, reshigh = UB)
>
> library(parma)
> # optimal reward to risk (covariance matrix)
> parmspec <- parmaspec(scenario = returns, risk = "EV", forecast =
> colMeans(returns), riskType = "minrisk", LB = LB, UB = UB, target =
> mean(returns))
> parm <- parmasolve(parmspec)
>
> round(cbind(weights(parm), popt$pw), 3)
>        [,1]  [,2]
> MSFT 0.253 0.253
> AAPL 0.208 0.208
> AMZN 0.055 0.055
> NVDA 0.020 0.020
> CSCO 0.000 0.000
> ADBE 0.033 0.033
> AMGN 0.253 0.253
> ORCL 0.002 0.002
> QCOM 0.000 0.000
> GILD 0.177 0.177
>
> Exact same results.
>
> Regards,
>
> Alexios
>
>
> On 6/7/20 5:14 PM, Roger Bos wrote:
> > Thank you to everyone for your suggestions, but I am still having
> trouble.
> > I see that there are two ways to pass custom moments into optimize
> > portfolio, a custom function and using momentargs list.  The example code
> > at the end of this email uses both of those methods, as well as the
> default
> > method.  I also compare those to portfolio.optim and parma.
> >
> > I get quite different results for each method.  I know that they will not
> > be exactly the same, but surely I am doing something wrong given the
> > results I am getting.  I would hope that all three optimize portfolio
> > methods would give me the same results.  Here are the results I am
> getting:
> >
> >               opt.portf opt.portf.fun opt.portf.args portfolio.optim
> parma
> > MSFT     0.372         0.190          0.448           0.253 0.000
> > AAPL     0.008         0.094          0.044           0.208 0.357
> > AMZN     0.000         0.076          0.000           0.055 0.119
> > NVDA     0.020         0.000          0.000           0.020 0.169
> > CSCO     0.000         0.004          0.002           0.000 0.000
> > ADBE     0.004         0.040          0.002           0.033 0.032
> > AMGN     0.298         0.348          0.382           0.253 0.000
> > ORCL     0.068         0.072          0.010           0.002 0.000
> > QCOM    0.072         0.000          0.000           0.000 0.000
> > GILD       0.158         0.176          0.112           0.177 0.322
> >
> > opt.portf is optimize.portfolio with internal mu and sigma
> > opt.portf.fun is optimize.portfolio with mu and sigma provided in
> momentFUN
> > opt.portf.args is optimize.portfolio with mu and sigma provided in
> > momentargs
> >
> > So if optimize portfolio just uses the column means for mu and cov for
> > sigma, why am I getting different results than when I use a custom
> function
> > or pass in the moments?  Obviously I am doing something wrong since I get
> > different results when using momentFUN and momentargs.  Thanks in advance
> > for any help, Roger.
> >
> > ###
> >
> > library(tidyquant)
> > symbols <-
> > c("MSFT","AAPL","AMZN","NVDA","CSCO","ADBE","AMGN","ORCL","QCOM","GILD")
> >
> > getYahooReturns <- function(symbols, return_column = "Ad") {
> >    returns <- list()
> >    for (symbol in symbols) {
> >      getSymbols(symbol, from = '2000-01-01', adjustOHLC = TRUE, env =
> > .GlobalEnv, auto.assign = TRUE)
> >      return <- Return.calculate(Ad(get(symbol)))
> >      colnames(return) <- gsub("\\.Adjusted", "", colnames(return))
> >      returns[[symbol]] <- return
> >    }
> >    returns <- do.call(cbind, returns)
> >    return(returns)
> > }
> >
> > returns <- getYahooReturns(symbols)
> > returns <- returns[-1, ]
> > returns[is.na(returns)] <- 0
> >
> > # portfolio.optim from tseries package
> > library(tseries)
> > LB <- rep(0, ncol(returns))
> > UB <- rep(1, ncol(returns))
> > popt <- portfolio.optim(x = returns, covmat = sigma, reslow = LB,
> reshigh =
> > UB)
> >
> > library(parma)
> > # optimal reward to risk (covariance matrix)
> > parmspec <- parmaspec(S = cov(returns), risk = "EV", forecast =
> > colMeans(returns), riskType = "optimal", LB = LB, UB = UB)
> > parm <- parmasolve(parmspec)
> >
> > library(PortfolioAnalytics)
> > simple.moments <- function(R, ...) {
> >    num_assets = ncol(R)
> >    out <- list()
> >    out$mu <- matrix(colMeans(R), ncol = 1)
> >    out$sigma <- cov(R)
> >    # out$m3 <- PerformanceAnalytics:::M3.MM(R)
> >    # out$m4 <- PerformanceAnalytics:::M4.MM(R)
> >    out$m3 <- matrix(0, nrow = num_assets, ncol = num_assets^2)
> >    out$m4 <- matrix(0, nrow = num_assets, ncol = num_assets^3)
> >    out
> > }
> >
> > num_assets = ncol(returns)
> > momentargs <- list()
> > momentargs$mu <- matrix(colMeans(returns), ncol = 1)
> > momentargs$sigma <- cov(returns)
> > momentargs$m3 <- matrix(0, nrow = num_assets, ncol = num_assets^2)
> > momentargs$m4 <- matrix(0, nrow = num_assets, ncol = num_assets^3)
> >
> > pspec <- portfolio.spec(assets = symbols)
> > pspec <- add.constraint(portfolio=pspec, type="box", min = 0, max = 1,
> > min_sum = 0.99, max_sum = 1.01)
> > pspec <- add.objective(portfolio=pspec, type="return", name="mean")
> > pspec <- add.objective(portfolio=pspec, type="risk", name="var")
> >
> > opt      <- optimize.portfolio(R = returns, portfolio = pspec,
> > optimize_method = "DEoptim")
> > opt.fun  <- optimize.portfolio(R = returns, portfolio = pspec,
> > optimize_method = "DEoptim", momentFUN = "simple.moments")
> > opt.args <- optimize.portfolio(R = returns, portfolio = pspec,
> > optimize_method = "DEoptim", momentargs = momentargs)
> > data.frame(opt.portf = opt$weights,
> >             opt.portf.fun = opt.fun$weights,
> >             opt.portf.args = opt.args$weights,
> >             portfolio.optim = round(popt$pw, 3),
> >             parma = round(weights(parm), 3))
> >
> >
> > On Sat, Jun 6, 2020 at 8:38 AM Brian G. Peterson <brian using braverock.com>
> > wrote:
> >
> >> On Sat, 2020-06-06 at 14:33 +0200, Enrico Schumann wrote:
> >>> On Fri, 05 Jun 2020, Roger Bos writes:
> >>>
> >>>> All,
> >>>>
> >>>> I am comparing optimize.portfolio from the PortfolioAnalytics
> >>>> package to
> >>>> portfolio.optim from the tseries package.  portfolio.optim seems a
> >>>> bit
> >>>> easier to use, but I like the set up of optimize.portfolio.  I have
> >>>> created
> >>>> a minimal reprex below that compares the output of both in case
> >>>> that helps
> >>>> answer my questions.
> >>>> Here are my two primary questions:
> >>>>
> >>>> 1) What if I wanted to pass a custom covariance matrix to
> >>>> optimize.portfolio, like from a risk model.  Is that possible?  I
> >>>> can pass
> >>>> it to portfolio.optim because covmat is one of the parameters.
> >>>> 2) What if I wanted to pass forecasted returns to
> >>>> optimize.portfolio?  How
> >>>> would that be done.
> >>>>
> >>>> If there is anything that can be improved in this example, that
> >>>> would be
> >>>> helpful as well.  Thank you in advance for any assistance, Roger.
> >>>>
> >>>> ###
> >>>>
> >>>> library(PortfolioAnalytics)
> >>>> library(tidyquant)
> >>>>
> >>>> symbols <-
> >>>> c("MSFT","AAPL","AMZN","NVDA","CSCO","ADBE","AMGN","ORCL","QCOM","G
> >>>> ILD")
> >>>>
> >>>> getYahooReturns <- function(symbols, return_column = "Ad") {
> >>>>    returns <- list()
> >>>>    for (symbol in symbols) {
> >>>>      getSymbols(symbol, from = '2000-01-01', adjustOHLC = TRUE, env
> >>>> =
> >>>> .GlobalEnv, auto.assign = TRUE)
> >>>>      return <- Return.calculate(Ad(get(symbol)))
> >>>>      colnames(return) <- gsub("\\.Adjusted", "", colnames(return))
> >>>>      returns[[symbol]] <- return
> >>>>    }
> >>>>    returns <- do.call(cbind, returns)
> >>>>    return(returns)
> >>>> }
> >>>>
> >>>> returns <- getYahooReturns(symbols)
> >>>> returns <- returns[-1, ]
> >>>> returns[is.na(returns)] <- 0
> >>>>
> >>>> # portfolio.optim from tseries package
> >>>> library(tseries)
> >>>> sigma <- cov(returns)
> >>>> reslow <- rep(0, ncol(returns))
> >>>> reshigh <- rep(1, ncol(returns))
> >>>> popt <- portfolio.optim(x = returns, covmat = sigma, reslow =
> >>>> reslow,
> >>>> reshigh = reshigh)
> >>>> popt$pw
> >>>>
> >>>> pspec <- portfolio.spec(assets = symbols)
> >>>> pspec <- add.constraint(portfolio=pspec, type="box",
> >>>>                      min = 0, max = 1, min_sum = 0.99, max_sum =
> >>>> 1.01)
> >>>> pspec <- add.objective(portfolio=pspec,
> >>>>                         type="return",
> >>>>                         name="mean")
> >>>> pspec <- add.objective(portfolio=pspec,
> >>>>                         type="risk",
> >>>>                         name="var")
> >>>>
> >>>> opt <- optimize.portfolio(R = returns,
> >>>>                     portfolio = pspec,
> >>>>                     optimize_method = "DEoptim", )
> >>>> data.frame(optimize.portfolio = opt$weights, portfolio.optim =
> >>>> round(popt$pw, 3))
> >>>>
> >>>
> >>> If all else fails, and supposing that 'PortfolioAnalytics' per
> >>> default computes means and covariances in the standard way, you could
> >>> create input data (time series) that have exactly the desired
> >>> covariances and means:
> >>>
> >>>
> >>>
> >>
> https://stackoverflow.com/questions/58293991/how-to-use-fportfolio-package-in-r-for-non-time-series-input/58302451#58302451
> >>>
> >>
> >> per default, PortfolioAnalytics uses sample moments as most users would
> >> expect.
> >>
> >> As I already told the OP, the user may pass mu and sigma and m3 and m4
> >> directly, or may construct custom moment functions to compute the
> >> moments using any method they choose.
> >>
> >> This is outlined in section 2 of the vignette:
> >>
> >>
> >>
> https://cran.r-project.org/web/packages/PortfolioAnalytics/vignettes/custom_moments_objectives.pdf
> >>
> >>
> >> and, of course, in the manual.
> >>
> >>
> >
> >       [[alternative HTML version deleted]]
> >
> > _______________________________________________
> > R-SIG-Finance using r-project.org mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-sig-finance
> > -- Subscriber-posting only. If you want to post, subscribe first.
> > -- Also note that this is not the r-help list where general R questions
> should go.
> >
>

	[[alternative HTML version deleted]]



More information about the R-SIG-Finance mailing list