[R-SIG-Finance] minimum variance portfolio (no shorts)
Brian G. Peterson
brian at braverock.com
Sun Feb 19 01:15:13 CET 2012
On Sat, 2012-02-18 at 18:48 -0500, benn fine wrote:
> Thank you for your swift response:
>
>
> For other newbies who might have a similar issue, can you review the
> following lines of code?
>
>
> for background, I have three assets and want to find the minimum
> vairance portfolio allowing short sales (once I confirm I get the same
> as from Zivot's code and excel I will work with long only).
Long only is much easier than long short... you'd be much better off
starting there to make sure you understand what you're doing.
If you really only want a minimum variance objective, used the closed
form solution provided by Eric. Using a global optimizer when a closed
form exists is a waste of computational power, and will have decreased
accuracy unless you do a large global search.
> Here are the weights I am expecting:
>
>
> > foo=globalMin.portfolio(mu.hat,cov.hat)
> > foo
> Call:
> globalMin.portfolio(er = mu.hat, cov.mat = cov.hat)
You never say, but I assume that these are sample means and variances,
and not some
> Portfolio expected return: 0.005188703
> Portfolio standard deviation: 0.04135499
> Portfolio weights:
> monthly.returns monthly.returns.1 monthly.returns.2
> -0.5894 0.3976 1.1918
>
>
> I think I am getting close with optimize.portfolio but I am getting
> error messages about risk over 100%.
> Can you please comment on any errors you see below?
>
>
> myconstr=constraint(assets=3, min_sum=1, max_sum=1, min=-1.5,
> max=1.5,weight_seq=generatesequence())
So, now you're now saying that you want a long/short portfolio where the
weights sum to 1, but the minimum or maximum weight may be 150% of
capital. Is this what you want? This will create a portfolio that is
not 'long/short neutral' which is usually what people want when they say
they want long/short (weights sum to approximately zero, not 1).
As noted in the documentation and our seminar slides, min_sum and
max_sum should probably have some delta around your desired sum, so that
generatesequence() will be faster.
> aConstraintObj = add.objective(constraints =
> myconstr,
> type="risk",
> name="var",
> enabled=TRUE)
>
>
> optimize.portfolio(myrets,aConstraintObj,optimize_method="DEoptim")
You probably want to start with random portfolios until you get some
intuition for what you're doing, as I've said many times before, DEoptim
will be more accurate and slower.
- Brian
>
> On Sat, Feb 18, 2012 at 6:08 PM, Brian G. Peterson
> <brian at braverock.com> wrote:
> On Sat, 2012-02-18 at 17:37 -0500, benn fine wrote:
> > I realize this topic has been hashed to death but i think
> the multitude of
> > answers is confusing me.
> >
> > I have mu,hat and cov.hat and a time series object of
> returns.
> > I want the minimum variance portfolio without short sales
> >
> > Is there a basic function somewhere that does that? I'm
> finding
> > minvariancePortfolio in Fportfolio a little tricky to use.
>
>
> 'a little tricky to use' is hardly reproducible.
>
> > I am trying the optimizeportfolio routine in
> PortfolioAnalytics. But the
> > results seem a bit odd.
>
>
> PortfolioAnalytics will give the correct result given the
> correct
> objective function, but in any event I wouldn't use a global
> solver when
> a simple closed form solution is available.
> Portfolioanalytics, as
> stated in the documentation or our seminar slides, is designed
> for much
> more complex objectives for which no closed form solution
> exists.
>
> > I have some code from Eric Zivot's website to compute the
> global minimum
> > variance portfolio (see below).
> > When I run it on a simple 4 asset example, I don't get the
> same result as
> > optimize.portfolio, and in
> > fact the optimize.portfolio weights give a larger portfolio
> variance.
> >
> > Here is the call for optimize.portoflio:
> >
> > myconstr=constraint(assets=4, min_sum=1, max_sum=1,
> min=-100,
> > max=100,weight_seq=generatesequence())
> > optimize.portfolio(myrets,myconstr)
>
>
> ouch. weights are PERCENTAGES. This is clearly stated in the
> documentation, and in all the examples and lecture slides.
>
> You said *without short sales*, yet this is 100x leveraged
> long/short
> portfolio.
>
> > Has someone written a nice wrapper to easily get the min
> variance portfolio
> > wo short sales?
>
>
> I don't know how much nicer you expect than three lines of
> code...
>
> > Any ideas why Eric's code (which I trust) gives a different
> answer from
> > opitimize.portfolio?
>
>
> You put in the wrong constraints.
>
> You also don't show the rest of your objective function here.
>
> Right now, you're using a 100x leveraged long/short portfolio
> and no
> objective...
>
> You'll want to fix your min and max arguments, and have at
> least one
> add.objective call.
>
> Please look at the seminar slides from R/Finance
>
> http://www.rinfinance.com/agenda/2010/Carl+Peterson
> +Boudt_Tutorial.pdf
>
> - Brian
>
> >
> > Thanks! Sorry for the cluelessness.
> >
> > globalMin.portfolio <-
> > function(er, cov.mat)
> > {
> > # Compute global minimum variance portfolio
> > #
> > # inputs:
> > # er N x 1 vector of
> expected returns
> > # cov.mat N x N return covariance matrix
> > #
> > # output is portfolio object with the following elements
> > # call original function call
> > # er portfolio expected
> return
> > # sd portfolio standard
> deviation
> > # weights N x 1 vector of portfolio weights
> > call <- match.call()
> >
> > #
> > # check for valid inputs
> > #
> > asset.names <- names(er)
> > er <- as.vector(er) #
> assign names if none exist
> > cov.mat <- as.matrix(cov.mat)
> > if(length(er) != nrow(cov.mat))
> > stop("invalid inputs")
> > if(any(diag(chol(cov.mat)) <= 0))
> > stop("Covariance matrix not positive definite")
> > # remark: could use generalized inverse if cov.mat is
> positive semi-definite
> >
> > #
> > # compute global minimum portfolio
> > #
> > cov.mat.inv <- solve(cov.mat)
> > one.vec <- rep(1,length(er))
> > # w.gmin <- cov.mat.inv %*% one.vec/as.vector(one.vec %*%
> cov.mat.inv
> > %*% one.vec)
> > w.gmin <- rowSums(cov.mat.inv) / sum(cov.mat.inv)
> > w.gmin <- as.vector(w.gmin)
> > names(w.gmin) <- asset.names
> > er.gmin <- crossprod(w.gmin,er)
> > sd.gmin <- sqrt(t(w.gmin) %*% cov.mat %*% w.gmin)
> > gmin.port <- list("call" = call,
> > "er" = as.vector(er.gmin),
> > "sd" = as.vector(sd.gmin),
> > "weights" = w.gmin)
> > class(gmin.port) <- "portfolio"
> > gmin.port
> > }
> >
>
> > [[alternative HTML version deleted]]
> >
> > _______________________________________________
> > R-SIG-Finance at 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.
>
> --
> Brian G. Peterson
> http://braverock.com/brian/
> Ph: 773-459-4973
> IM: bgpbraverock
>
>
>
--
Brian G. Peterson
http://braverock.com/brian/
Ph: 773-459-4973
IM: bgpbraverock
More information about the R-SIG-Finance
mailing list