{"id":209,"date":"2012-06-10T14:36:39","date_gmt":"2012-06-10T14:36:39","guid":{"rendered":"https:\/\/www.wdiam.com\/?p=209"},"modified":"2020-08-06T20:22:40","modified_gmt":"2020-08-06T20:22:40","slug":"mean-variance-portfolio-optimization-with-r-and-quadratic-programming","status":"publish","type":"post","link":"https:\/\/www.wdiam.com\/b\/2012\/06\/10\/mean-variance-portfolio-optimization-with-r-and-quadratic-programming\/","title":{"rendered":"Mean-Variance Portfolio Optimization with R and Quadratic Programming"},"content":{"rendered":"<p>The following is a demonstration of how to use R to do quadratic programming in order to do mean-variance portfolio optimization under different constraints, e.g., no leverage, no shorting, max concentration, etc.<\/p>\n<p>Taking a step back, it&#8217;s probably helpful to realize the point of all of this. In the 1950s, Harry Markowitz introduced what we now call <a href=\"http:\/\/en.wikipedia.org\/wiki\/Modern_portfolio_theory\">Modern Portfolio Theory<\/a> (MPT), which is a mathematical formulation for diversification. Intuitively, because some stocks zig when others zag, when we hold a portfolio of these stocks, our portfolio can have some notional return at a lower variance than holding the stocks outright. More specifically, given a basket of stocks, there exists a notion of an <a href=\"http:\/\/en.wikipedia.org\/wiki\/Efficient_frontier\">efficient frontier<\/a>. I.e., for any return you choose, there exists a portfolio with the lowest variance and for any variance you fix, there exists a portfolio with the greatest return. Any portfolio you choose that is not on this efficient frontier is considered sub-optimal (for a given return, why would you choose a a higher variance portfolio when a lower one exists).<\/p>\n<p>The question becomes if given a selection of stocks to choose from, how much do we invest in each stock if at all?<\/p>\n<p>In an investments course I took a while back, we worked the solution for the case where we had a basket of three stocks to choose from, in Excel. Obviously, this solution wasn&#8217;t really scalable outside of the N=3 case. When asked about extending N to an arbitrary number, the behind-schedule-professor did some handwaving about matrix math. Looking into this later, there does exist a closed-form equation for determining the holdings for an arbitrary basket of stocks. However, the math starts getting more complicated with each constraint you decide to tack on (e.g., no leverage).<\/p>\n<p>The happy medium between &#8220;portfolio optimizer in Excel for three stocks&#8221; and &#8220;hardcore matrix math for an arbitrary number of stocks&#8221; is to use a quadratic programming solver. Some context is needed to see why this is the case.<\/p>\n<p><strong>Quadratic Programming<\/strong><br \/>\nAccording to wikipedia, <a href=\"http:\/\/en.wikipedia.org\/wiki\/Quadratic_programming\">quadratic programming<\/a> attempts to minimize a function of the form <span class=\"katex-eq\" data-katex-display=\"false\">\\frac{1}{2}x^{T}Qx + c^{T}x<\/span> subject to one or more constraints of the form <span class=\"katex-eq\" data-katex-display=\"false\">Ax \\le b<\/span> (inequality) or <span class=\"katex-eq\" data-katex-display=\"false\">Ex = d<\/span> (equality).<\/p>\n<p><strong>Modern Portfolio Theory<\/strong><br \/>\nThe <a href=\"http:\/\/en.wikipedia.org\/wiki\/Modern_portfolio_theory#The_efficient_frontier_with_no_risk-free_asset\">mathematical formulation<\/a> of MPT is that for a given risk tolerance <span class=\"katex-eq\" data-katex-display=\"false\">q \\in [0,\\infty)<\/span>, we can find the efficient frontier by minimizing <span class=\"katex-eq\" data-katex-display=\"false\">w^{T} \\Sigma w - q*R^{T}w<\/span>.<\/p>\n<p>Where,<\/p>\n<ul>\n<li><span class=\"katex-eq\" data-katex-display=\"false\">w<\/span> is a vector of holding weights such that <span class=\"katex-eq\" data-katex-display=\"false\">\\sum w_i = 1<\/span><\/li>\n<li><span class=\"katex-eq\" data-katex-display=\"false\">\\Sigma<\/span> is the covariance matrix of the returns of the assets<\/li>\n<li><span class=\"katex-eq\" data-katex-display=\"false\">q \\ge 0<\/span> is the &#8220;risk tolerance&#8221;: <span class=\"katex-eq\" data-katex-display=\"false\">q = 0<\/span> works to minimize portfolio variance and <span class=\"katex-eq\" data-katex-display=\"false\">q = \\infty<\/span> works to maximize portfolio return<\/li>\n<li><span class=\"katex-eq\" data-katex-display=\"false\">R<\/span> is the vector of expected returns<\/li>\n<li><span class=\"katex-eq\" data-katex-display=\"false\">w^{T} \\Sigma w<\/span> is the variance of portfolio returns<\/li>\n<li><span class=\"katex-eq\" data-katex-display=\"false\">R^{T} w<\/span> is the expected return on the portfolio<\/li>\n<\/ul>\n<p>My introducing of quadratic programming before mean-variance optimization was clearly setup, but look at the equivalence between <span class=\"katex-eq\" data-katex-display=\"false\">\\frac{1}{2}x^{T}Qx + c^{T}x<\/span> and <span class=\"katex-eq\" data-katex-display=\"false\">w^{T} \\Sigma w - q*R^{T}w<\/span>.<\/p>\n<p><strong>Quadratic Programming in R<\/strong><br \/>\n<a href=\"http:\/\/cran.r-project.org\/web\/packages\/quadprog\/quadprog.pdf\">solve.QP<\/a>, from <a href=\"http:\/\/cran.r-project.org\/web\/packages\/quadprog\/\">quadprog<\/a>, is a good choice for a quadratic programming solver. From the documentation, it minimizes quadratic programming problems of the form <span class=\"katex-eq\" data-katex-display=\"false\">-d^{T}b + \\frac{1}{2} b^{T}Db<\/span> with the constraints <span class=\"katex-eq\" data-katex-display=\"false\">A^{T}b \\ge b_0<\/span>. Pedantically, note the variable mapping of <span class=\"katex-eq\" data-katex-display=\"false\">D = 2\\Sigma<\/span> (this is to offset the <span class=\"katex-eq\" data-katex-display=\"false\">\\frac{1}{2}<\/span> in the implied quadratic programming setup) and <span class=\"katex-eq\" data-katex-display=\"false\">d = R<\/span>.<\/p>\n<p>The fun begins when we have to modify <span class=\"katex-eq\" data-katex-display=\"false\">A^{T}b \\ge b_0<\/span> to impose the constraints we&#8217;re interested in.<\/p>\n<p><strong>Loading Up the Data<\/strong><br \/>\nI went to google finance and downloaded historical data for all of the sector SPDRs, e.g., XLY, XLP, XLE, XLF. I&#8217;ve named the files in the format of <code>dat.{SYMBOL}.csv<\/code>. The R code loads it up, formats it, and then ultimately creates a data frame where each column is the symbol and each row represents an observation (close to close log return).<\/p>\n<p>The data is straight-forward enough, with approximately 13 years worth:<\/p>\n<pre>&gt; dim(dat.ret)\n[1] 3399    9\n&gt; head(dat.ret, 3)\n              XLB         XLE          XLF         XLI          XLK\n[1,]  0.010506305  0.02041755  0.014903406 0.017458395  0.023436164\n[2,]  0.022546751 -0.00548872  0.006319802 0.013000812 -0.003664126\n[3,] -0.008864066 -0.00509339 -0.013105239 0.004987542  0.002749353\n              XLP          XLU          XLV          XLY\n[1,]  0.023863921 -0.004367553  0.022126545  0.004309507\n[2,] -0.001843998  0.018349139  0.006232977  0.018206972\n[3,] -0.005552485 -0.005303294 -0.014473165 -0.009255754\n&gt; \n<\/pre>\n<p><strong>Mean-Variance Optimization with Sum of Weights Equal to One<\/strong><br \/>\nIf it wasn&#8217;t clear before, we typically fix the <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span> in <span class=\"katex-eq\" data-katex-display=\"false\"> w^{T} \\Sigma w - q*R^{T}w<\/span> before optimization. By permuting the value of <span class=\"katex-eq\" data-katex-display=\"false\">q<\/span>, we then generate the efficient frontier. As such, for these examples, we&#8217;ll set <span class=\"katex-eq\" data-katex-display=\"false\">q = 0.5<\/span>.<\/p>\n<p>solve.QP&#8217;s arguments are:<\/p>\n<pre>solve.QP(Dmat, dvec, Amat, bvec, meq=0, factorized=FALSE)<\/pre>\n<p><code>Dmat<\/code> (covariance) and <code>dvec<\/code> (penalized returns) are generated easily enough:<\/p>\n<pre>risk.param<\/pre>\n<p><code>Amat and bvec<\/code> are part of the inequality (or equality) you can impose, i.e., <span class=\"katex-eq\" data-katex-display=\"false\">A^{T}b \\ge b_0<\/span>. <code>meq<\/code> is an integer argument that specifies &#8220;how many of the first meq constraints are equality statements instead of inequality statements.&#8221; The default for <code>meq<\/code> is zero.<\/p>\n<p>By construction, you need to think of the constraints in terms of matrix math. E.g., to have all the weights sum up to one, <code>Amat<\/code> needs to contain a column of ones and <code>bvec<\/code> needs to contain a single value of one. Additionally, since it&#8217;s an equality contraint, <code>meq<\/code> needs to be one.<\/p>\n<p>In R code:<\/p>\n<pre># Constraints: sum(x_i) = 1\nAmat<\/pre>\n<p>Having instantiated all the arguments for <code>solve.QP<\/code>, it&#8217;s relatively straightforward to invoke it. Multiple things are outputted, e.g., constrained solution, unconstrained solution, number of iterations to solve, etc. For our purpose, we&#8217;re primarily just interested in the solution.<\/p>\n<pre>&gt; qp  qp$solution\n[1] -0.1489193  0.6463653 -1.0117976  0.4107733 -0.4897956  0.2612327 -0.1094819\n[8]  0.5496478  0.8919753\n<\/pre>\n<p>Things to note in the solution are that we have negative values (shorting is allowed) and there exists at least one weight whose absolute value is greater than one (leverage is allowed).<\/p>\n<p><strong>Mean-Variance Optimization with Sum of Weights Equal to One and No Shorting<\/strong><br \/>\nWe need to modify <code>Amat<\/code> and <code>bvec<\/code> to add the constraint of no shorting. In writing, we want to add a diagonal matrix of ones to <code>Amat<\/code> and a vector of zeros to <code>bvec<\/code>, which works out when doing the matrix multiplication that for each weight, its value must be greater than zero.<\/p>\n<pre># Constraints: sum(x_i) = 1 &amp; x_i &gt;= 0\nAmat  qp$solution\n[1] 0.0000000 0.4100454 0.0000000 0.0000000 0.0000000 0.3075880 0.0000000\n[8] 0.2823666 0.0000000\n<\/pre>\n<p>Note that with the constraints that all the weights sum up to one and that the weights are positive, we&#8217;ve implicitly also constrained the solution to have no leverage.<\/p>\n<p><strong>Mean-Variance Optimization with Sum of Weights Equal to One, No Shorting, and No Heavy Concentration<\/strong><br \/>\nLooking at the previous solution, note that one of the weights suggests that we put 41% of our portfolio into a single asset. We may not be comfortable with such a heavy allocation, and we might want to impose the additional constraint that no single asset in our portfolio takes up more than 15%. In math and with our existing constraints, that&#8217;s the same as saying <span class=\"katex-eq\" data-katex-display=\"false\">-x \\ge -0.15<\/span> which is equivalent to saying <span class=\"katex-eq\" data-katex-display=\"false\">x \\le 0.15<\/span>.<\/p>\n<pre># Constraints: sum(x_i) = 1 &amp; x_i &gt;= 0 &amp; x_i &lt;= 0.15\nAmat  qp$solution\n[1] 0.1092174 0.1500000 0.0000000 0.1407826 0.0000000 0.1500000 0.1500000\n[8] 0.1500000 0.1500000\n<\/pre>\n<p><strong>Turning the Weights into Expected Portfolio Return and Expected Portfolio Volatility<\/strong><br \/>\nWith our weights, we can now calculate the portfolio return as <span class=\"katex-eq\" data-katex-display=\"false\">R^{T}w<\/span> and portfolio volatility as <span class=\"katex-eq\" data-katex-display=\"false\">sqrt{w^T \\Sigma w}<\/span>. Doing this, we might note that the values look &#8220;small&#8221; and not what you expected. Keep in mind that our observations are in daily-space and thus our expected return is expected daily return and expected volatility is expected daily volatility. You will need to annualize it, i.e., <span class=\"katex-eq\" data-katex-display=\"false\">R^{T}w * 252<\/span> and <span class=\"katex-eq\" data-katex-display=\"false\">\\sqrt{w^{T} \\Sigma w * 252}<\/span>.<\/p>\n<p>The following is an example of the values of the weights and portfolio statistics while permuting the risk parameter and solving the quadratic programming problem with the constraints that the weights sum to one and there&#8217;s no shorting.<\/p>\n<pre>&gt; head(ef.w)\n      XLB       XLE XLF XLI XLK XLP XLU       XLV        XLY\n1       0 0.7943524   0   0   0   0   0 0.1244543 0.08119329\n1.005   0 0.7977194   0   0   0   0   0 0.1210635 0.08121713\n1.01    0 0.8010863   0   0   0   0   0 0.1176727 0.08124097\n1.015   0 0.8044533   0   0   0   0   0 0.1142819 0.08126480\n1.02    0 0.8078203   0   0   0   0   0 0.1108911 0.08128864\n1.025   0 0.8111873   0   0   0   0   0 0.1075003 0.08131248\n&gt; head(ef.stat)\n             ret        sd\n1     0.06663665 0.2617945\n1.005 0.06679809 0.2624120\n1.01  0.06695954 0.2630311\n1.015 0.06712098 0.2636519\n1.02  0.06728243 0.2642742\n1.025 0.06744387 0.2648981\n&gt; \n<\/pre>\n<p>Note that as we increase the risk parameter, we&#8217;re working to maximize return at the expense of risk. While obvious, it&#8217;s worth stating that we&#8217;re looking at the efficient frontier. If you plotted <code>ef.stat<\/code> in its entirety on a plot whose axis are in return space and risk space, you will get the efficient frontier.<\/p>\n<p><strong>Wrap Up<\/strong><br \/>\nI&#8217;ve demonstrated how to use R and the quadprog package to do quadratic programming. It also happens to coincide that the mean-variance portfolio optimization problem really lends itself to quadratic programming. It&#8217;s relatively straightforward to do variable mapping between the two problems. The only potential gotcha is how to state your desired constraints into the form <span class=\"katex-eq\" data-katex-display=\"false\">A^{T}b \\ge b_{0}<\/span>, but several examples of constraints were given, for which you can hopefully extrapolate from.<\/p>\n<p>Getting away from the mechanics and talking about the theory, I&#8217;ll also offer that there are some serious flaws with the approach demonstrated if you attempt to implement this for your own trading. Specifically, you will most likely want to create return forecasts and risk forecasts instead of using historical values only. You might also want to impose constraints to induce sparsity on what you actually hold, in order to minimize transaction costs. In saying that your portfolio is mean-variance optimal, there&#8217;s the assumption that the returns you&#8217;re working with is normal, which is definitely not the case. These and additional considerations will need to be handled before you let this run in &#8220;production.&#8221;<\/p>\n<p>All that being said, however, Markowitz&#8217;s mean-variance optimization is the <strong>building block<\/strong> for whatever more robust solution you might end up coming with. And, an understanding in both theory and implementation of a mean-variance optimization is needed before you can progress.<\/p>\n<p><strong>Helpful Links<\/strong><br \/>\n<a href=\"https:\/\/www.wdiam.com\/b\/wp-content\/uploads\/2012\/06\/quadratic_programming_markowitz_rvdb.pdf\">Lecture on Quadratic Programming and Markowitz Model (R. Vanderbei)<\/a><br \/>\n<a href=\"https:\/\/www.wdiam.com\/b\/wp-content\/uploads\/2012\/06\/linear_programming_markowitz_rvdb.pdf\">Lecture on Linear Programming and a Modified Markowitz Model (R. Vanderbei)<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The following is a demonstration of how to use R to do quadratic programming in order to do mean-variance portfolio optimization under different constraints, e.g., no leverage, no shorting, max concentration, etc. Taking a step back, it&#8217;s probably helpful to realize the point of all of this. In the 1950s, Harry Markowitz introduced what we &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.wdiam.com\/b\/2012\/06\/10\/mean-variance-portfolio-optimization-with-r-and-quadratic-programming\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Mean-Variance Portfolio Optimization with R and Quadratic Programming&#8221;<\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,6],"tags":[26,27,30,32,33,34,35],"class_list":["post-209","post","type-post","status-publish","format-standard","hentry","category-investing","category-statistics","tag-markowitz","tag-mean-variance","tag-optimization","tag-portfolio","tag-quadprog","tag-quadratic-programming","tag-r"],"_links":{"self":[{"href":"https:\/\/www.wdiam.com\/b\/wp-json\/wp\/v2\/posts\/209","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wdiam.com\/b\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wdiam.com\/b\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wdiam.com\/b\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wdiam.com\/b\/wp-json\/wp\/v2\/comments?post=209"}],"version-history":[{"count":2,"href":"https:\/\/www.wdiam.com\/b\/wp-json\/wp\/v2\/posts\/209\/revisions"}],"predecessor-version":[{"id":598,"href":"https:\/\/www.wdiam.com\/b\/wp-json\/wp\/v2\/posts\/209\/revisions\/598"}],"wp:attachment":[{"href":"https:\/\/www.wdiam.com\/b\/wp-json\/wp\/v2\/media?parent=209"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wdiam.com\/b\/wp-json\/wp\/v2\/categories?post=209"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wdiam.com\/b\/wp-json\/wp\/v2\/tags?post=209"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}