[R-SIG-Finance] minimum variance portfolio (no shorts)
Brian G. Peterson
brian at braverock.com
Sun Feb 19 01:42:15 CET 2012
the largest problem I still see here is that you want to minimize 'sd',
not 'var'
I suspect that will do what you want it to do, and the 'weights-aware'
version is already inside the package for this, so you shouldn't need to
do anything else.
It would be much easier for people to help you if you used publicly
available data to construct a fully reproducible example...
On Sat, 2012-02-18 at 19:32 -0500, benn fine wrote:
> The thinking was to see how optimize.portfolio works by having it give
> me (approximately) the same weights I get from the closed form
> solution. Then I would be satisfied it would work for long only. When
> I say short, I simply mean that the weights can be negative or
> positive.
>
>
> So yes, using the sample mean and sample covariance matrix, I get
> asset weights of -0.5894, 0.3976, and 1.1918 based on the closed
> form solution.
>
>
> I still can't get optimize.portfolio to work, even when using random
> portfolios.
>
>
> Is my thinking correct that I need to write a "portfolio aware"
> variance function as mentioned in your slides for your CVaR example?
> That is, I am doing the following by just putting "var" in for the
> objective function, but is that enough or do I need to write my own
> function that takes portfolio weights and covariance matrix and
> returns the variance?
>
>
> > aConstraintObj = add.objective(constraints =
> > myconstr,
> > type="risk",
> > name="var",
> > enabled=TRUE)
>
> The following just does not work:
>
>
> myconstr=constraint(assets=3, min_sum=.99, max_sum=1.01, min= -2,
> max=2,weight_seq=generatesequence())
>
>
> aConstraintObj = add.objective(constraints =
> myconstr,
> type="risk",
> name="var",
> enabled=TRUE)
>
>
>
>
> optimize.portfolio(myrets,aConstraintObj,optimize_method="random")
>
>
>
>
>
>
> On Sat, Feb 18, 2012 at 7:15 PM, Brian G. Peterson
> <brian at braverock.com> wrote:
> 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
>
>
>
>
--
Brian G. Peterson
http://braverock.com/brian/
Ph: 773-459-4973
IM: bgpbraverock
More information about the R-SIG-Finance
mailing list