[R-SIG-Finance] Using optimize.portfolio
Brian G. Peterson
br|@n @end|ng |rom br@verock@com
Mon Jun 8 02:59:08 CEST 2020
Roger,
If no Return cleaning method is specified, the default portfolio
moments function will use pairwise complete observations:
if you pass momentargs, the internal calculations for mu and sigma will
be replaced by momentargs$mu and momentargs$sigma
Alexios has already pointed out the return target, which is not
specified in your objectives for optimize.portfolio.
I also note that you're using DEoptim, which is unecessarily slow (and
may not always converge to the same result) for a simple mean variance
optimization. You probably want optimize.method='ROI', which will use
the same direct quadratic approach. DEoptim (or 'random' or 'GEnSA',
or 'pso') make sense for more complex objectives that aren't amenable
to convex solvers.
Regards,
Brian
--
Brian G. Peterson
ph: +1.773.459.4973
im: bgpbraverock
On Sun, 2020-06-07 at 20:14 -0400, 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
> optimizeportfolio, a custom function and using momentargs list. The
> example codeat the end of this email uses both of those methods, as
> well as the defaultmethod. I also compare those to portfolio.optim
> and parma.
> I get quite different results for each method. I know that they will
> notbe exactly the same, but surely I am doing something wrong given
> theresults I am getting. I would hope that all three optimize
> portfoliomethods would give me the same results. Here are the
> results I am getting:
> opt.portf opt.portf.fun opt.portf.args portfolio.optim
> parmaMSFT 0.372 0.190 0.448 0.253
> 0.000AAPL 0.008 0.094 0.044 0.208
> 0.357AMZN 0.000 0.076 0.000 0.055
> 0.119NVDA 0.020 0.000 0.000 0.020
> 0.169CSCO 0.000 0.004 0.002 0.000
> 0.000ADBE 0.004 0.040 0.002 0.033
> 0.032AMGN 0.298 0.348 0.382 0.253
> 0.000ORCL 0.068 0.072 0.010 0.002
> 0.000QCOM 0.072 0.000 0.000 0.000
> 0.000GILD 0.158 0.176 0.112 0.177
> 0.322
> opt.portf is optimize.portfolio with internal mu and
> sigmaopt.portf.fun is optimize.portfolio with mu and sigma provided
> in momentFUNopt.portf.args is optimize.portfolio with mu and sigma
> provided inmomentargs
> So if optimize portfolio just uses the column means for mu and cov
> forsigma, why am I getting different results than when I use a custom
> functionor pass in the moments? Obviously I am doing something wrong
> since I getdifferent results when using momentFUN and
> momentargs. Thanks in advancefor any help, Roger.
> ###
> library(tidyquant)symbols <-
> c("MSFT","AAPL","AMZN","NVDA","CSCO","ADBE","AMGN","ORCL","QCOM","GIL
> D")
> 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 packagelibrary(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
> > > > PortfolioAnalyticspackage toportfolio.optim from the tseries
> > > > package. portfolio.optim seems abiteasier to use, but I like
> > > > the set up of optimize.portfolio. I havecreateda minimal
> > > > reprex below that compares the output of both in casethat
> > > > helpsanswer my questions.Here are my two primary questions:
> > > > 1) What if I wanted to pass a custom covariance matrix
> > > > tooptimize.portfolio, like from a risk model. Is that
> > > > possible? Ican passit to portfolio.optim because covmat is one
> > > > of the parameters.2) What if I wanted to pass forecasted
> > > > returns tooptimize.portfolio? Howwould that be done.
> > > > If there is anything that can be improved in this example,
> > > > thatwould behelpful 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
> > > > ","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 packagelibrary(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="retu
> > > > rn", 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'
> > > perdefault computes means and covariances in the standard way,
> > > you couldcreate input data (time series) that have exactly the
> > > desiredcovariances 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
> > wouldexpect.
> > As I already told the OP, the user may pass mu and sigma and m3 and
> > m4directly, or may construct custom moment functions to compute
> > themoments 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.
cov(tmpR, use = "pairwise.complete.obs")
[[alternative HTML version deleted]]
More information about the R-SIG-Finance
mailing list