[R-SIG-Finance] Using optimize.portfolio

alexios galanos @|ex|o@ @end|ng |rom 4d@c@pe@com
Mon Jun 8 02:44:10 CEST 2020


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



More information about the R-SIG-Finance mailing list