From noreply at r-forge.r-project.org Thu Apr 3 20:33:08 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 3 Apr 2014 20:33:08 +0200 (CEST) Subject: [Returnanalytics-commits] r3346 - in pkg/PortfolioAnalytics/sandbox: . RFinance2014 RFinance2014/data Message-ID: <20140403183308.9876A187006@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-03 20:33:08 +0200 (Thu, 03 Apr 2014) New Revision: 3346 Added: pkg/PortfolioAnalytics/sandbox/RFinance2014/ pkg/PortfolioAnalytics/sandbox/RFinance2014/data/ pkg/PortfolioAnalytics/sandbox/RFinance2014/data/edhec.csv pkg/PortfolioAnalytics/sandbox/RFinance2014/data/edhec.rda pkg/PortfolioAnalytics/sandbox/RFinance2014/data/parse_edhec.R pkg/PortfolioAnalytics/sandbox/RFinance2014/edhec.rda pkg/PortfolioAnalytics/sandbox/RFinance2014/edhec_eda.R pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.html pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.md pkg/PortfolioAnalytics/sandbox/RFinance2014/slides.pdf Log: Initial commit of framework for RFinance 2014 PortfolioAnalytics Presentation Added: pkg/PortfolioAnalytics/sandbox/RFinance2014/data/edhec.csv =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/data/edhec.csv (rev 0) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/data/edhec.csv 2014-04-03 18:33:08 UTC (rev 3346) @@ -0,0 +1,206 @@ +date;Convertible Arbitrage;CTA Global;Distressed Securities;Emerging Markets;Equity Market Neutral;Event Driven;Fixed Income Arbitrage;Global Macro;Long/Short Equity;Merger Arbitrage;Relative Value;Short Selling;Funds Of Funds +31/01/1997;1.19%;3.93%;1.78%;7.91%;1.89%;2.13%;1.91%;5.73%;2.81%;1.50%;1.80%;-1.66%;3.17% +28/02/1997;1.23%;2.98%;1.22%;5.25%;1.01%;0.84%;1.22%;1.75%;-0.06%;0.34%;1.18%;4.26%;1.06% +31/03/1997;0.78%;-0.21%;-0.12%;-1.20%;0.16%;-0.23%;1.09%;-1.19%;-0.84%;0.60%;0.10%;7.78%;-0.77% +30/04/1997;0.86%;-1.70%;0.30%;1.19%;1.19%;-0.05%;1.30%;1.72%;0.84%;-0.01%;1.22%;-1.29%;0.09% +31/05/1997;1.56%;-0.15%;2.33%;3.15%;1.89%;3.46%;1.18%;1.08%;3.94%;1.97%;1.73%;-7.37%;2.75% +30/06/1997;2.12%;0.85%;2.17%;5.81%;1.65%;2.58%;1.08%;2.18%;2.23%;2.31%;1.98%;-0.65%;2.25% +31/07/1997;1.93%;5.91%;2.34%;5.60%;2.47%;3.07%;0.95%;7.38%;4.54%;2.00%;1.81%;-4.29%;4.35% +31/08/1997;1.34%;-4.73%;1.47%;-0.66%;0.17%;0.71%;0.87%;-1.80%;1.07%;0.79%;1.03%;-0.72%;0.51% +30/09/1997;1.22%;1.98%;3.50%;2.29%;2.02%;3.29%;1.19%;2.90%;4.29%;1.97%;1.83%;-1.55%;3.34% +31/10/1997;1.00%;-0.98%;-0.64%;-5.72%;0.95%;0.61%;-0.32%;-1.42%;0.10%;0.94%;0.79%;5.72%;-0.99% +30/11/1997;0.00%;1.33%;0.54%;-3.78%;0.41%;1.34%;0.53%;1.06%;-0.26%;2.23%;1.11%;2.17%;-0.34% +31/12/1997;0.68%;2.86%;0.73%;1.60%;0.66%;1.54%;0.79%;2.64%;1.04%;1.58%;0.82%;1.61%;0.89% +31/01/1998;1.45%;1.04%;0.95%;-4.29%;0.60%;0.55%;-0.26%;-0.50%;0.13%;0.55%;1.32%;0.14%;-0.36% +28/02/1998;1.46%;-0.65%;2.27%;3.39%;1.35%;2.94%;0.98%;1.28%;3.42%;2.12%;1.30%;1.55%;2.56% +31/03/1998;1.44%;1.22%;2.52%;3.18%;1.79%;2.63%;1.28%;5.70%;3.36%;1.64%;1.45%;6.37%;3.73% +30/04/1998;1.26%;-2.96%;1.65%;0.41%;0.67%;1.04%;0.75%;0.34%;1.20%;1.39%;1.45%;6.57%;1.25% +31/05/1998;0.56%;1.93%;0.06%;-8.25%;0.80%;-0.83%;0.40%;0.95%;-0.87%;-0.09%;0.53%;14.37%;-0.72% +30/06/1998;-0.06%;0.51%;-0.47%;-4.22%;1.08%;0.02%;-0.80%;1.20%;1.67%;0.72%;0.26%;-0.53%;0.21% +31/07/1998;0.60%;-0.10%;-0.69%;0.19%;0.12%;-0.37%;1.06%;0.58%;-0.06%;0.07%;0.11%;3.43%;-0.07% +31/08/1998;-3.19%;6.91%;-8.36%;-19.22%;-1.07%;-8.86%;-1.43%;-2.63%;-5.52%;-5.44%;-3.41%;24.63%;-6.16% +30/09/1998;-1.96%;4.54%;-2.15%;-3.95%;0.61%;-1.10%;-3.62%;-0.59%;2.06%;0.76%;0.05%;-3.76%;-0.37% +31/10/1998;-2.14%;0.04%;-0.29%;1.40%;0.52%;0.91%;-8.01%;-2.23%;1.69%;1.59%;-1.40%;-10.77%;-0.02% +30/11/1998;2.69%;-0.89%;1.64%;4.30%;1.58%;2.44%;0.52%;1.94%;2.91%;2.20%;1.98%;-7.56%;2.20% +31/12/1998;1.13%;2.21%;1.08%;-0.98%;2.09%;2.19%;1.20%;2.33%;4.08%;2.24%;1.64%;-5.31%;2.22% +31/01/1999;2.19%;-1.67%;1.81%;-1.20%;1.01%;2.01%;1.58%;0.86%;2.58%;1.12%;1.95%;-6.65%;2.02% +28/02/1999;0.82%;1.97%;-0.21%;1.02%;0.23%;-0.42%;2.08%;-1.11%;-1.69%;0.36%;0.85%;8.33%;-0.63% +31/03/1999;1.36%;-0.65%;1.59%;5.85%;0.33%;1.93%;1.60%;0.24%;2.29%;1.33%;1.16%;-1.54%;2.13% +30/04/1999;2.43%;2.10%;4.18%;6.30%;1.07%;4.29%;1.06%;3.29%;3.12%;2.18%;2.38%;-3.75%;4.00% +31/05/1999;1.66%;-1.50%;2.07%;0.61%;0.89%;2.15%;0.72%;-0.55%;0.95%;2.10%;1.46%;0.09%;1.19% +30/06/1999;1.02%;2.34%;2.73%;6.54%;1.68%;2.97%;0.88%;2.14%;3.15%;2.22%;1.48%;-4.12%;2.82% +31/07/1999;1.01%;-0.51%;0.84%;-0.61%;1.35%;0.96%;0.51%;-0.18%;1.77%;1.47%;1.10%;0.92%;0.88% +31/08/1999;0.48%;-0.27%;0.20%;-1.47%;0.95%;-0.27%;-0.28%;-0.61%;0.22%;0.50%;0.62%;4.68%;0.28% +30/09/1999;0.96%;0.64%;-0.41%;-0.69%;0.95%;0.90%;0.92%;-0.02%;1.13%;1.16%;1.05%;4.01%;0.52% +31/10/1999;0.45%;-3.54%;0.27%;2.88%;0.66%;0.54%;0.87%;0.73%;2.12%;0.96%;0.70%;-1.30%;1.30% +30/11/1999;1.24%;1.66%;2.20%;6.92%;1.33%;2.84%;1.06%;4.05%;4.81%;2.37%;1.37%;-12.39%;4.83% +31/12/1999;1.40%;1.42%;3.00%;12.30%;1.98%;2.86%;0.97%;6.12%;7.45%;0.90%;1.83%;-11.37%;6.22% +31/01/2000;2.27%;1.28%;0.88%;0.77%;0.75%;0.88%;0.41%;0.21%;0.75%;1.43%;1.73%;4.27%;1.69% +29/02/2000;2.67%;-0.22%;4.21%;5.28%;2.53%;3.46%;0.97%;4.08%;6.99%;2.39%;1.85%;-13.40%;6.66% +31/03/2000;2.43%;-1.38%;1.03%;3.18%;1.34%;0.69%;-0.61%;-1.04%;0.06%;1.31%;1.63%;-2.30%;0.39% +30/04/2000;2.23%;-2.41%;-1.01%;-5.41%;1.68%;-0.59%;-0.06%;-3.04%;-2.01%;1.88%;0.92%;10.28%;-2.69% +31/05/2000;1.49%;1.14%;-1.32%;-4.33%;0.62%;-0.34%;1.07%;-0.70%;-0.97%;1.46%;0.80%;7.04%;-1.22% +30/06/2000;1.79%;-1.24%;2.03%;3.34%;1.71%;2.68%;0.58%;1.54%;3.49%;1.67%;1.76%;-11.07%;3.11% +31/07/2000;0.93%;-1.31%;0.64%;0.25%;0.63%;0.57%;0.18%;0.37%;0.06%;1.16%;0.84%;5.53%;-0.22% +31/08/2000;1.62%;1.89%;1.40%;3.68%;2.10%;1.73%;1.07%;2.48%;3.45%;1.57%;1.57%;-11.35%;2.67% +30/09/2000;1.41%;-2.08%;-0.19%;-4.62%;0.58%;0.48%;0.76%;-1.49%;-0.16%;1.37%;0.75%;12.04%;-0.69% +31/10/2000;0.52%;0.75%;-0.73%;-2.56%;0.40%;-0.68%;0.06%;-0.24%;-0.84%;0.26%;-0.04%;7.84%;-1.04% +30/11/2000;-0.81%;4.25%;-2.09%;-3.85%;0.45%;-1.36%;0.66%;1.25%;-1.53%;1.02%;0.06%;16.57%;-2.05% +31/12/2000;-0.02%;6.82%;0.01%;1.16%;1.60%;1.27%;0.48%;4.72%;2.48%;1.25%;0.75%;0.63%;1.33% +31/01/2001;3.44%;0.25%;3.08%;5.86%;0.75%;2.98%;1.63%;2.14%;1.65%;1.11%;3.33%;-2.71%;2.23% +28/02/2001;1.82%;-0.16%;1.00%;-2.21%;1.20%;0.45%;0.54%;-0.72%;-2.64%;0.54%;0.30%;10.21%;-0.89% +31/03/2001;1.62%;4.38%;-0.37%;-1.75%;1.08%;-0.42%;0.51%;0.38%;-1.99%;-0.61%;-0.11%;6.20%;-0.68% +30/04/2001;1.57%;-3.62%;0.48%;1.14%;0.75%;1.10%;0.94%;0.49%;2.46%;0.58%;1.74%;-9.91%;1.04% +31/05/2001;0.33%;0.81%;2.35%;2.78%;0.77%;1.85%;0.68%;0.32%;0.43%;1.61%;1.41%;-1.30%;0.80% +30/06/2001;0.12%;-0.77%;3.60%;1.60%;0.17%;0.63%;0.17%;0.17%;0.19%;-0.87%;0.19%;1.10%;0.13% +31/07/2001;0.91%;-0.40%;0.73%;-2.86%;0.31%;0.49%;0.54%;-0.40%;-1.44%;0.79%;0.10%;3.53%;-0.40% +31/08/2001;1.42%;1.53%;1.06%;0.30%;0.94%;0.90%;1.05%;0.06%;-0.96%;0.99%;-0.31%;7.52%;0.19% +30/09/2001;0.78%;2.46%;-0.14%;-4.25%;0.23%;-2.54%;-0.13%;-0.70%;-3.48%;-2.67%;-2.21%;9.41%;-1.42% +31/10/2001;1.17%;3.36%;1.03%;2.78%;0.58%;1.48%;1.34%;2.08%;0.99%;0.85%;1.64%;-2.98%;0.95% +30/11/2001;0.80%;-5.43%;0.86%;4.83%;0.55%;1.05%;-0.24%;0.21%;2.00%;0.14%;1.36%;-6.55%;0.58% +31/12/2001;-0.94%;1.48%;0.15%;4.21%;0.56%;1.07%;0.53%;1.38%;1.80%;0.45%;0.97%;-2.51%;0.99% +31/01/2002;1.48%;-0.72%;1.86%;2.73%;0.65%;0.78%;0.86%;0.69%;-0.37%;0.77%;0.97%;3.43%;0.30% +28/02/2002;-0.49%;-2.02%;-0.33%;1.81%;-0.07%;-0.71%;0.56%;-0.35%;-1.23%;-0.44%;-0.11%;3.90%;-0.15% +31/03/2002;0.53%;0.09%;0.52%;3.31%;0.47%;1.53%;0.45%;0.64%;1.55%;0.73%;1.45%;-4.46%;0.90% +30/04/2002;0.96%;-1.04%;1.39%;1.44%;0.76%;0.46%;1.13%;0.98%;-0.42%;-0.13%;0.70%;4.83%;0.52% +31/05/2002;0.33%;2.70%;0.91%;0.01%;0.53%;0.01%;0.99%;1.23%;-0.34%;0.00%;0.31%;3.46%;0.50% +30/06/2002;0.04%;6.55%;-1.17%;-2.92%;0.22%;-2.83%;0.69%;-0.22%;-2.49%;-1.70%;-1.07%;5.48%;-0.95% +31/07/2002;-1.59%;4.13%;-1.33%;-3.09%;-0.13%;-3.00%;0.57%;-0.78%;-3.89%;-1.74%;-1.85%;6.44%;-1.40% +31/08/2002;0.50%;2.20%;0.09%;1.19%;0.69%;0.60%;0.97%;0.63%;0.41%;0.61%;0.58%;0.15%;0.37% +30/09/2002;1.46%;2.84%;-0.44%;-2.52%;0.15%;-0.70%;-0.33%;0.54%;-1.60%;-0.28%;-1.10%;7.31%;-0.33% +31/10/2002;1.04%;-3.76%;-0.31%;1.54%;0.16%;0.31%;-0.63%;-0.86%;1.23%;0.32%;0.84%;-4.05%;-0.31% +30/11/2002;2.51%;-1.64%;2.39%;1.90%;0.25%;2.16%;0.54%;0.47%;2.24%;0.54%;1.85%;-5.47%;1.06% +31/12/2002;1.57%;4.89%;2.22%;0.48%;0.94%;0.44%;1.53%;1.92%;-1.49%;0.46%;0.23%;4.43%;0.77% +31/01/2003;2.83%;4.41%;2.43%;0.12%;0.83%;1.54%;1.06%;1.82%;0.05%;0.40%;0.67%;1.62%;0.72% +28/02/2003;1.33%;4.02%;0.92%;0.84%;0.24%;0.26%;0.79%;1.66%;-0.37%;0.18%;-0.04%;1.30%;0.31% +31/03/2003;0.89%;-4.45%;1.13%;0.19%;0.15%;0.83%;0.19%;-1.22%;0.20%;-0.07%;0.49%;-0.75%;-0.04% +30/04/2003;1.50%;0.65%;3.45%;4.50%;0.31%;2.72%;0.91%;1.17%;2.98%;0.99%;1.86%;-6.56%;1.34% +31/05/2003;1.36%;4.90%;2.70%;4.33%;1.07%;3.01%;2.07%;3.97%;3.62%;1.54%;2.12%;-4.99%;2.05% +30/06/2003;-0.58%;-1.92%;2.67%;2.68%;0.34%;1.81%;0.44%;0.56%;1.28%;0.48%;0.71%;-1.62%;0.68% +31/07/2003;-0.72%;-1.71%;1.17%;1.04%;-0.06%;1.19%;-0.92%;-0.35%;1.18%;0.53%;0.41%;-3.61%;0.25% +31/08/2003;-0.87%;0.78%;1.37%;3.74%;0.31%;1.33%;0.43%;2.02%;1.79%;0.70%;0.58%;-3.54%;0.78% +30/09/2003;1.71%;-0.19%;2.42%;2.64%;0.78%;1.33%;1.05%;2.15%;0.94%;0.77%;0.86%;1.36%;1.21% +31/10/2003;1.46%;1.04%;2.67%;2.59%;1.15%;1.91%;0.35%;1.11%;2.99%;1.11%;1.59%;-6.56%;1.52% +30/11/2003;0.92%;0.18%;1.54%;0.96%;0.46%;1.16%;0.69%;0.31%;1.30%;0.44%;1.02%;-1.36%;0.70% +31/12/2003;0.54%;3.81%;1.98%;4.03%;0.54%;1.72%;1.01%;2.93%;1.91%;0.98%;1.27%;-1.78%;1.39% +31/01/2004;1.19%;1.99%;3.01%;2.51%;1.09%;2.34%;0.92%;1.17%;1.92%;0.97%;1.46%;-0.90%;1.56% +29/02/2004;0.17%;5.29%;0.75%;2.53%;0.63%;1.13%;0.84%;1.50%;1.23%;0.51%;0.57%;0.18%;1.11% +31/03/2004;0.61%;-0.51%;0.46%;1.72%;0.32%;0.16%;0.03%;0.64%;0.41%;0.17%;0.38%;-1.48%;0.43% +30/04/2004;0.20%;-5.32%;0.93%;-2.52%;-0.82%;0.02%;0.62%;-1.78%;-1.65%;-0.39%;-0.45%;3.84%;-0.68% +31/05/2004;-1.28%;-1.18%;-0.10%;-1.81%;0.24%;-0.23%;0.40%;-0.81%;-0.35%;0.00%;-0.37%;-0.24%;-0.82% +30/06/2004;-1.06%;-3.16%;2.02%;0.20%;0.42%;1.13%;0.55%;-0.19%;0.91%;0.17%;0.22%;-0.51%;0.34% +31/07/2004;0.13%;-1.19%;0.19%;-0.27%;0.06%;-0.82%;0.62%;-0.14%;-1.54%;-0.92%;0.07%;6.38%;-0.49% +31/08/2004;0.40%;-0.84%;0.88%;1.33%;-0.09%;0.35%;0.36%;-0.39%;-0.22%;0.11%;0.31%;1.26%;-0.10% +30/09/2004;-0.17%;2.20%;1.04%;2.80%;0.85%;1.03%;0.12%;0.08%;2.10%;0.42%;0.52%;-2.16%;0.99% +31/10/2004;-0.44%;3.58%;1.43%;1.85%;-0.05%;1.24%;0.28%;1.38%;0.74%;0.74%;0.40%;-0.92%;0.68% +30/11/2004;0.81%;4.75%;3.37%;3.28%;1.40%;3.06%;0.75%;2.80%;3.08%;1.64%;1.49%;-5.74%;2.44% +31/12/2004;0.56%;0.00%;2.66%;2.01%;0.58%;2.44%;0.60%;0.33%;1.78%;1.33%;0.99%;-3.91%;1.45% +31/01/2005;-0.96%;-4.38%;0.37%;1.43%;0.81%;0.04%;0.44%;-0.47%;-0.17%;0.00%;0.12%;3.87%;0.06% +28/02/2005;-0.58%;0.05%;1.34%;3.46%;0.80%;1.44%;0.85%;1.71%;2.10%;0.65%;0.81%;1.18%;1.36% +31/03/2005;-1.40%;-0.06%;0.32%;-1.97%;0.19%;-0.04%;0.24%;-0.27%;-0.96%;0.32%;-0.42%;2.44%;-0.44% +30/04/2005;-3.16%;-3.54%;-0.52%;-0.49%;-0.30%;-1.28%;-0.03%;-0.80%;-1.84%;-1.05%;-1.08%;3.93%;-1.41% +31/05/2005;-1.33%;2.32%;0.06%;0.72%;0.47%;0.65%;-0.10%;0.88%;1.15%;0.95%;-0.02%;-4.75%;0.18% +30/06/2005;1.07%;2.60%;1.33%;1.60%;0.81%;1.33%;0.10%;1.16%;1.95%;0.85%;0.95%;-0.32%;1.31% +31/07/2005;1.64%;-0.13%;1.73%;2.57%;0.78%;2.15%;0.81%;1.19%;2.65%;1.15%;1.49%;-2.42%;1.34% +31/08/2005;0.66%;1.00%;1.24%;1.52%;0.62%;0.92%;0.36%;0.83%;0.97%;0.61%;0.53%;2.59%;0.79% +30/09/2005;1.42%;0.79%;1.12%;4.02%;0.87%;1.00%;0.62%;2.69%;2.22%;0.35%;1.22%;1.98%;1.47% +31/10/2005;-0.15%;-0.92%;-0.32%;-2.30%;0.01%;-1.73%;0.57%;-0.74%;-1.74%;-1.45%;-0.38%;2.33%;-1.49% +30/11/2005;0.04%;3.79%;1.00%;2.79%;0.61%;1.25%;0.15%;1.64%;2.11%;1.12%;0.67%;-3.00%;1.60% +31/12/2005;0.92%;-1.53%;1.22%;2.84%;0.68%;1.42%;0.54%;1.35%;2.49%;1.38%;1.26%;-0.35%;1.91% +31/01/2006;2.50%;1.74%;2.53%;5.26%;1.15%;3.41%;0.93%;2.58%;3.81%;2.72%;2.38%;-2.88%;2.86% +28/02/2006;1.16%;-1.86%;0.65%;1.61%;0.46%;0.51%;0.41%;0.02%;0.16%;1.04%;0.73%;0.64%;0.37% +31/03/2006;1.07%;2.84%;1.72%;1.22%;0.98%;1.85%;0.55%;0.94%;2.38%;1.44%;1.57%;-1.39%;1.64% +30/04/2006;0.64%;3.87%;1.93%;3.65%;1.02%;1.64%;1.21%;2.38%;1.72%;1.19%;1.26%;-0.12%;1.71% +31/05/2006;0.91%;-1.46%;0.86%;-3.89%;0.02%;0.08%;0.59%;-1.55%;-2.48%;0.09%;-0.25%;2.46%;-1.33% +30/06/2006;0.12%;-1.42%;-0.15%;-0.97%;0.63%;0.12%;0.36%;-0.15%;-0.62%;0.87%;0.21%;1.18%;-0.28% +31/07/2006;0.66%;-2.16%;0.09%;0.67%;0.51%;-0.11%;0.64%;0.06%;-0.31%;0.58%;0.17%;1.73%;-0.05% +31/08/2006;0.98%;0.20%;0.99%;1.33%;-0.09%;1.12%;0.37%;-0.39%;1.14%;0.53%;0.92%;-1.56%;0.66% +30/09/2006;0.93%;-0.55%;0.33%;0.11%;0.09%;0.35%;0.14%;-0.67%;0.05%;0.41%;0.40%;-2.36%;-0.03% +31/10/2006;0.54%;1.02%;1.94%;2.57%;0.65%;2.06%;0.67%;0.97%;1.94%;1.32%;1.32%;-3.80%;1.63% +30/11/2006;0.92%;2.26%;1.79%;3.23%;0.75%;1.82%;0.60%;1.99%;2.00%;1.42%;1.29%;-2.68%;1.85% +31/12/2006;1.27%;1.46%;1.65%;2.91%;1.07%;1.68%;0.72%;1.16%;1.53%;1.33%;1.28%;0.39%;1.75% +31/01/2007;1.30%;1.13%;1.50%;0.79%;0.83%;2.01%;0.69%;0.61%;1.21%;1.91%;1.35%;-1.07%;1.21% +28/02/2007;1.17%;-1.44%;1.45%;1.00%;0.51%;2.07%;1.06%;0.18%;0.82%;2.55%;1.14%;0.28%;0.96% +31/03/2007;0.60%;-1.41%;1.08%;1.85%;1.01%;1.46%;0.60%;0.27%;1.15%;0.63%;0.81%;-0.51%;0.96% +30/04/2007;0.26%;2.41%;1.64%;2.55%;0.89%;1.97%;0.71%;1.52%;1.98%;1.60%;1.34%;-2.65%;1.63% +31/05/2007;1.10%;2.30%;1.80%;2.70%;1.21%;2.13%;0.55%;1.92%;2.24%;1.71%;1.56%;-1.99%;2.04% +30/06/2007;0.11%;2.29%;0.27%;2.36%;0.77%;-0.07%;0.48%;1.07%;0.77%;-0.53%;1.00%;2.36%;0.82% +31/07/2007;-0.53%;-1.22%;-0.56%;2.75%;0.51%;-0.32%;0.07%;1.16%;0.09%;-0.54%;0.04%;4.86%;0.41% +31/08/2007;-1.45%;-2.80%;-1.18%;-2.74%;-0.94%;-1.44%;-0.48%;-1.16%;-1.60%;0.01%;-0.77%;0.92%;-2.22% +30/09/2007;1.61%;4.69%;0.95%;4.28%;1.23%;1.34%;1.64%;3.30%;2.56%;1.31%;1.53%;-2.07%;1.99% +31/10/2007;1.77%;2.80%;1.75%;4.85%;1.68%;2.14%;1.14%;3.04%;2.81%;1.91%;2.00%;-0.26%;3.03% +30/11/2007;-1.31%;-0.16%;-1.69%;-2.37%;-0.18%;-2.02%;-0.94%;-0.63%;-2.25%;-1.49%;-1.12%;7.19%;-1.48% +31/12/2007;-0.77%;1.17%;0.02%;1.30%;0.54%;0.07%;0.36%;1.04%;0.43%;-0.25%;0.22%;0.56%;0.40% +31/01/2008;-0.09%;2.55%;-2.33%;-5.03%;-1.12%;-2.71%;-0.12%;-0.10%;-4.00%;-1.26%;-1.18%;5.56%;-2.72% +29/02/2008;-0.83%;6.20%;0.14%;2.80%;1.20%;0.84%;-0.49%;3.12%;1.40%;0.60%;0.64%;3.00%;1.42% +31/03/2008;-3.17%;-0.56%;-1.26%;-3.79%;-0.49%;-1.68%;-3.06%;-1.69%;-2.36%;-0.45%;-1.62%;1.92%;-2.62% +30/04/2008;0.76%;-0.78%;0.88%;1.90%;0.59%;1.18%;1.87%;0.78%;2.23%;1.49%;1.30%;-4.61%;0.97% +31/05/2008;1.07%;1.62%;1.37%;1.63%;1.26%;1.76%;1.03%;1.14%;2.27%;1.36%;1.59%;-1.42%;1.72% +30/06/2008;-0.81%;3.30%;-0.31%;-2.74%;1.56%;-1.13%;-0.27%;0.30%;-1.64%;-1.09%;-0.84%;7.51%;-0.68% +31/07/2008;-1.88%;-3.33%;-1.82%;-3.30%;-1.00%;-1.66%;-0.23%;-2.13%;-2.61%;0.11%;-1.25%;0.72%;-2.64% +31/08/2008;-0.66%;-1.14%;-0.72%;-3.36%;-1.35%;-0.25%;-0.03%;-1.33%;-1.46%;0.51%;-0.23%;-2.15%;-1.56% +30/09/2008;-10.27%;0.10%;-5.18%;-9.82%;-2.85%;-6.27%;-5.06%;-3.13%;-6.75%;-2.76%;-5.38%;3.78%;-6.18% +31/10/2008;-12.37%;3.45%;-7.75%;-13.31%;-0.44%;-6.25%;-8.67%;-1.57%;-6.29%;-2.45%;-6.92%;11.70%;-6.00% +30/11/2008;-2.76%;2.14%;-4.35%;-3.91%;-5.87%;-3.01%;-3.08%;0.33%;-1.88%;0.06%;-2.09%;4.28%;-1.92% +31/12/2008;1.77%;1.40%;-1.97%;-0.10%;0.05%;-0.71%;-0.35%;1.18%;0.81%;1.62%;0.31%;-1.46%;-1.19% +31/01/2009;4.91%;-0.16%;0.82%;-1.12%;0.79%;1.32%;1.12%;0.29%;-0.17%;0.56%;1.00%;2.82%;0.60% +28/02/2009;1.64%;-0.31%;-1.22%;-1.33%;-0.46%;-0.91%;0.65%;-0.55%;-1.61%;0.06%;-0.16%;3.28%;-0.37% +31/03/2009;2.35%;-1.80%;0.22%;3.50%;0.21%;1.17%;0.57%;0.48%;1.88%;1.25%;1.00%;-4.62%;0.08% +30/04/2009;5.00%;-1.40%;3.87%;6.63%;-0.12%;3.37%;2.21%;1.27%;3.75%;0.81%;3.42%;-8.20%;0.92% +31/05/2009;5.78%;2.13%;5.04%;8.84%;1.46%;4.42%;3.65%;3.48%;5.16%;1.07%;3.92%;0.08%;3.12% +30/06/2009;2.41%;-1.47%;1.98%;0.13%;0.36%;1.23%;1.26%;-0.76%;0.09%;1.04%;1.01%;-0.94%;0.24% +31/07/2009;6.11%;-0.12%;3.11%;4.51%;0.42%;2.91%;3.22%;1.66%;2.77%;0.68%;2.60%;-5.96%;1.53% +31/08/2009;3.15%;0.54%;2.44%;1.66%;0.70%;2.07%;2.02%;0.50%;1.57%;1.02%;1.62%;-1.65%;1.13% +30/09/2009;3.68%;1.51%;4.10%;5.36%;0.85%;3.36%;3.25%;2.31%;2.85%;1.10%;2.20%;-3.94%;1.71% +31/10/2009;1.19%;-1.47%;1.39%;1.08%;-0.05%;0.43%;1.85%;-0.04%;-0.86%;0.26%;0.32%;3.14%;-0.21% +30/11/2009;0.80%;3.32%;2.02%;1.51%;0.09%;1.52%;0.96%;1.65%;1.30%;0.68%;0.89%;-2.27%;0.82% +31/12/2009;2.15%;-2.53%;3.24%;2.29%;0.72%;2.35%;1.41%;-0.28%;1.86%;1.02%;1.61%;-3.73%;0.66% +31/01/2010;0.53%;-2.78%;1.87%;-0.78%;0.28%;0.77%;1.72%;-0.84%;-0.95%;0.48%;0.60%;1.83%;-0.36% +28/02/2010;0.36%;0.90%;0.31%;-0.19%;0.50%;0.76%;0.23%;0.47%;0.84%;0.57%;0.57%;-2.61%;0.13% +31/03/2010;2.29%;2.75%;3.36%;4.21%;0.77%;2.73%;1.36%;1.71%;2.87%;1.09%;1.79%;-4.96%;1.71% +30/04/2010;1.99%;1.00%;2.51%;1.33%;0.18%;1.64%;1.13%;0.76%;1.00%;0.38%;1.22%;-2.87%;0.85% +31/05/2010;-2.44%;-2.48%;-2.50%;-4.80%;-0.50%;-2.57%;-1.02%;-1.28%;-3.71%;-1.15%;-1.86%;4.45%;-2.72% +30/06/2010;0.17%;0.11%;-1.05%;-0.39%;-0.45%;-1.06%;0.78%;-0.23%;-1.61%;0.23%;-0.34%;4.19%;-0.79% +31/07/2010;2.27%;-0.80%;1.43%;2.96%;0.90%;1.70%;1.00%;0.33%;1.91%;1.27%;1.74%;-4.26%;0.69% +31/08/2010;1.21%;3.10%;-0.49%;0.28%;-0.44%;-0.32%;0.88%;1.08%;-0.96%;0.70%;0.31%;3.89%;0.06% +30/09/2010;1.89%;2.67%;2.17%;4.29%;1.60%;2.72%;1.32%;2.63%;4.08%;1.34%;2.15%;-8.26%;2.19% +31/10/2010;2.14%;3.11%;2.06%;2.32%;1.05%;1.87%;1.07%;1.59%;2.08%;0.47%;1.49%;-1.79%;1.48% +30/11/2010;-0.12%;-2.24%;0.65%;-0.49%;0.44%;0.28%;0.56%;-0.47%;0.66%;-0.25%;0.37%;-1.62%;-0.09% +31/12/2010;1.45%;4.36%;3.11%;2.26%;0.94%;2.60%;0.55%;2.50%;3.42%;1.16%;1.57%;-5.07%;2.05% +31/01/2011;1.81%;-0.63%;1.73%;-0.65%;0.56%;1.41%;1.81%;-0.55%;0.52%;0.93%;0.97%;-0.76%;0.13% +28/02/2011;1.62%;1.77%;1.44%;0.11%;0.59%;1.29%;1.03%;0.95%;1.39%;0.62%;1.12%;-3.14%;0.83% +31/03/2011;0.38%;-1.64%;0.43%;1.54%;0.80%;0.20%;0.22%;-0.28%;0.21%;0.31%;0.34%;-1.70%;-0.18% +30/04/2011;0.20%;3.67%;1.29%;1.40%;1.05%;1.14%;0.97%;2.11%;1.39%;0.89%;0.72%;-1.97%;1.14% +31/05/2011;-0.17%;-3.39%;-0.14%;-1.91%;-0.37%;-0.52%;0.33%;-1.50%;-1.08%;-0.11%;-0.05%;1.34%;-1.16% +30/06/2011;-0.91%;-2.39%;-0.68%;-1.00%;-0.14%;-1.38%;-0.10%;-1.30%;-1.17%;-0.14%;-0.56%;2.70%;-1.38% +31/07/2011;-0.33%;2.58%;-0.15%;0.77%;-0.03%;-0.30%;0.18%;1.29%;-0.30%;-0.49%;-0.06%;1.99%;0.34% +31/08/2011;-1.95%;0.07%;-4.02%;-3.90%;-1.61%;-4.01%;-0.85%;-0.63%;-4.21%;-1.19%;-2.00%;6.69%;-2.52% +30/09/2011;-1.90%;-0.57%;-3.70%;-6.95%;-1.59%;-3.41%;-0.48%;-1.42%;-4.61%;-1.02%;-1.97%;7.77%;-2.62% +31/10/2011;1.29%;-3.17%;2.37%;3.65%;1.61%;2.98%;0.63%;0.53%;3.90%;1.72%;1.47%;-7.21%;0.94% +30/11/2011;-0.94%;0.14%;-1.08%;-2.72%;0.02%;-0.58%;-0.34%;-0.66%;-1.31%;0.17%;-0.24%;1.31%;-0.93% +31/12/2011;0.29%;0.34%;0.50%;-1.81%;0.06%;-0.34%;0.45%;-0.22%;-0.56%;0.56%;0.12%;0.41%;-0.54% +31/01/2012;2.36%;0.46%;3.24%;3.95%;0.95%;2.88%;1.16%;1.90%;3.27%;0.95%;2.02%;-6.79%;1.47% +29/02/2012;2.18%;0.91%;2.02%;3.41%;0.71%;1.70%;1.19%;1.34%;2.48%;1.11%;1.72%;-5.22%;1.40% +31/03/2012;0.65%;-2.04%;0.91%;-1.33%;0.23%;0.58%;0.61%;-0.61%;0.33%;0.24%;0.55%;-1.23%;0.01% +30/04/2012;-0.17%;-0.03%;-0.12%;-0.27%;-0.13%;-0.18%;0.34%;-0.59%;-0.68%;-0.11%;-0.20%;0.57%;-0.33% +31/05/2012;-0.77%;2.59%;-1.86%;-5.31%;-1.15%;-1.91%;-0.03%;-0.67%;-3.75%;-0.48%;-1.00%;6.77%;-1.40% +30/06/2012;0.72%;-2.72%;-0.09%;0.26%;0.06%;0.07%;0.46%;-0.63%;0.60%;0.23%;0.70%;-2.58%;-0.37% +31/07/2012;0.92%;3.12%;0.89%;0.81%;0.41%;0.48%;1.25%;1.44%;0.39%;0.06%;1.17%;0.87%;0.76% +31/08/2012;0.76%;-0.82%;1.61%;0.75%;0.49%;1.29%;0.82%;0.37%;1.08%;0.44%;0.95%;-3.67%;0.68% +30/09/2012;0.57%;-1.04%;1.69%;2.73%;0.43%;1.20%;0.76%;0.51%;1.57%;0.06%;1.02%;-3.85%;0.73% +31/10/2012;0.17%;-3.10%;1.18%;0.28%;0.28%;0.48%;0.58%;-0.83%;0.09%;-0.79%;0.30%;0.05%;-0.25% +30/11/2012;0.41%;-0.04%;0.82%;1.31%;0.37%;0.80%;0.54%;0.27%;0.52%;1.00%;0.56%;-1.50%;0.46% +31/12/2012;0.98%;0.57%;2.59%;3.30%;0.37%;1.93%;0.73%;1.11%;1.45%;1.45%;1.17%;-3.87%;1.08% +31/01/2013;1.58%;1.86%;2.19%;3.03%;1.35%;2.14%;1.16%;1.65%;3.08%;-0.16%;2.04%;-4.52%;2.06% +28/02/2013;0.09%;-0.99%;0.52%;-0.12%;0.33%;0.41%;0.56%;-0.12%;0.37%;0.39%;0.47%;-0.35%;0.32% +31/03/2013;0.77%;0.89%;1.49%;0.68%;0.35%;1.43%;1.13%;0.64%;1.44%;0.69%;1.30%;-1.89%;0.93% +30/04/2013;0.52%;1.92%;1.75%;0.63%;0.08%;0.78%;0.50%;1.14%;0.64%;0.61%;0.55%;-2.86%;0.76% +31/05/2013;1.34%;-2.61%;2.23%;0.33%;0.24%;1.87%;0.50%;-0.23%;1.35%;0.59%;1.01%;-2.45%;0.67% +30/06/2013;-0.81%;-2.73%;-1.05%;-3.21%;0.28%;-1.13%;-1.22%;-1.76%;-0.94%;-0.22%;-1.02%;0.56%;-1.33% +31/07/2013;0.60%;-0.76%;1.40%;0.75%;1.00%;1.49%;0.67%;0.16%;2.15%;1.03%;1.17%;-3.69%;0.91% +31/08/2013;0.46%;-1.39%;-0.34%;-1.22%;-0.59%;-0.11%;0.14%;-0.91%;-0.76%;-0.01%;-0.46%;1.07%;-0.68% +30/09/2013;0.43%;-0.57%;1.64%;2.35%;0.63%;1.60%;0.47%;0.69%;2.33%;0.84%;1.40%;-4.52%;1.27% +31/10/2013;0.95%;1.45%;1.61%;2.38%;1.42%;1.45%;0.85%;0.94%;2.04%;0.45%;1.45%;-2.07%;1.25% +30/11/2013;0.07%;1.14%;1.22%;0.30%;1.05%;1.19%;0.67%;0.69%;1.54%;0.30%;0.87%;-1.65%;1.09% +31/12/2013;0.48%;0.52%;1.20%;1.01%;0.76%;1.22%;0.40%;0.65%;1.57%;0.61%;1.02%;-1.55%;1.09% +31/01/2014;1.37%;-1.75%;0.47%;-1.95%;0.42%;0.30%;0.75%;-0.88%;-0.32%;0.46%;0.02%;0.94%;-0.33% \ No newline at end of file Added: pkg/PortfolioAnalytics/sandbox/RFinance2014/data/edhec.rda =================================================================== (Binary files differ) Property changes on: pkg/PortfolioAnalytics/sandbox/RFinance2014/data/edhec.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: pkg/PortfolioAnalytics/sandbox/RFinance2014/data/parse_edhec.R =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/data/parse_edhec.R (rev 0) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/data/parse_edhec.R 2014-04-03 18:33:08 UTC (rev 3346) @@ -0,0 +1,11 @@ +library(xts) + +df <- read.table("data/edhec.csv", header=TRUE, as.is=TRUE, sep=";") +head(df) + +edhec <- xts(apply(df[,-1], 2, function(x) as.numeric(gsub("%", "", x))) / 100, as.Date(df[,1], format="%d/%m/%Y")) +save(edhec, file="edhec.rda") +# load("edhec.rda") +# head(edhec) +# library(PerformanceAnalytics) +# data(edhec) Added: pkg/PortfolioAnalytics/sandbox/RFinance2014/edhec.rda =================================================================== (Binary files differ) Property changes on: pkg/PortfolioAnalytics/sandbox/RFinance2014/edhec.rda ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: pkg/PortfolioAnalytics/sandbox/RFinance2014/edhec_eda.R =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/edhec_eda.R (rev 0) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/edhec_eda.R 2014-04-03 18:33:08 UTC (rev 3346) @@ -0,0 +1,78 @@ +# script for data analysis + +library(PerformanceAnalytics) +library(lattice) +library(corrplot) + +load("data/edhec.rda") + +head(edhec) +R <- edhec[,1:4] +p <- 0.95 + +first(R) +last(R) + +# plot the timeseries of returns +# plot(as.zoo(edhec)) +xyplot(R, scales=list(y="same")) +charts.BarVaR(R, width=36, methods=c("ModifiedES", "ModifiedVaR")) +dev.off() + +# boxplot to compare return distributions +# mar(bottom, left, top, right) +# default: par(mar=c(5, 4, 4, 2) + 0.1) +par(mar=c(10, 4, 4, 2) + 0.1) +boxplot(coredata(R[,order(ES(R, p=p, invert=FALSE))]), + cex.axis=0.8, las=3, ylab="Returns", pch=18, + main="Return Distribution\n(sorted by Modified ES (95%))") +par(mar=c(5, 4, 4, 2) + 0.1) +dev.off() + +# head(R[,order(ES(R, invert=FALSE))]) +# head(R[,order(StdDev(R))]) +# chart.Boxplot(R[,order(ES(R, invert=FALSE))]) +# chart.Boxplot(R[,order(StdDev(R))]) +# boxplot(coredata(R), col=c(2:5), cex.names=0.8, las=3) + +# chart the distribution of returns +for(i in 1:ncol(R)){ + chart.Histogram(R[,i], methods=c("add.density", "add.normal"), + colorset=c("lightgray", "black", "blue")) + legend("topleft", legend=c("kernel density estimate", "normal"), + lty=c(1,1), col=c("black", "blue"), bty="n") + Sys.sleep(1) +} + + +# chart the correlation and covariance +# from http://cran.r-project.org/web/packages/corrplot/vignettes/corrplot-intro.html +cor.mtest <- function(mat, conf.level = 0.95) { + mat <- as.matrix(mat) + n <- ncol(mat) + p.mat <- lowCI.mat <- uppCI.mat <- matrix(NA, n, n) + diag(p.mat) <- 0 + diag(lowCI.mat) <- diag(uppCI.mat) <- 1 + for (i in 1:(n - 1)) { + for (j in (i + 1):n) { + tmp <- cor.test(mat[, i], mat[, j], conf.level = conf.level) + p.mat[i, j] <- p.mat[j, i] <- tmp$p.value + lowCI.mat[i, j] <- lowCI.mat[j, i] <- tmp$conf.int[1] + uppCI.mat[i, j] <- uppCI.mat[j, i] <- tmp$conf.int[2] + } + } + return(list(p.mat, lowCI.mat, uppCI.mat)) +} +res <- cor.mtest(R) + +corrplot(cor(R), p.mat=res[[1]], main="Correlation", + sig.level=0.05, tl.cex=0.8) + +# corrplot(M, method="number", bg="gray", tl.cex=0.8) +# corrplot.mixed(M, bg="gray", tl.cex=0.8) + +# If I compare sample min variance portfolio to a ledoit-shrinkage or robust, +# I should use plotcov to compare covaiance matrices + + + Added: pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R (rev 0) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R 2014-04-03 18:33:08 UTC (rev 3346) @@ -0,0 +1,271 @@ +# script used to run the portfolio optimizations + +library(PortfolioAnalytics) +# Load the updated edhec dataset +load("data/edhec.rda") + +# For now, use the first 8 +R <- edhec[,1:8] +# Abreviate column names for convenience and plotting +colnames(R) <- c("CA", "CTAG", "DS", "EM", "EQN", "ED", "FA", "GM") +funds <- colnames(R) + +# Example 1 +# Box constraints, minimum variance portfolio +# specify portfolio +init <- portfolio.spec(funds) + +# Add constraints +port1 <- add.constraint(init, type="full_investment") +port1 <- add.constraint(port1, type="box", min=0.05, max=0.6) + +# Add objective +port1 <- add.objective(port1, type="risk", name="var") + +# Custom moment function to use +robust.sigma <- function(R, ...){ + out <- list() + set.seed(1234) + out$sigma <- MASS::cov.rob(R, method="mcd", ...)$cov + return(out) +} + +# Rebalancing parameters +# Set rebalancing frequency +rebal.freq <- "quarters" +# Training Period +training <- 120 +# Trailing Period +trailing <- 72 + +# Run optimization +# Sample Covariance Matrix Estimate +opt.minVarSample <- optimize.portfolio.rebalancing(R, port1, + optimize_method="ROI", + rebalance_on=rebal.freq, + training_period=training, + trailing_periods=trailing) +ret.minVarSample <- summary(opt.minVarSample)$portfolio_returns + + +# MCD Covarinace Matrix Estimate +opt.minVarRobust <- optimize.portfolio.rebalancing(R, port1, + optimize_method="ROI", + momentFUN=robust.sigma, + rebalance_on=rebal.freq, + training_period=training, + trailing_periods=trailing) + +# Chart the weights +chart.Weights(opt.minVarSample, main="minVarSample Weights") +chart.Weights(opt.minVarRobust, main="minVarRobust Weights") + +# Calculate the turnover per period +turnover.rebalancing <- function(object){ + weights <- extractWeights(object) + n <- nrow(weights) + out <- vector("numeric", n) + out[1] <- NA + for(i in 2:n){ + out[i] <- out[i] <- sum(abs(as.numeric(weights[i,]) - as.numeric(weights[i-1,]))) + } + xts(out, index(weights)) +} + +# Compute the average turnover +to.minVarSample <- mean(turnover.rebalancing(opt.minVarSample), na.rm=TRUE) +to.minVarRobust <- mean(turnover.rebalancing(opt.minVarRobust), na.rm=TRUE) + + +# Calculate the diversification per period +diversification.rebalancing <- function(object){ + weights <- extractWeights(object) + n <- nrow(weights) + out <- vector("numeric", n) + for(i in 1:n){ + out[i] <- 1 - sum(weights[i,]^2) + } + xts(out, index(weights)) +} + +# Compute the average diversification +div.minVarSample <- mean(diversification.rebalancing(opt.minVarSample)) +div.minVarRobust <- mean(diversification.rebalancing(opt.minVarRobust)) + +# Compute the returns +ret.minVarSample <- summary(opt.minVarSample)$portfolio_returns +ret.minVarRobust <- summary(opt.minVarRobust)$portfolio_returns +ret.minVar <- cbind(ret.minVarSample, ret.minVarRobust) +colnames(ret.minVar) <- c("Sample", "Robust") +charts.PerformanceSummary(ret.minVar) + +## Example 2 + +# Example 2 will consider three portfolios +# - meanES +# - meanES with 30% component contribution limit +# - meanES equal risk contribution + +# meanES +# Add constraints +port2 <- add.constraint(init, type="full_investment") +port2 <- add.constraint(port2, type="box", min=0, max=0.6) + +# Add objectives +port2 <- add.objective(port2, type="return", name="mean") +port2 <- add.objective(port2, type="risk", name="ES", + arguments=list(p=0.92, clean="boudt")) + +opt.MeanES.ROI <- optimize.portfolio(R, port2, optimize_method="ROI", trace=TRUE) +plot(opt.MeanES.ROI) + +# relax the constraints for random portfolio +port2$constraints[[1]]$min_sum <- 0.99 +port2$constraints[[1]]$max_sum <- 1.01 + +search.size <- 20000 + +set.seed(123) +rp <- random_portfolios(port2, permutations=search.size) + +#set.seed(123) +#rp1 <- random_portfolios(port2, permutations=search.size) +#all.equal(rp, rp1) + + +opt.MeanES.RP <- optimize.portfolio(R, port2, optimize_method="random", + rp=rp, trace=TRUE) +#extractObjectiveMeasures(combine.optimizations(list(opt.MeanES.ROI, opt.MeanES.RP))) +#extractWeights(combine.optimizations(list(opt.MeanES.ROI, opt.MeanES.RP))) + +plot(opt.MeanES.RP, neighbors=25) + +# Calculate the component contribution to risk +portContribES <- ES(R, p=0.92, portfolio_method="component", + weights=extractWeights(opt.MeanES.RP)) +portContribES$pct_contrib_MES + +# Now suppose we want to place limits on percent component contribution to risk +port3 <- add.objective(port2, type="risk_budget", name="ES", + arguments=list(p=0.92, clean="boudt"), max_prisk=0.35) + +opt.MeanES.RB <- optimize.portfolio(R, port3, optimize_method="random", + trace=TRUE, rp=rp) +opt.MeanES.RB + +chart.RiskBudget(opt.MeanES.RB, risk.type="percentage", neighbors=25) + + +port4 <- add.objective(port2, type="risk_budget", name="ES", + arguments=list(p=0.92, clean="boudt"), + min_concentration=TRUE) +opt.MeanES.EqRB <- optimize.portfolio(R, port4, optimize_method="random", + trace=TRUE, rp=rp) +opt.MeanES.EqRB +chart.RiskBudget(opt.MeanES.EqRB, risk.type="percentage", neighbors=25) + +# plot +# - opt.meanES.ROI +# - opt.meanES.RP +# - opt.meanES.RB +# - opt.meanES.EqRB + +xtract <- extractStats(opt.MeanES.RP) + +# plot the feasible space +par(mar=c(6,4,4,1)+0.1) +plot(xtract[,"ES"], xtract[,"mean"], col="gray", + xlab="ES", ylab="Mean", + xlim=c(0, max(xtract[,"ES"]))) + +# opt.MeanES.ROI +points(x=opt.MeanES.ROI$objective_measures$ES, + y=opt.MeanES.ROI$objective_measures$mean, + pch=15, col="blue") +text(x=opt.MeanES.ROI$objective_measures$ES, + y=opt.MeanES.ROI$objective_measures$mean, + labels="Mean ES ROI", pos=4, col="blue", cex=0.8) + +# opt.MeanES.RP +points(x=opt.MeanES.RP$objective_measures$ES, + y=opt.MeanES.RP$objective_measures$mean, + pch=15, col="purple") +text(x=opt.MeanES.RP$objective_measures$ES, + y=opt.MeanES.RP$objective_measures$mean, + labels="Mean ES RP", pos=1, col="purple", cex=0.8) + +# opt.MeanES.RB +points(x=opt.MeanES.RB$objective_measures$ES$MES, + y=opt.MeanES.RB$objective_measures$mean, + pch=15, col="black") +text(x=opt.MeanES.RB$objective_measures$ES$MES, + y=opt.MeanES.RB$objective_measures$mean, + labels="Mean ES RB", pos=4, col="black", cex=0.8) + +# opt.MeanES.EqRB +points(x=opt.MeanES.EqRB$objective_measures$ES$MES, + y=opt.MeanES.EqRB$objective_measures$mean, + pch=15, col="darkgreen") +text(x=opt.MeanES.EqRB$objective_measures$ES$MES, + y=opt.MeanES.EqRB$objective_measures$mean, + labels="Mean ES EqRB", pos=4, col="darkgreen", cex=0.8) + + +# Backtest these three portfolios +# I'm going to add a risk budget object to port2 with multiplier=0 so that +# it is calculated, but does not affect the optimization +port2 <- add.objective(port2, name="ES", type="risk_budget", arguments=list(p=0.92), multiplier=0) + + +# Rebalancing parameters +# Set rebalancing frequency +rebal.freq <- "quarters" +# Training Period +training <- 120 +# Trailing Period +trailing <- 72 + +bt.opt.MeanES <- optimize.portfolio.rebalancing(R, port2, rp=rp, + optimize_method="random", + rebalance_on=rebal.freq, + training_period=training, + trailing_periods=trailing) +chart.RiskBudget(bt.opt.MeanES, main="Mean ES", risk.type="percentage") + +bt.opt.MeanES.RB <- optimize.portfolio.rebalancing(R, port3, rp=rp, + optimize_method="random", + rebalance_on=rebal.freq, + training_period=training, + trailing_periods=trailing) +chart.RiskBudget(bt.opt.MeanES.RB, main="Mean-ES 30% Limit", + risk.type="percentage") + + +bt.opt.MeanES.EqRB <- optimize.portfolio.rebalancing(R, port4, rp=rp, + optimize_method="random", + rebalance_on=rebal.freq, + training_period=training, + trailing_periods=trailing) +chart.RiskBudget(bt.opt.MeanES.EqRB, main="Mean-ES Equal Risk", + risk.type="percentage") + [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/returnanalytics -r 3346 From noreply at r-forge.r-project.org Sun Apr 6 02:07:28 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 6 Apr 2014 02:07:28 +0200 (CEST) Subject: [Returnanalytics-commits] r3347 - in pkg/PortfolioAnalytics/sandbox/RFinance2014: . R Message-ID: <20140406000729.5D160187305@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-06 02:07:26 +0200 (Sun, 06 Apr 2014) New Revision: 3347 Added: pkg/PortfolioAnalytics/sandbox/RFinance2014/R/ pkg/PortfolioAnalytics/sandbox/RFinance2014/R/lwShrink.R Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.html pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.md pkg/PortfolioAnalytics/sandbox/RFinance2014/slides.pdf Log: Updating optimization script with new examples and data Added: pkg/PortfolioAnalytics/sandbox/RFinance2014/R/lwShrink.R =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/R/lwShrink.R (rev 0) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/R/lwShrink.R 2014-04-06 00:07:26 UTC (rev 3347) @@ -0,0 +1,54 @@ +lwShrink <- function(x, shrink=NULL){ + # port of matlab code from http://www.econ.uzh.ch/faculty/wolf/publications.html#9 + # Ledoit, O. and Wolf, M. (2004). + # Honey, I shrunk the sample covariance matrix. + # Journal of Portfolio Management 30, Volume 4, 110-119. + + # De-mean returns + n <- nrow(x) + p <- ncol(x) + meanx <- colMeans(x) + x <- x - matrix(rep(meanx, n), ncol=p, byrow=TRUE) + + # Compute sample covariance matrix using the de-meaned returns + sample <- (1 / n) * (t(x) %*% x) + + # Compute prior + var <- matrix(diag(sample), ncol=1) + sqrtvar <- sqrt(var) + tmpMat <- matrix(rep(sqrtvar, p), nrow=p) + rBar <- (sum(sum(sample / (tmpMat * t(tmpMat)))) - p) / (p * (p - 1)) + prior <- rBar * tmpMat * t(tmpMat) + diag(prior) <- var + + if(is.null(shrink)){ + # What is called pi-hat + y <- x^2 + phiMat <- t(y) %*% y / n - 2 * (t(x) %*% x) * sample / n + sample^2 + phi <- sum(phiMat) + + # What is called rho-hat + term1 <- (t(x^3) %*% x) / n + help <- t(x) %*% x / n + helpDiag <- matrix(diag(help), ncol=1) + term2 <- matrix(rep(helpDiag, p), ncol=p, byrow=FALSE) * sample + term3 <- help * matrix(rep(var, p), ncol=p, byrow=FALSE) + term4 <- matrix(rep(var, p), ncol=p, byrow=FALSE) * sample + thetaMat <- term1 - term2 - term3 + term4 + diag(thetaMat) <- 0 + rho <- sum(diag(phiMat)) + rBar * sum(sum(((1 / sqrtvar) %*% t(sqrtvar)) * thetaMat)) + + # What is called gamma-hat + gamma <- norm(sample - prior, "F")^2 + + # Compute shrinkage constant + kappa <- (phi - rho) / gamma + shrinkage <- max(0, min(1, kappa / n)) + } else { + shrinkage <- shrink + } + # Compute the estimator + sigma <- shrinkage * prior + (1 - shrinkage) * sample + out <- list(cov=sigma, prior=prior, shrinkage=shrinkage) + return(out) +} Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R 2014-04-03 18:33:08 UTC (rev 3346) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R 2014-04-06 00:07:26 UTC (rev 3347) @@ -1,222 +1,264 @@ # script used to run the portfolio optimizations +# Examples to consider +# Example 1: Consider a portfolio of stocks. Full investment and long +# only (or box) constraints. Objective to minimize portfolio variance. +# Demonstrate a custom moments function to compare a sample covariance +# matrix estimate and a robust covariance matrix estimate. An alternative +# to a MCD estimate is ledoit-wolf shrinkage, DCC GARCH model, +# factor model, etc. + +# Example 2: Consider a portfolio of stocks. Dollar neutral, beta +# neutral, box constraints, and leverage_exposure constraints. Objective +# to minimize portfolio StdDev. This will demonstrate some of the +# more advanced constraint types. Could also introduce position limit +# constraints here in this example. + +# Example 3: Consider an allocation to hedge funds using the +# EDHEC-Risk Alternative Index as a proxy. This will be an extended +# example starting with an objective to minimize portfolio expected +# shortfall, then risk budget percent contribution limit, then equal +# risk contribution limit. + +# Example 4: Consider an allocation to hedge funds using the +# EDHEC-Risk Alternative Index as a proxy. + +# Option 1 for example 4 +# Objective to maximize a risk adjusted return measure +# (e.g.Calmar Ratio, Sterling Ratio, Sortino Ratio, or Upside Potential +# Ratio) + +# I prefer doing this option +# Option 2 for example 4 +# Objective to maximize the +# fourth order expansion of the Constant Relative Risk Aversion (CRRA) +# expected utility function. Demonstrate a custom moment function and +# a custom objective function. + +# Load the packages library(PortfolioAnalytics) +library(foreach) +library(ROI) +library(ROI.plugin.quadprog) +library(ROI.plugin.glpk) + +# Source in the lwShrink function +source("R/lwShrink.R") + +# Example 1 and Example 2 will use the crsp_weekly data +# load the CRSP weekly data +load("data/crsp_weekly.rda") + +# Example 3 and Example 4 will use the edhec data # Load the updated edhec dataset load("data/edhec.rda") -# For now, use the first 8 -R <- edhec[,1:8] -# Abreviate column names for convenience and plotting -colnames(R) <- c("CA", "CTAG", "DS", "EM", "EQN", "ED", "FA", "GM") -funds <- colnames(R) -# Example 1 -# Box constraints, minimum variance portfolio -# specify portfolio -init <- portfolio.spec(funds) +# Prep data for Examples 1 and 2 +# use the first 10 stocks in largecap_weekly, midcap_weekly, and smallcap_weekly +N <- 10 +equity.data <- cbind(largecap_weekly[,1:N], + midcap_weekly[,1:N], + smallcap_weekly[,1:N]) +market <- largecap_weekly[,21] +Rf <- largecap_weekly[,22] +stocks <- colnames(equity.data) +# Specify an initial portfolio +portf.init <- portfolio.spec(stocks) + +##### Example 1 ##### # Add constraints -port1 <- add.constraint(init, type="full_investment") -port1 <- add.constraint(port1, type="box", min=0.05, max=0.6) +# weights sum to 1 +portf.minvar <- add.constraint(portf.init, type="full_investment") +# box constraints such that no stock has weight less than 1% or greater than 20% +portf.minvar <- add.constraint(portf.minvar, type="box", min=0.01, max=0.2) # Add objective -port1 <- add.objective(port1, type="risk", name="var") +# objective to minimize portfolio variance +portf.minvar <- add.objective(portf.minvar, type="risk", name="var") -# Custom moment function to use -robust.sigma <- function(R, ...){ - out <- list() - set.seed(1234) - out$sigma <- MASS::cov.rob(R, method="mcd", ...)$cov - return(out) -} - # Rebalancing parameters # Set rebalancing frequency rebal.freq <- "quarters" # Training Period -training <- 120 +training <- 400 # Trailing Period -trailing <- 72 +trailing <- 250 # Run optimization # Sample Covariance Matrix Estimate -opt.minVarSample <- optimize.portfolio.rebalancing(R, port1, - optimize_method="ROI", - rebalance_on=rebal.freq, - training_period=training, - trailing_periods=trailing) -ret.minVarSample <- summary(opt.minVarSample)$portfolio_returns +# By default, momentFUN uses set.portfolio.moments which computes the sample +# moment estimates -# MCD Covarinace Matrix Estimate -opt.minVarRobust <- optimize.portfolio.rebalancing(R, port1, +opt.minVarSample <- optimize.portfolio.rebalancing(equity.data, portf.minvar, optimize_method="ROI", - momentFUN=robust.sigma, rebalance_on=rebal.freq, training_period=training, trailing_periods=trailing) -# Chart the weights -chart.Weights(opt.minVarSample, main="minVarSample Weights") -chart.Weights(opt.minVarRobust, main="minVarRobust Weights") - -# Calculate the turnover per period -turnover.rebalancing <- function(object){ - weights <- extractWeights(object) - n <- nrow(weights) - out <- vector("numeric", n) - out[1] <- NA - for(i in 2:n){ - out[i] <- out[i] <- sum(abs(as.numeric(weights[i,]) - as.numeric(weights[i-1,]))) - } - xts(out, index(weights)) +# Custom moment function to use Ledoit-Wolf shinkage covariance matrix estimate +lw.sigma <- function(R, ...){ + out <- list() + # estimate covariance matrix via robust covariance matrix estimate, + # ledoit-wolf shrinkage, GARCH, factor model, etc. + # set.seed(1234) + # out$sigma <- MASS::cov.rob(R, method="mcd", ...)$cov + out$sigma <- lwShrink(R)$cov + #print(index(last(R))) + return(out) } -# Compute the average turnover -to.minVarSample <- mean(turnover.rebalancing(opt.minVarSample), na.rm=TRUE) -to.minVarRobust <- mean(turnover.rebalancing(opt.minVarRobust), na.rm=TRUE) +# Using Ledoit-Wolf Shrinkage Covariance Matrix Estimate +opt.minVarLW <- optimize.portfolio.rebalancing(equity.data, portf.minvar, + optimize_method="ROI", + momentFUN=lw.sigma, + rebalance_on=rebal.freq, + training_period=training, + trailing_periods=trailing) +# Chart the weights +chart.Weights(opt.minVarSample, main="minVarSample Weights") +chart.Weights(opt.minVarLW, main="minVarLW Weights") -# Calculate the diversification per period -diversification.rebalancing <- function(object){ - weights <- extractWeights(object) - n <- nrow(weights) - out <- vector("numeric", n) - for(i in 1:n){ - out[i] <- 1 - sum(weights[i,]^2) - } - xts(out, index(weights)) -} - -# Compute the average diversification -div.minVarSample <- mean(diversification.rebalancing(opt.minVarSample)) -div.minVarRobust <- mean(diversification.rebalancing(opt.minVarRobust)) - -# Compute the returns +# Compute and chart the returns ret.minVarSample <- summary(opt.minVarSample)$portfolio_returns -ret.minVarRobust <- summary(opt.minVarRobust)$portfolio_returns +ret.minVarRobust <- summary(opt.minVarLW)$portfolio_returns ret.minVar <- cbind(ret.minVarSample, ret.minVarRobust) -colnames(ret.minVar) <- c("Sample", "Robust") +colnames(ret.minVar) <- c("Sample", "LW") charts.PerformanceSummary(ret.minVar) -## Example 2 +##### Example 2 ##### +portf.init <- portfolio.spec(stocks, + weight_seq=generatesequence(min=-0.2, max=0.2, by=0.001)) -# Example 2 will consider three portfolios -# - meanES -# - meanES with 30% component contribution limit -# - meanES equal risk contribution +# weights sum to 0 +portf.dn <- add.constraint(portf.init, type="weight_sum", + min_sum=-0.01, max_sum=0.01) +# box constraints such that no stock has weight less than -20% or greater than 20% +portf.dn <- add.constraint(portf.dn, type="box", + min=-0.2, max=0.2) +# maximum of 20 non-zero positions +portf.dn <- add.constraint(portf.dn, type="position_limit", max_pos=20) -# meanES -# Add constraints -port2 <- add.constraint(init, type="full_investment") -port2 <- add.constraint(port2, type="box", min=0, max=0.6) +# cov(equity.data[,1], market) / var(market) +# coef(lm(equity.data ~ market))[2,] +betas <- t(CAPM.beta(equity.data, market, Rf)) +portf.dn <- add.constraint(portf.dn, type="factor_exposure", B=betas, + lower=-0.5, upper=0.5) +# portf.dn <- add.constraint(portf.dn, type="leverage_exposure", leverage=2) -# Add objectives -port2 <- add.objective(port2, type="return", name="mean") -port2 <- add.objective(port2, type="risk", name="ES", - arguments=list(p=0.92, clean="boudt")) +rp <- random_portfolios(portf.dn, 10000, eliminate=TRUE) +dim(rp) -opt.MeanES.ROI <- optimize.portfolio(R, port2, optimize_method="ROI", trace=TRUE) -plot(opt.MeanES.ROI) +# Add objective +# objective to minimize portfolio variance +portf.dn.StdDev <- add.objective(portf.dn, type="return", name="mean", + target=0.001) +portf.dn.StdDev <- add.objective(portf.dn.StdDev, type="risk", name="StdDev") -# relax the constraints for random portfolio -port2$constraints[[1]]$min_sum <- 0.99 -port2$constraints[[1]]$max_sum <- 1.01 +opt <- optimize.portfolio(equity.data, portf.dn.StdDev, + optimize_method="random", rp=rp, + trace=TRUE) +opt -search.size <- 20000 +plot(opt, risk.col="StdDev", neighbors=10) -set.seed(123) -rp <- random_portfolios(port2, permutations=search.size) +# chart.RiskReward(opt, risk.col="StdDev", neighbors=25) +# chart.Weights(opt, plot.type="bar", legend.loc=NULL) +# wts <- extractWeights(opt) +# t(wts) %*% betas +# sum(abs(wts)) +# sum(wts[wts > 0]) +# sum(wts[wts < 0]) +# sum(wts != 0) -#set.seed(123) -#rp1 <- random_portfolios(port2, permutations=search.size) -#all.equal(rp, rp1) +# Prep data for Examples 3 and 4 +# For now, use the first 8 +R <- edhec[,1:8] +# Abreviate column names for convenience and plotting +colnames(R) <- c("CA", "CTAG", "DS", "EM", "EQN", "ED", "FA", "GM") +funds <- colnames(R) +##### Example 3 ##### +# Example 3 will consider three portfolios +# - minES +# - minES with 30% component contribution limit +# - minES with equal risk contribution -opt.MeanES.RP <- optimize.portfolio(R, port2, optimize_method="random", - rp=rp, trace=TRUE) -#extractObjectiveMeasures(combine.optimizations(list(opt.MeanES.ROI, opt.MeanES.RP))) -#extractWeights(combine.optimizations(list(opt.MeanES.ROI, opt.MeanES.RP))) +portf.init <- portfolio.spec(funds) +portf.init <- add.constraint(portf.init, type="weight_sum", + min_sum=0.99, max_sum=1.01) -plot(opt.MeanES.RP, neighbors=25) +portf.init <- add.constraint(portf.init, type="box", + min=0.05, max=0.4) -# Calculate the component contribution to risk -portContribES <- ES(R, p=0.92, portfolio_method="component", - weights=extractWeights(opt.MeanES.RP)) -portContribES$pct_contrib_MES +# Set multiplier=0 so that it is calculated, but does not affect the optimization +portf.init <- add.objective(portf.init, type="return", + name="mean", multiplier=0) -# Now suppose we want to place limits on percent component contribution to risk -port3 <- add.objective(port2, type="risk_budget", name="ES", - arguments=list(p=0.92, clean="boudt"), max_prisk=0.35) +# Add objective to minimize expected shortfall +portf.minES <- add.objective(portf.init, type="risk", name="ES") -opt.MeanES.RB <- optimize.portfolio(R, port3, optimize_method="random", - trace=TRUE, rp=rp) -opt.MeanES.RB +# Add objective to +portf.minES.RB <- add.objective(portf.minES, type="risk_budget", + name="ES", max_prisk=0.3) -chart.RiskBudget(opt.MeanES.RB, risk.type="percentage", neighbors=25) +portf.minES.EqRB <- add.objective(portf.minES, type="risk_budget", + name="ES", min_concentration=TRUE) +portf <- combine.portfolios(list(minES=portf.minES, + minES.RB=portf.minES.RB, + minES.EqRB=portf.minES.EqRB)) -port4 <- add.objective(port2, type="risk_budget", name="ES", - arguments=list(p=0.92, clean="boudt"), - min_concentration=TRUE) -opt.MeanES.EqRB <- optimize.portfolio(R, port4, optimize_method="random", - trace=TRUE, rp=rp) -opt.MeanES.EqRB -chart.RiskBudget(opt.MeanES.EqRB, risk.type="percentage", neighbors=25) +opt.minES <- optimize.portfolio(R, portf, optimize_method="DEoptim", + search_size=2000, trace=TRUE, traceDE=0, + message=TRUE) -# plot -# - opt.meanES.ROI -# - opt.meanES.RP -# - opt.meanES.RB -# - opt.meanES.EqRB +extractObjectiveMeasures(opt.minES) -xtract <- extractStats(opt.MeanES.RP) +xtract <- extractStats(opt.minES) +str(xtract) +# get the mean column from each element of the list +xtract.mean <- unlist(lapply(xtract, function(x) x[,"mean"])) +xtract.ES <- unlist(lapply(xtract, function(x) x[,"ES"])) + # plot the feasible space -par(mar=c(6,4,4,1)+0.1) -plot(xtract[,"ES"], xtract[,"mean"], col="gray", +par(mar=c(7,4,4,1)+0.1) +plot(xtract.ES, xtract.mean, col="gray", xlab="ES", ylab="Mean", - xlim=c(0, max(xtract[,"ES"]))) + xlim=c(0, max(xtract.ES))) -# opt.MeanES.ROI -points(x=opt.MeanES.ROI$objective_measures$ES, - y=opt.MeanES.ROI$objective_measures$mean, - pch=15, col="blue") -text(x=opt.MeanES.ROI$objective_measures$ES, - y=opt.MeanES.ROI$objective_measures$mean, - labels="Mean ES ROI", pos=4, col="blue", cex=0.8) - -# opt.MeanES.RP -points(x=opt.MeanES.RP$objective_measures$ES, - y=opt.MeanES.RP$objective_measures$mean, +# min ES +points(x=opt.minES[[1]]$objective_measures$ES, + y=opt.minES[[1]]$objective_measures$mean, pch=15, col="purple") -text(x=opt.MeanES.RP$objective_measures$ES, - y=opt.MeanES.RP$objective_measures$mean, - labels="Mean ES RP", pos=1, col="purple", cex=0.8) +text(x=opt.minES[[1]]$objective_measures$ES, + y=opt.minES[[1]]$objective_measures$mean, + labels="Min ES", pos=4, col="purple", cex=0.8) -# opt.MeanES.RB -points(x=opt.MeanES.RB$objective_measures$ES$MES, - y=opt.MeanES.RB$objective_measures$mean, +# min ES with Risk Budget +points(x=opt.minES[[2]]$objective_measures$ES$MES, + y=opt.minES[[2]]$objective_measures$mean, pch=15, col="black") -text(x=opt.MeanES.RB$objective_measures$ES$MES, - y=opt.MeanES.RB$objective_measures$mean, - labels="Mean ES RB", pos=4, col="black", cex=0.8) +text(x=opt.minES[[2]]$objective_measures$ES$MES, + y=opt.minES[[2]]$objective_measures$mean, + labels="Min ES RB", pos=4, col="black", cex=0.8) # opt.MeanES.EqRB -points(x=opt.MeanES.EqRB$objective_measures$ES$MES, - y=opt.MeanES.EqRB$objective_measures$mean, +points(x=opt.minES[[3]]$objective_measures$ES$MES, + y=opt.minES[[3]]$objective_measures$mean, pch=15, col="darkgreen") -text(x=opt.MeanES.EqRB$objective_measures$ES$MES, - y=opt.MeanES.EqRB$objective_measures$mean, - labels="Mean ES EqRB", pos=4, col="darkgreen", cex=0.8) +text(x=opt.minES[[3]]$objective_measures$ES$MES, + y=opt.minES[[3]]$objective_measures$mean, + labels="Min ES EqRB", pos=4, col="darkgreen", cex=0.8) -# Backtest these three portfolios -# I'm going to add a risk budget object to port2 with multiplier=0 so that -# it is calculated, but does not affect the optimization -port2 <- add.objective(port2, name="ES", type="risk_budget", arguments=list(p=0.92), multiplier=0) +chart.RiskBudget(opt.minES[[2]], risk.type="percentage", neighbors=10) +chart.RiskBudget(opt.minES[[3]], risk.type="percentage", neighbors=10) - # Rebalancing parameters # Set rebalancing frequency rebal.freq <- "quarters" @@ -225,47 +267,46 @@ # Trailing Period trailing <- 72 -bt.opt.MeanES <- optimize.portfolio.rebalancing(R, port2, rp=rp, - optimize_method="random", - rebalance_on=rebal.freq, - training_period=training, - trailing_periods=trailing) -chart.RiskBudget(bt.opt.MeanES, main="Mean ES", risk.type="percentage") +# Backtest +bt.opt.minES <- optimize.portfolio.rebalancing(R, portf, + optimize_method="DEoptim", + rebalance_on=rebal.freq, + training_period=training, + trailing_periods=trailing, + traceDE=0, message=TRUE) -bt.opt.MeanES.RB <- optimize.portfolio.rebalancing(R, port3, rp=rp, - optimize_method="random", - rebalance_on=rebal.freq, - training_period=training, - trailing_periods=trailing) -chart.RiskBudget(bt.opt.MeanES.RB, main="Mean-ES 30% Limit", - risk.type="percentage") +##### Example 4 ##### -bt.opt.MeanES.EqRB <- optimize.portfolio.rebalancing(R, port4, rp=rp, - optimize_method="random", - rebalance_on=rebal.freq, - training_period=training, - trailing_periods=trailing) -chart.RiskBudget(bt.opt.MeanES.EqRB, main="Mean-ES Equal Risk", - risk.type="percentage") - -# pass in a portfolio.list instead of typing this 3 times - -# calculate the returns -ret.MeanES <- summary(bt.opt.MeanES)$portfolio_returns -ret.MeanES.RB <- summary(bt.opt.MeanES.RB)$portfolio_returns -ret.MeanES.EqRB <- summary(bt.opt.MeanES.EqRB)$portfolio_returns - -# Combine the returns -ret <- cbind(ret.MeanES, ret.MeanES.RB, ret.MeanES.EqRB) -colnames(ret) <- c("Mean.ES", "MeanES.RB", "MeanES.EqRB") -charts.PerformanceSummary(ret) - # CRRA 4th order expansion expected utility -# look in PerformanceAnalytics +# PerformanceAnalytics for moments # M3.MM # M4.MM # StdDev.MM # skewness.MM # kurtosis.MM + + +# # Calculate the turnover per period +# turnover.rebalancing <- function(object){ +# weights <- extractWeights(object) +# n <- nrow(weights) +# out <- vector("numeric", n) +# out[1] <- NA +# for(i in 2:n){ +# out[i] <- out[i] <- sum(abs(as.numeric(weights[i,]) - as.numeric(weights[i-1,]))) +# } +# xts(out, index(weights)) +# } +# +# # Calculate the diversification per period +# diversification.rebalancing <- function(object){ +# weights <- extractWeights(object) +# n <- nrow(weights) +# out <- vector("numeric", n) +# for(i in 1:n){ +# out[i] <- 1 - sum(weights[i,]^2) +# } +# xts(out, index(weights)) +# } Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd 2014-04-03 18:33:08 UTC (rev 3346) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd 2014-04-06 00:07:26 UTC (rev 3347) @@ -6,8 +6,8 @@ toc: true --- -```{r} -libary(knitr) +```{r, echo=FALSE} +library(knitr) opts_chunk$set(fig.height=4.5, fig.cap="", tidy=FALSE, cache=TRUE) ``` @@ -91,9 +91,18 @@ Specify a Portfolio --> Add Constraints --> Add Objectives --> Run Optimization --> Analyze Results -# Examples + -## Data +# Data + +## Data Setup Here we will look at portfolio optimization in the context of portfolio of hedge funds * EDHEC-Risk Alternative Indexes @@ -127,13 +136,18 @@ # dev.off() ``` -## Specify a Portfolio Object -```{r} -args(portfolio.spec) -``` +# Example 1 -```{r} -init.portf <- portfolio.spec(colnames(R)) +## Minimum Variance Portfolio +Set up portfolio to minimize variance +```{r, eval=FALSE} +# Specify initial portfolio +init <- portfolio.spec(funds) +# Add constraints +port1 <- add.constraint(init, type="full_investment") +port1 <- add.constraint(port1, type="box", min=0.05, max=0.6) +# Add objective +port1 <- add.objective(port1, type="risk", name="var") ``` Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.html =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.html 2014-04-03 18:33:08 UTC (rev 3346) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.html 2014-04-06 00:07:26 UTC (rev 3347) @@ -135,10 +135,47 @@ + + + + + - - - - - - - - - - - - -

Portfolio Optimization

- -

General

- -

TODO: Add some general comments here about goals and pitfalls of optimization in the context of constructing a portfolio.

- -

Modern Portfolio Theory

- -

“Modern” Portfolio Theory (MPT) was introduced by Harry Markowitz in 1952.

- -

In general, MPT states that an investor's objective is to maximize portfolio expected return for a given amount of risk.

- -

General Objectives

- - - -

How do we define risk?

- -

Portfolio Optimization Objectives

- - - -

PortfolioAnalytics

- -

Overview

- -

PortfolioAnalytics is an R package designed to provide numerical solutions and visualizations for portfolio optimization problems with complex constraints and objectives.

- -

Key Features

- - - - - -

Support Multiple Solvers

- -

Linear and Quadratic Programming Solvers

- - - -

Global (stochastic or continuous solvers)

- - - -

Random Portfolios

- -

TODO: Add graphic comparing the three methods

- -

Random Portfolios: Simplex Method

- -

TODO: Add graphic with different fev biasing values

- -

Workflow

- -

TODO: Add a nice graphic here (Guy might have one)

- -

Specify a Portfolio –> Add Constraints –> Add Objectives –> Run Optimization –> Analyze Results

- - - -

Example 1

- -

Data Setup

- -

Here we will look at portfolio optimization in the context of stocks.

- - - -

Distribution of Monthly Returns

- [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/returnanalytics -r 3363 From noreply at r-forge.r-project.org Sat Apr 12 06:49:51 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sat, 12 Apr 2014 06:49:51 +0200 (CEST) Subject: [Returnanalytics-commits] r3364 - pkg/PortfolioAnalytics/sandbox/RFinance2014 Message-ID: <20140412044951.A97AF18703F@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-12 06:49:50 +0200 (Sat, 12 Apr 2014) New Revision: 3364 Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/makefile pkg/PortfolioAnalytics/sandbox/RFinance2014/optimization_analysis.R pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.md pkg/PortfolioAnalytics/sandbox/RFinance2014/slidy_presentation.html Log: presentation update Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/makefile =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/makefile 2014-04-11 05:50:24 UTC (rev 3363) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/makefile 2014-04-12 04:49:50 UTC (rev 3364) @@ -1,17 +1,18 @@ # http://robjhyndman.com/hyndsight/makefiles/ # https://www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/makefile.html -# List out the R files used -RFILES := data_analysis.R optimize.R optimization_analysis.R +# List the R files used +RFILES := data_prep.R data_analysis.R optimize.R optimization_analysis.R # Rout indicator files to show R file has run +# R CMD BATCH will generate .Rout files after running OUT_FILES:= $(RFILES:.R=.Rout) -all: slidy_presentation.html presentation.Rmd $(OUT_FILES) +all: $(OUT_FILES) slidy_presentation.html presentation.Rmd # Generate slidy presentation from markdown file -slidy_presentation.html: presentation.md +slidy_presentation.html: $(RFILES) $(OUT_FILES) presentation.md pandoc -t slidy -s presentation.md -o slidy_presentation.html # Generate markdown file from R markdown file @@ -20,25 +21,35 @@ # Data analysis script data_analysis.Rout: data_analysis.R - R CMD BATCH data_analysis.R + R CMD BATCH --vanilla data_analysis.R # Optimization analysis script to analyze results of optimization optimization_analysis.Rout: optimization_analysis.R optimize.R - R CMD BATCH optimization_analysis.R + R CMD BATCH --vanilla optimization_analysis.R # Run optimizations optimize.Rout: optimize.R - R CMD BATCH optimize.R + R CMD BATCH --vanilla optimize.R +# Data prep +data_prep.Rout: data_prep.R + R CMD BATCH --vanilla data_prep.R + lwShrink.Rout: R/lwShrink.R - R CMD BATCH R/lwShrink.R + R CMD BATCH --vanilla R/lwShrink.R # Use Rscript to run the necessary R files as an alternative to R CMD BATCH -run: +runR: + Rscript data_prep.R Rscript data_analysis.R Rscript optimize.R Rscript optimization_analysis.R clean: - rm *.Rout - rm *.html \ No newline at end of file + rm -f *.Rout + rm -f data_figures/*.png + rm -f optimization_figures/*.png + rm -f optimization_results/*.rda + rm -f *.md + rm -f *.html + \ No newline at end of file Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/optimization_analysis.R =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/optimization_analysis.R 2014-04-11 05:50:24 UTC (rev 3363) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/optimization_analysis.R 2014-04-12 04:49:50 UTC (rev 3364) @@ -107,21 +107,35 @@ risk.type="percentage", neighbors=10) dev.off() -# Plot the risk contribution through time +# Plot the risk contribution of portfolio 1 through time png(paste(figures.dir, "risk_minES.png", sep="/")) chart.RiskBudget(bt.opt.minES[[1]], main="Min ES Risk Contribution", risk.type="percentage") dev.off() +# Plot the risk contribution of portfolio 1 through time +png(paste(figures.dir, "weights_minES.png", sep="/")) +chart.Weights(bt.opt.minES[[1]], main="Min ES Weights") +dev.off() +# Plot the risk contribution of portfolio 3 through time png(paste(figures.dir, "risk_minESRB.png", sep="/")) chart.RiskBudget(bt.opt.minES[[2]], main="Min ES RB Risk Contribution", risk.type="percentage") dev.off() +# Plot the weights of portfolio 2 through time +png(paste(figures.dir, "weights_minESRB.png", sep="/")) +chart.Weights(bt.opt.minES[[2]], main="Min ES RB Weights") +dev.off() +# Plot the risk contribution of portfolio 3 through time png(paste(figures.dir, "risk_minESEqRB.png", sep="/")) chart.RiskBudget(bt.opt.minES[[3]], main="Min ES EqRB Risk Contribution", risk.type="percentage") dev.off() +# Plot the weights of portfolio 3 through time +png(paste(figures.dir, "weights_minESEqRB.png", sep="/")) +chart.Weights(bt.opt.minES[[3]], main="Min ES EqRB Weights") +dev.off() # Extract the returns from each element and chart the performance summary ret.bt.opt <- do.call(cbind, lapply(bt.opt.minES, @@ -149,14 +163,12 @@ } # Chart the optimization in Risk-Reward space -png(paste(figures.dir, "crra_RR.png", sep="/")) -par(mfrow=c(1,2)) +png(paste(figures.dir, "crra_RR_ES.png", sep="/")) chart.RiskReward(opt.crra, risk.col="ES") # dev.off() -# png(paste(figures.dir, "crra_minES.png", sep="/")) +png(paste(figures.dir, "crra_RR_StdDev.png", sep="/")) chart.RiskReward(opt.crra, risk.col="StdDev") -par(mfrow=c(1,1)) dev.off() # Compute the portfolio returns with rebalancing Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R 2014-04-11 05:50:24 UTC (rev 3363) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R 2014-04-12 04:49:50 UTC (rev 3364) @@ -145,7 +145,7 @@ # Add factor exposure constraint to limit portfolio beta portf.dn <- add.constraint(portf.dn, type="factor_exposure", B=betas, - lower=-0.5, upper=0.5) + lower=-0.25, upper=0.25) # portf.dn <- add.constraint(portf.dn, type="leverage_exposure", leverage=2) # generate random portfolios @@ -159,7 +159,8 @@ } # Add objective to maximize return -portf.dn.StdDev <- add.objective(portf.dn, type="return", name="mean") +portf.dn.StdDev <- add.objective(portf.dn, type="return", name="mean", + target=0.0015) # Add objective to target a portfolio standard deviation of 2% portf.dn.StdDev <- add.objective(portf.dn.StdDev, type="risk", name="StdDev", target=0.02) @@ -199,7 +200,7 @@ # Add risk budget objective with upper limit on percentage contribution portf.minES.RB <- add.objective(portf.minES, type="risk_budget", - name="ES", max_prisk=0.2) + name="ES", max_prisk=0.3) # Relax the box constraint portf.minES.RB$constraints[[2]]$max <- rep(1,ncol(R)) @@ -207,7 +208,7 @@ # Add risk budget objective to minimize concentration of percentage component # contribution to risk. Concentration is defined as the Herfindahl-Hirschman -# Index (HHI). $\sum_{i=1}^n x_i^2$ +# Index (HHI). $\sum_i x_i^2$ portf.minES.EqRB <- add.objective(portf.minES, type="risk_budget", name="ES", min_concentration=TRUE) # relax the box constraint @@ -233,7 +234,7 @@ } else { # Run the optimization opt.minES <- optimize.portfolio(R, portf, optimize_method="DEoptim", - search_size=2000, trace=TRUE, traceDE=0, + search_size=5000, trace=TRUE, traceDE=0, message=TRUE) cat("opt.minES complete. Saving results to ", results.dir, "\n") save(opt.minES, file=paste(results.dir, "opt.minES.rda", sep="/")) @@ -259,6 +260,7 @@ rebalance_on=rebal.freq, training_period=training, trailing_periods=trailing, + search_size=5000, traceDE=0, message=TRUE) cat("bt.opt.minES complete. Saving results to ", results.dir, "\n") save(bt.opt.minES, file=paste(results.dir, "bt.opt.minES.rda", sep="/")) @@ -299,7 +301,7 @@ min=0.05, max=0.4) portf.crra <- add.objective(portf.crra, type="return", - name="CRRA", arguments=list(lambda=5)) + name="CRRA", arguments=list(lambda=10)) # I just want these for plotting # Set multiplier=0 so that it is calculated, but does not affect the optimization @@ -336,6 +338,85 @@ save(bt.opt.crra, file=paste(results.dir, "bt.opt.crra.rda", sep="/")) } +##### RP Demo ##### +cat("Random portfolio method comparison\n") +if(file.exists("optimization_figures/rp_plot.png")){ + cat("file already exists\n") +} else { + portf.lo <- portfolio.spec(colnames(R)) + portf.lo <- add.constraint(portf.lo, type="weight_sum", + min_sum=0.99, max_sum=1.01) + + portf.lo <- add.constraint(portf.lo, type="long_only") + + # Use the long only portfolio previously created + # Generate random portfolios using the 3 methods + rp1 <- random_portfolios(portf.lo, permutations=5000, + rp_method='sample') + rp2 <- random_portfolios(portf.lo, permutations=5000, + rp_method='simplex') + rp3 <- random_portfolios(portf.lo, permutations=5000, + rp_method='grid') + + # Calculate the portfolio mean return and standard deviation + rp1_mean <- apply(rp1, 1, function(x) mean(R %*% x)) + rp1_StdDev <- apply(rp1, 1, function(x) StdDev(R, weights=x)) + rp2_mean <- apply(rp2, 1, function(x) mean(R %*% x)) + rp2_StdDev <- apply(rp2, 1, function(x) StdDev(R, weights=x)) + rp3_mean <- apply(rp3, 1, function(x) mean(R %*% x)) + rp3_StdDev <- apply(rp3, 1, function(x) StdDev(R, weights=x)) + + x.assets <- StdDev(R) + y.assets <- colMeans(R) + + x.lower <- min(x.assets) * 0.9 + x.upper <- max(x.assets) * 1.1 + y.lower <- min(y.assets) * 0.9 + y.upper <- max(y.assets) * 1.1 + + png("optimization_figures/rp_plot.png") + # plot feasible portfolios + plot(x=rp1_StdDev, y=rp1_mean, col="gray", main="Random Portfolio Methods", + ylab="mean", xlab="StdDev", xlim=c(x.lower, x.upper), + ylim=c(y.lower, y.upper)) + points(x=rp2_StdDev, y=rp2_mean, col="red", pch=2) + points(x=rp3_StdDev, y=rp3_mean, col="green", pch=5) + points(x=x.assets, y=y.assets) + text(x=x.assets, y=y.assets, labels=colnames(R), pos=4, cex=0.8) + legend("bottomright", legend=c("sample", "simplex", "grid"), + col=c("gray", "red", "green"), + pch=c(1, 2, 5), bty="n") + dev.off() +} + +cat("Random portfolio simplex method fev biasing\n") +if(file.exists("optimization_figures/fev_plot.png")){ + cat("file already exists\n") +} else { + png("optimization_figures/fev_plot.png") + fev <- 0:5 + x.assets <- StdDev(R) + y.assets <- colMeans(R) + par(mfrow=c(2, 3)) + for(i in 1:length(fev)){ + rp <- rp_simplex(portfolio=portf.lo, permutations=2000, fev=fev[i]) + tmp.mean <- apply(rp, 1, function(x) mean(R %*% x)) + tmp.StdDev <- apply(rp, 1, function(x) StdDev(R=R, weights=x)) + x.lower <- min(c(tmp.StdDev, x.assets)) * 0.85 + x.upper <- max(c(tmp.StdDev, x.assets)) * 1.15 + y.lower <- min(c(tmp.mean, y.assets)) * 0.85 + y.upper <- max(c(tmp.mean, y.assets)) * 1.15 + plot(x=tmp.StdDev, y=tmp.mean, main=paste("FEV =", fev[i]), + ylab="mean", xlab="StdDev", col=rgb(0, 0, 100, 50, maxColorValue=255), + xlim=c(x.lower, x.upper), + ylim=c(y.lower, y.upper)) + points(x=x.assets, y=y.assets) + text(x=x.assets, y=y.assets, labels=colnames(R), pos=4, cex=0.8) + } + par(mfrow=c(1,1)) + dev.off() +} + # # Calculate the turnover per period # turnover.rebalancing <- function(object){ # weights <- extractWeights(object) Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd 2014-04-11 05:50:24 UTC (rev 3363) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd 2014-04-12 04:49:50 UTC (rev 3364) @@ -2,23 +2,15 @@ % Ross Bennett % May 16, 2014 - - -```{r, echo=FALSE} -library(knitr) -opts_chunk$set(fig.height=4.5, fig.cap="", tidy=FALSE, cache=TRUE) -``` - - # Portfolio Optimization ## General TODO: Add some general comments here about goals and pitfalls of optimization in the context of constructing a portfolio. + + ## Modern Portfolio Theory "Modern" Portfolio Theory (MPT) was introduced by Harry Markowitz in 1952. @@ -32,14 +24,17 @@ How do we define risk? + + ## Portfolio Optimization Objectives * Minimize Risk * Volatility * Tail Loss (VaR, ES) * Other Downside Risk Measure * Maximize Risk Adjusted Return - * Sharpe Ratio - * Modified Sharpe Ratio + * Sharpe Ratio, Modified Sharpe Ratio * Several Others * Risk Budgets * Equal Component Contribution to Risk (i.e. Risk Parity) @@ -47,20 +42,23 @@ * Maximize a Utility Function * Quadratic, CRRA, CARA, etc. + + # PortfolioAnalytics ## Overview PortfolioAnalytics is an R package designed to provide numerical solutions and visualizations for portfolio optimization problems with complex constraints and objectives. -## Key Features - * Support for multiple constraint and objective types +* An objective function can be any valid R function * Modular constraints and objectives -* An objective function can be any valid R function -* Custom moments +* Support for user defined moment functions +* Visualizations * Solver agnostic -* Visualizations +* Support for parallel computing + ## Random Portfolios -TODO: Add graphic comparing the three methods +PortfolioAnalytics has three methods to generate random portfolios. +1. The **sample** method to generate random portfolios is based on an idea by Pat Burns. +2. The **simplex** method to generate random portfolios is based on a paper by W. T. Shaw. +3. The **grid** method to generate random portfolios is based on the `gridSearch` function in the NMOF package. + + + +## Comparison of Random Portfolio Methods +![](optimization_figures/rp_plot.png) + ## Random Portfolios: Simplex Method -TODO: Add graphic with different fev biasing values +![](optimization_figures/fev_plot.png) + ## Workflow TODO: Add a nice graphic here (Guy might have one) @@ -119,8 +137,14 @@ * 15 Mid Cap * 5 Small Cap +```{r, eval=FALSE, tidy=FALSE} +equity.data <- cbind(largecap_weekly[,1:15], + midcap_weekly[,1:15], + smallcap_weekly[,1:5]) +``` + ## Distribution of Monthly Returns -![alt text](data_figures/equity_box.png) +![](data_figures/equity_box.png) ## Minimum Variance Portfolio Consider a portfolio of stocks. Our objective to minimize portfolio variance subect to full investment and box constraints. We will use out of sample backtesting to compare the sample covariance matrix estimate and a Ledoit-Wolf shinkage estimate. @@ -129,19 +153,20 @@ Demonstrate a custom moments function to compare a sample covariance matrix estimate and a Ledoit-Wolf shrinkage covariance matrix estimate. An alternative is a robust (MCD, MVE, etc.) estimate, DCC GARCH model, factor model, etc. --> -## Data -```{r, eval=FALSE} -equity.data <- cbind(largecap_weekly[,1:15], - midcap_weekly[,1:15], - smallcap_weekly[,1:5]) -``` - ## Specify Portfolio ```{r,eval=FALSE} +# Specify an initial portfolio stocks <- colnames(equity.data) portf.init <- portfolio.spec(stocks) + +# Add full investment constraint such that the weights sum to 1 portf.minvar <- add.constraint(portf.init, type="full_investment") + +# Add box constraint such that no asset can have a weight of greater than +# 20% or less than 1% portf.minvar <- add.constraint(portf.minvar, type="box", min=0.01, max=0.2) + +# Add objective to minimize portfolio variance portf.minvar <- add.objective(portf.minvar, type="risk", name="var") ``` @@ -152,9 +177,9 @@ ## Ledoit-Wolf Shrinkage Estimate The default function for `momentFUN` is `set.portfolio.moments`. We need to write our own function to estimate the covariance matrix. ```{r, eval=FALSE} +# Function to estimate covariance matrix via Ledoit-Wolf shrinkage lw.sigma <- function(R, ...){ out <- list() - # estimate covariance matrix via ledoit-wolf shrinkage out$sigma <- lwShrink(R)$cov return(out) } @@ -164,20 +189,27 @@ ```{r, eval=FALSE} # Set rebalancing frequency rebal.freq <- "quarters" + # Training Period training <- 400 + # Trailing Period trailing <- 250 ``` + - ## Run Optimization -```{r, eval=FALSE} +```{r, eval=FALSE, tidy=FALSE} +# Backtest using sample covariance matrix estimate opt.minVarSample <- optimize.portfolio.rebalancing(equity.data, portf.minvar, optimize_method="ROI", rebalance_on=rebal.freq, training_period=training, trailing_periods=trailing) + +# Backtest using Ledoit-Wolf shrinkage covariance matrix estimate opt.minVarLW <- optimize.portfolio.rebalancing(equity.data, portf.minvar, optimize_method="ROI", momentFUN=lw.sigma, @@ -186,20 +218,16 @@ trailing_periods=trailing) ``` -## Chart Weights +## Chart Weights Through Time ```{r, eval=FALSE} chart.Weights(opt.minVarSample, main="minVarSample Weights", legend.loc=NULL) chart.Weights(opt.minVarLW, main="minVarLW Weights", legend.loc=NULL) ``` +![](optimization_figures/weights_minVarSample.png) +![](optimization_figures/weights_minVarLW.png) -## Sample Estimate -![alt text](optimization_figures/weights_minVarSample.png) - -## Ledoit-Wolf Shrinkage Estimate -![alt text](optimization_figures/weights_minVarLW.png) - ## Returns -Compute the rebalancing returns and chart the performance summary +Compute the portfolio rebalancing returns and chart the performance. ```{r, eval=FALSE} ret.minVarSample <- summary(opt.minVarSample)$portfolio_returns ret.minVarRobust <- summary(opt.minVarLW)$portfolio_returns @@ -209,46 +237,79 @@ ``` ## Performance Summary -![alt text](optimization_figures/ret_minVar.png) +![](optimization_figures/ret_minVar.png) # Example 2 ## Market Neutral Portfolio -Consider a portfolio of stocks. Our objective to maximize portfolio return and minimize portfolio StdDev with a target of 0.02 subject to Dollar neutral, beta neutral, box, and position limit constraints. We will use the same data considered in example 1. +Here we consider a portfolio of stocks. Our objective is to maximize portfolio return with a target of 0.0015 and minimize portfolio StdDev with a target of 0.02 subject to dollar neutral, beta, box, and position limit constraints. We will use the same data considered in Example 1. + + ## Specify Portfolio: Contraints ```{r, eval=FALSE, tidy=FALSE} portf.init <- portfolio.spec(stocks) + +# Add constraint such that the portfolio weights sum to 0* portf.dn <- add.constraint(portf.init, type="weight_sum", min_sum=-0.01, max_sum=0.01) + +# Add box constraint such that no asset can have a weight of greater than +# 20% or less than -20% portf.dn <- add.constraint(portf.dn, type="box", min=-0.2, max=0.2) + +# Add constraint such that we have at most 20 positions portf.dn <- add.constraint(portf.dn, type="position_limit", max_pos=20) + +# Compute the betas of each stock betas <- t(CAPM.beta(equity.data, market, Rf)) + +# Add constraint such that the portfolio beta is between -0.25 and 0.25 portf.dn <- add.constraint(portf.dn, type="factor_exposure", B=betas, - lower=-0.5, upper=0.5) + lower=-0.25, upper=0.25) ``` + + ## Specify Portfolio: Objectives ```{r,eval=FALSE, tidy=FALSE} -portf.dn.StdDev <- add.objective(portf.dn, type="return", name="mean") +# Add objective to maximize portfolio return with a target of 0.0015 +portf.dn.StdDev <- add.objective(portf.dn, type="return", name="mean", + target=0.0015) + +# Add objective to minimize portfolio StdDev with a target of 0.02 portf.dn.StdDev <- add.objective(portf.dn.StdDev, type="risk", name="StdDev", target=0.02) ``` + + ## Run Optimization ```{r, eval=FALSE, tidy=FALSE} +# Generate random portfolios rp <- random_portfolios(portf.dn, 10000, "sample", eliminate=TRUE) +# Run the optimization opt.dn <- optimize.portfolio(equity.data, portf.dn.StdDev, optimize_method="random", rp=rp, trace=TRUE) ``` + + ## Plot Results ```{r, eval=FALSE, tidy=FALSE} plot(opt.dn, main="Dollar Neutral Portfolio", risk.col="StdDev", neighbors=10) ``` -![alt text](optimization_figures/opt_dn.png) +![](optimization_figures/opt_dn.png) # Example 3 @@ -265,55 +326,78 @@ * Emerging Markets (EM) * Global Macro (GM) +## Data +```{r, eval=FALSE, tidy=FALSE} +R <- edhec[,c("Convertible.Arbitrage", "Equity.Market.Neutral", + "Fixed.Income.Arbitrage", + "CTA.Global", "Emerging.Markets", "Global.Macro")] +# Abreviate column names for convenience and plotting +colnames(R) <- c("CA", "EMN", "FIA", "CTAG", "EM", "GM") +``` ## Monthly Returns -![alt text](data_figures/relative_barvar.png) -![alt text](data_figures/directional_barvar.png) +![](data_figures/relative_barvar.png) +![](data_figures/directional_barvar.png) ## Distribution of Monthly Returns -![alt text](data_figures/edhec_box.png) +![](data_figures/edhec_box.png) ## Minimum Expected Shortfall -Consider an allocation to hedge funds using the EDHEC-Risk Alternative Index as a proxy. This will be an extended example starting with an objective to minimize portfolio expected shortfall, then risk budget percent contribution limit, then equal risk contribution limit. +Consider an allocation to hedge funds using the EDHEC-Risk Alternative Index as a proxy. This will be an extended example starting with an objective to minimize modified expected shortfall, then add risk budget percent contribution limit, and finally add equal risk contribution limit. + * Minimize Expected Shortfall * Minimize Expected Shortfall with Risk Budget Limit * Minimize Expected Shortfall with Equal Risk Contribution -Add risk budget objective to minimize concentration of percentage component contribution to risk. Concentration is defined as the Herfindahl-Hirschman Index (HHI). $\sum_{i=1}^n x_i^2$ +Add risk budget objective to minimize concentration of percentage component contribution to risk. Concentration is defined as the Herfindahl-Hirschman Index (HHI). $\sum_i x_i^2$ -## Data -```{r, eval=FALSE} -R <- edhec[,c("Convertible.Arbitrage", "Equity.Market.Neutral", - "Fixed.Income.Arbitrage", - "CTA.Global", "Emerging.Markets", "Global.Macro")] -# Abreviate column names for convenience and plotting -colnames(R) <- c("CA", "EMN", "FIA", "CTAG", "EM", "GM") -``` + ## Specify Initial Portfolio ```{r, eval=FALSE, tidy=FALSE} +# Specify an initial portfolio funds <- colnames(R) portf.init <- portfolio.spec(funds) + +# Add constraint such that the weights sum to 1* portf.init <- add.constraint(portf.init, type="weight_sum", min_sum=0.99, max_sum=1.01) + +# Add box constraint such that no asset can have a weight of greater than +# 40% or less than 5% portf.init <- add.constraint(portf.init, type="box", min=0.05, max=0.4) + +# Add return objective with multiplier=0 such that the portfolio mean +# return is calculated, but does not impact optimization portf.init <- add.objective(portf.init, type="return", name="mean", multiplier=0) ``` + + ## Add Objectives ```{r, eval=FALSE, tidy=FALSE} +# Add objective to minimize expected shortfall portf.minES <- add.objective(portf.init, type="risk", name="ES") +# Add objective to set upper bound on percentage component contribution portf.minES.RB <- add.objective(portf.minES, type="risk_budget", - name="ES", max_prisk=0.2) + name="ES", max_prisk=0.3) +# Relax box constraints portf.minES.RB$constraints[[2]]$max <- rep(1,ncol(R)) +# Add objective to minimize concentration of modified ES +# component contribution portf.minES.EqRB <- add.objective(portf.minES, type="risk_budget", name="ES", min_concentration=TRUE) +# Relax box constraints portf.minES.EqRB <- add.constraint(portf.minES.EqRB, type="box", min=0.05, max=1, indexnum=2) ``` @@ -324,16 +408,22 @@ ## Run Optimization ```{r, eval=FALSE, tidy=FALSE} +# Combine the 3 portfolios portf <- combine.portfolios(list(minES=portf.minES, minES.RB=portf.minES.RB, minES.EqRB=portf.minES.EqRB)) +# Run the optimization opt.minES <- optimize.portfolio(R, portf, optimize_method="DEoptim", - search_size=2000, trace=TRUE, traceDE=0) + search_size=5000, trace=TRUE, traceDE=0) ``` + + ## Plot in Risk-Return Space -![alt text](optimization_figures/opt_minES.png) +![](optimization_figures/opt_minES.png) ## Chart Risk Budgets ```{r, eval=FALSE, tidy=FALSE} @@ -343,41 +433,40 @@ chart.RiskBudget(opt.minES[[3]], main="Equal ES Component Contribution", risk.type="percentage", neighbors=10) ``` +![](optimization_figures/rb_minES.png) +![](optimization_figures/eqrb_minES.png) -## Risk Budget 1 -![alt text](optimization_figures/rb_minES.png) - -## Risk Budget 2 -![alt text](optimization_figures/eqrb_minES.png) - -## Rebalancing Parameters +## Set Rebalancing Parameters and Run Backtest ```{r, eval=FALSE, tidy=FALSE} # Set rebalancing frequency rebal.freq <- "quarters" + # Training Period training <- 120 + # Trailing Period trailing <- 72 -``` -## Run Backtest -```{r, eval=FALSE, tidy=FALSE} bt.opt.minES <- optimize.portfolio.rebalancing(R, portf, optimize_method="DEoptim", rebalance_on=rebal.freq, training_period=training, trailing_periods=trailing, + search_size=5000, traceDE=0) ``` -## Min ES Risk Contributions Through Time -![alt text](optimization_figures/risk_minES.png) +## Min ES Risk Contributions and Weights Through Time +![](optimization_figures/risk_minES.png) +![](optimization_figures/weights_minES.png) -## Min ES Risk Budget Limit Risk Contributions Through Time -![alt text](optimization_figures/risk_minESRB.png) +## Min ES Risk Budget Limit Risk Contributions and Weights Through Time +![](optimization_figures/risk_minESRB.png) +![](optimization_figures/weights_minESRB.png) -## Min ES Equal Component Contribution Risk Contributions Through Time -![alt text](optimization_figures/risk_minESEqRB.png) +## Min ES Equal Component Contribution Risk Contributions and Weights Through Time +![](optimization_figures/risk_minESEqRB.png) +![](optimization_figures/weights_minESEqRB.png) ## Compute Returns and Chart Performance @@ -387,27 +476,28 @@ colnames(ret.bt.opt) <- c("min ES", "min ES RB", "min ES Eq RB") charts.PerformanceSummary(ret.bt.opt) ``` -![alt text](optimization_figures/ret_minES.png) +![](optimization_figures/ret_minES.png) # Example 4 ## Maximize CRRA -Consider an allocation to hedge funds using the EDHEC-Risk Alternative Index as a proxy. Our objective to maximize the fourth order expansion of the Constant Relative Risk Aversion (CRRA) expected utility function as in the Boudt paper and Martinelli paper. +Consider an allocation to hedge funds using the EDHEC-Risk Alternative Index as a proxy. Our objective to maximize the fourth order expansion of the Constant Relative Risk Aversion (CRRA) expected utility function as in the Boudt paper and Martinelli paper. We use the same data as Example 3. +TODO: Add equation + -## CRRA -TODO: Add equation +## Define a function to compute CRRA ```{r, eval=FALSE, tidy=FALSE} CRRA <- function(R, weights, lambda, sigma, m3, m4){ weights <- matrix(weights, ncol=1) M2.w <- t(weights) %*% sigma %*% weights M3.w <- t(weights) %*% m3 %*% (weights %x% weights) M4.w <- t(weights) %*% m4 %*% (weights %x% weights %x% weights) - term1 <- 0.5 * lambda * M2.w + term1 <- (1 / 2) * lambda * M2.w term2 <- (1 / 6) * lambda * (lambda + 1) * M3.w term3 <- (1 / 24) * lambda * (lambda + 1) * (lambda + 2) * M4.w out <- -term1 + term2 - term3 @@ -418,15 +508,27 @@ ## Specify Portfolio ```{r, eval=FALSE, tidy=FALSE} +# Specify portfolio portf.crra <- portfolio.spec(funds) + +# Add constraint such that the weights sum to 1 portf.crra <- add.constraint(portf.crra, type="weight_sum", min_sum=0.99, max_sum=1.01) + +# Add box constraint such that no asset can have a weight of greater than +# 40% or less than 5% portf.crra <- add.constraint(portf.crra, type="box", min=0.05, max=0.4) + +# Add objective to maximize CRRA portf.crra <- add.objective(portf.crra, type="return", - name="CRRA", arguments=list(lambda=5)) + name="CRRA", arguments=list(lambda=10)) ``` + + ## Run Optimization ```{r, eval=FALSE, tidy=FALSE} opt.crra <- optimize.portfolio(R, portf.crra, optimize_method="DEoptim", @@ -434,10 +536,15 @@ momentFUN="crra.moments") ``` + + ## Chart Results -![alt text](optimization_figures/crra_RR.png) +![](optimization_figures/crra_RR_ES.png) +![](optimization_figures/crra_RR_StdDev.png) -## Backtest +## Run Backtest and Compute Returns ```{r, eval=FALSE, tidy=FALSE} bt.opt.crra <- optimize.portfolio.rebalancing(R, portf.crra, optimize_method="DEoptim", @@ -447,16 +554,21 @@ rebalance_on=rebal.freq, training_period=training, trailing_periods=trailing) + +ret.crra <- summary(bt.opt.crra)$portfolio_returns +colnames(ret.crra) <- "CRRA" ``` -## Compute Returns and Chart Performance + + +## Chart Performance ```{r, eval=FALSE, tidy=FALSE} -ret.crra <- summary(bt.opt.crra)$portfolio_returns -colnames(ret.crra) <- "CRRA" charts.PerformanceSummary(cbind(ret.bt.opt, ret.crra), main="Optimization Performance") ``` -![alt text](optimization_figures/ret_crra.png) +![](optimization_figures/ret_crra.png) # Conclusion @@ -474,6 +586,19 @@ - Google for funding the Google Summer of Code for PortfolioAnalytics and many other proposals for R --> +## References [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/returnanalytics -r 3364 From noreply at r-forge.r-project.org Mon Apr 14 03:59:40 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 14 Apr 2014 03:59:40 +0200 (CEST) Subject: [Returnanalytics-commits] r3365 - pkg/PortfolioAnalytics/sandbox/RFinance2014 Message-ID: <20140414015941.27A14187353@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-14 03:59:38 +0200 (Mon, 14 Apr 2014) New Revision: 3365 Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.md pkg/PortfolioAnalytics/sandbox/RFinance2014/slidy_presentation.html Log: minor updates to presentation Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd 2014-04-12 04:49:50 UTC (rev 3364) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd 2014-04-14 01:59:38 UTC (rev 3365) @@ -2,15 +2,13 @@ % Ross Bennett % May 16, 2014 +# Overview +* Discuss Portfolio Optimization +* Introduce PortfolioAnalytics +* Demonstrate PortfolioAnalytics with Examples + # Portfolio Optimization -## General -TODO: Add some general comments here about goals and pitfalls of optimization in the context of constructing a portfolio. - - - ## Modern Portfolio Theory "Modern" Portfolio Theory (MPT) was introduced by Harry Markowitz in 1952. @@ -20,12 +18,11 @@ * Maximize a measure of gain per unit measure of risk * Minimize a measure of risk -* Maximize a utility function -How do we define risk? +How do we define risk? What about more complex objectives? ## Portfolio Optimization Objectives @@ -43,7 +40,7 @@ * Quadratic, CRRA, CARA, etc. # PortfolioAnalytics @@ -66,7 +63,10 @@ - The multiple types and modularity of constraints and objectives allows us to add, remove, combine, etc. multiple constraint and objective types very easily. - Define an objective as any valid R function - Define a function to compute the moments (sample, robust, shrinkage, factor model, GARCH model, etc.) + - Estimation error is a significant concern with optimization. Having the ability to test different models with different parameters is critical. - PortfolioAnalytics comes "pre-built" with several constraint types. +- Visualization helps to build intuition about the problem and understand the feasible space of portfolios +- Periodic rebalancing and analyzing out of sample performance will help refine objectives and constraints --> @@ -98,6 +98,8 @@ 3. The **grid** method to generate random portfolios is based on the `gridSearch` function in the NMOF package. ## Specify Portfolio ```{r, eval=FALSE, tidy=FALSE} @@ -587,18 +592,14 @@ --> ## References -* TODO: Add relevant links and references -* ROI -* DEoptim -* pso -* GenSA -* PerformanceAnalytics +* [ROI](http://cran.r-project.org/web/packages/ROI/index.html) +* [DEoptim](http://cran.r-project.org/web/packages/DEoptim/index.html) +* [pso](http://cran.r-project.org/web/packages/pso/index.html) +* [GenSA](http://cran.r-project.org/web/packages/GenSA/index.html) +* [PerformanceAnalytics](http://cran.r-project.org/web/packages/PerformanceAnalytics/index.html) * Pat Burns Random Portfolios * W.T. Shaw Random Portfolios * Martinelli paper * Boudt paper -* PortfolioAnalytics on R-Forge +* [PortfolioAnalytics on R-Forge](https://r-forge.r-project.org/projects/returnanalytics/) * Shiny App? - - - Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.md =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.md 2014-04-12 04:49:50 UTC (rev 3364) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.md 2014-04-14 01:59:38 UTC (rev 3365) @@ -2,15 +2,13 @@ % Ross Bennett % May 16, 2014 +# Overview +* Discuss Portfolio Optimization +* Introduce PortfolioAnalytics +* Demonstrate PortfolioAnalytics with Examples + # Portfolio Optimization -## General -TODO: Add some general comments here about goals and pitfalls of optimization in the context of constructing a portfolio. - - - ## Modern Portfolio Theory "Modern" Portfolio Theory (MPT) was introduced by Harry Markowitz in 1952. @@ -20,12 +18,11 @@ * Maximize a measure of gain per unit measure of risk * Minimize a measure of risk -* Maximize a utility function -How do we define risk? +How do we define risk? What about more complex objectives? ## Portfolio Optimization Objectives @@ -43,7 +40,7 @@ * Quadratic, CRRA, CARA, etc. # PortfolioAnalytics @@ -66,7 +63,10 @@ - The multiple types and modularity of constraints and objectives allows us to add, remove, combine, etc. multiple constraint and objective types very easily. - Define an objective as any valid R function - Define a function to compute the moments (sample, robust, shrinkage, factor model, GARCH model, etc.) + - Estimation error is a significant concern with optimization. Having the ability to test different models with different parameters is critical. - PortfolioAnalytics comes "pre-built" with several constraint types. +- Visualization helps to build intuition about the problem and understand the feasible space of portfolios +- Periodic rebalancing and analyzing out of sample performance will help refine objectives and constraints --> @@ -98,6 +98,8 @@ 3. The **grid** method to generate random portfolios is based on the `gridSearch` function in the NMOF package. ## Specify Portfolio @@ -633,18 +638,14 @@ --> ## References -* TODO: Add relevant links and references -* ROI -* DEoptim -* pso -* GenSA -* PerformanceAnalytics +* [ROI](http://cran.r-project.org/web/packages/ROI/index.html) +* [DEoptim](http://cran.r-project.org/web/packages/DEoptim/index.html) +* [pso](http://cran.r-project.org/web/packages/pso/index.html) +* [GenSA](http://cran.r-project.org/web/packages/GenSA/index.html) +* [PerformanceAnalytics](http://cran.r-project.org/web/packages/PerformanceAnalytics/index.html) * Pat Burns Random Portfolios * W.T. Shaw Random Portfolios * Martinelli paper * Boudt paper -* PortfolioAnalytics on R-Forge +* [PortfolioAnalytics on R-Forge](https://r-forge.r-project.org/projects/returnanalytics/) * Shiny App? - - - Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/slidy_presentation.html =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/slidy_presentation.html 2014-04-12 04:49:50 UTC (rev 3364) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/slidy_presentation.html 2014-04-14 01:59:38 UTC (rev 3365) @@ -42,30 +42,30 @@

May 16, 2014

-

Portfolio Optimization

-

General

-

TODO: Add some general comments here about goals and pitfalls of optimization in the context of constructing a portfolio.

- - -
-

Modern Portfolio Theory

+
+

Overview

+ +
+
+

Portfolio Optimization

+

Modern Portfolio Theory

"Modern" Portfolio Theory (MPT) was introduced by Harry Markowitz in 1952.

In general, MPT states that an investor's objective is to maximize portfolio expected return for a given amount of risk.

General Objectives

-

How do we define risk?

+

How do we define risk? What about more complex objectives?

-
-

Portfolio Optimization Objectives

+

Portfolio Optimization Objectives

-

PortfolioAnalytics

-

Overview

+
+

PortfolioAnalytics

+

Overview

PortfolioAnalytics is an R package designed to provide numerical solutions and visualizations for portfolio optimization problems with complex constraints and objectives.

  • Support for multiple constraint and objective types
  • @@ -111,12 +112,14 @@ - The multiple types and modularity of constraints and objectives allows us to add, remove, combine, etc. multiple constraint and objective types very easily. - Define an objective as any valid R function - Define a function to compute the moments (sample, robust, shrinkage, factor model, GARCH model, etc.) + - Estimation error is a significant concern with optimization. Having the ability to test different models with different parameters is critical. - PortfolioAnalytics comes "pre-built" with several constraint types. +- Visualization helps to build intuition about the problem and understand the feasible space of portfolios +- Periodic rebalancing and analyzing out of sample performance will help refine objectives and constraints --> -
-

Support Multiple Solvers

+

Support Multiple Solvers

Linear and Quadratic Programming Solvers

  • R Optimization Infrastructure (ROI) @@ -137,8 +140,7 @@ Brief explanation of each solver and what optimization problems (constraints and objectives) are supported --> -
-

Random Portfolios

+

Random Portfolios

PortfolioAnalytics has three methods to generate random portfolios.

  1. The sample method to generate random portfolios is based on an idea by Pat Burns.
  2. @@ -146,6 +148,8 @@
  3. The grid method to generate random portfolios is based on the gridSearch function in the NMOF package.
-
-

Comparison of Random Portfolio Methods

+

Comparison of Random Portfolio Methods

-
-

Random Portfolios: Simplex Method

+

Random Portfolios: Simplex Method

-
-

Workflow

+

Workflow

TODO: Add a nice graphic here (Guy might have one)

Specify a Portfolio --> Add Constraints --> Add Objectives --> Run Optimization --> Analyze Results

-
-

Specify Portfolio

+

Specify Portfolio

# Specify an initial portfolio
 stocks <- colnames(equity.data)
 portf.init <- portfolio.spec(stocks)
@@ -221,8 +220,7 @@
 Talk a little about adding constraints and objectives
 -->
 
-
-

Ledoit-Wolf Shrinkage Estimate

+

Ledoit-Wolf Shrinkage Estimate

The default function for momentFUN is set.portfolio.moments. We need to write our own function to estimate the covariance matrix.

# Function to estimate covariance matrix via Ledoit-Wolf shrinkage
 lw.sigma <- function(R, ...) {
@@ -230,8 +228,7 @@
     out$sigma <- lwShrink(R)$cov
     return(out)
 }
-
-

Backtesting Parameters

+

Backtesting Parameters

# Set rebalancing frequency
 rebal.freq <- "quarters"
 
@@ -244,8 +241,7 @@
 Explain each of the rebalancing parameters
 -->
 
-
-

Run Optimization

+

Run Optimization

# Backtest using sample covariance matrix estimate
 opt.minVarSample <- optimize.portfolio.rebalancing(equity.data, portf.minvar, 
                                                    optimize_method="ROI", 
@@ -260,34 +256,31 @@
                                                rebalance_on=rebal.freq, 
                                                training_period=training, 
                                                trailing_periods=trailing)
-
-

Chart Weights Through Time

+

Chart Weights Through Time

chart.Weights(opt.minVarSample, main = "minVarSample Weights", legend.loc = NULL)
 chart.Weights(opt.minVarLW, main = "minVarLW Weights", legend.loc = NULL)

-
-

Returns

+

Returns

Compute the portfolio rebalancing returns and chart the performance.

ret.minVarSample <- summary(opt.minVarSample)$portfolio_returns
 ret.minVarRobust <- summary(opt.minVarLW)$portfolio_returns
 ret.minVar <- cbind(ret.minVarSample, ret.minVarRobust)
 colnames(ret.minVar) <- c("Sample", "LW")
 charts.PerformanceSummary(ret.minVar)
-
-

Performance Summary

+

Performance Summary

-

Example 2

-

Market Neutral Portfolio

+
+

Example 2

+

Market Neutral Portfolio

Here we consider a portfolio of stocks. Our objective is to maximize portfolio return with a target of 0.0015 and minimize portfolio StdDev with a target of 0.02 subject to dollar neutral, beta, box, and position limit constraints. We will use the same data considered in Example 1.

-
-

Specify Portfolio: Contraints

+

Specify Portfolio: Contraints

portf.init <- portfolio.spec(stocks)
 
 # Add constraint such that the portfolio weights sum to 0*
@@ -311,8 +304,7 @@
 explain the constraints
 -->
 
-
-

Specify Portfolio: Objectives

+

Specify Portfolio: Objectives

# Add objective to maximize portfolio return with a target of 0.0015
 portf.dn.StdDev <- add.objective(portf.dn, type="return", name="mean",
                                  target=0.0015)
@@ -324,8 +316,7 @@
 explain the objectives, specifically the target
 -->
 
-
-

Run Optimization

+

Run Optimization

# Generate random portfolios
 rp <- random_portfolios(portf.dn, 10000, "sample", eliminate=TRUE)
 
@@ -337,15 +328,15 @@
 generate a set of random portfolios and then pass directly to optimize.portfolio. Could just specify optimize_method = "random" and will automatically generate for you.
 -->
 
-
-

Plot Results

+

Plot Results

plot(opt.dn, main="Dollar Neutral Portfolio", risk.col="StdDev", neighbors=10)
-

Example 3

-

Data Setup

+
+

Example 3

+

Data Setup

Here we will look at portfolio optimization in the context of portfolio of hedge funds.

  • EDHEC-Risk Alternative Indexes
  • @@ -359,23 +350,19 @@
  • Global Macro (GM)
-
-

Data

+

Data

R <- edhec[,c("Convertible.Arbitrage", "Equity.Market.Neutral", 
               "Fixed.Income.Arbitrage", 
               "CTA.Global", "Emerging.Markets", "Global.Macro")]
 # Abreviate column names for convenience and plotting
 colnames(R) <- c("CA", "EMN", "FIA", "CTAG", "EM", "GM")
-
-

Monthly Returns

+

Monthly Returns

-
-

Distribution of Monthly Returns

+

Distribution of Monthly Returns

-
-

Minimum Expected Shortfall

+

Minimum Expected Shortfall

Consider an allocation to hedge funds using the EDHEC-Risk Alternative Index as a proxy. This will be an extended example starting with an objective to minimize modified expected shortfall, then add risk budget percent contribution limit, and finally add equal risk contribution limit.

  • Minimize Expected Shortfall
  • @@ -387,8 +374,7 @@ comments --> -
-

Specify Initial Portfolio

+

Specify Initial Portfolio

# Specify an initial portfolio
 funds <- colnames(R)
 portf.init <- portfolio.spec(funds)
@@ -410,8 +396,7 @@
 basic comments about setting up an initial portfolio
 -->
 
-
-

Add Objectives

+

Add Objectives

# Add objective to minimize expected shortfall
 portf.minES <- add.objective(portf.init, type="risk", name="ES")
 
@@ -433,8 +418,7 @@
 -->
 
 
-
-

Run Optimization

+

Run Optimization

# Combine the 3 portfolios
 portf <- combine.portfolios(list(minES=portf.minES, 
                                  minES.RB=portf.minES.RB, 
@@ -447,21 +431,18 @@
 explain how portf is a list of portfolios and passed to optimize.portfolio
 -->
 
-
-

Plot in Risk-Return Space

+

Plot in Risk-Return Space

-
-

Chart Risk Budgets

+

Chart Risk Budgets

chart.RiskBudget(opt.minES[[2]], main="Risk Budget Limit", 
                  risk.type="percentage", neighbors=10)
 
 chart.RiskBudget(opt.minES[[3]], main="Equal ES Component Contribution", 
                  risk.type="percentage", neighbors=10)

-
-

Set Rebalancing Parameters and Run Backtest

+

Set Rebalancing Parameters and Run Backtest

# Set rebalancing frequency
 rebal.freq <- "quarters"
 
@@ -478,17 +459,13 @@
                                                trailing_periods=trailing,
                                                search_size=5000,
                                                traceDE=0)
-
-

Min ES Risk Contributions and Weights Through Time

+

Min ES Risk Contributions and Weights Through Time

-
-

Min ES Risk Budget Limit Risk Contributions and Weights Through Time

+

Min ES Risk Budget Limit Risk Contributions and Weights Through Time

-
-

Min ES Equal Component Contribution Risk Contributions and Weights Through Time

[TRUNCATED] To get the complete diff run: svnlook diff /svnroot/returnanalytics -r 3365 From noreply at r-forge.r-project.org Mon Apr 14 23:09:50 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 14 Apr 2014 23:09:50 +0200 (CEST) Subject: [Returnanalytics-commits] r3366 - pkg/PortfolioAnalytics/man Message-ID: <20140414210950.A926B183A10@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-14 23:09:50 +0200 (Mon, 14 Apr 2014) New Revision: 3366 Modified: pkg/PortfolioAnalytics/man/PortfolioAnalytics-package.Rd Log: Updates to package Rd file. Minor edits and adding package dependencies section. Modified: pkg/PortfolioAnalytics/man/PortfolioAnalytics-package.Rd =================================================================== --- pkg/PortfolioAnalytics/man/PortfolioAnalytics-package.Rd 2014-04-14 01:59:38 UTC (rev 3365) +++ pkg/PortfolioAnalytics/man/PortfolioAnalytics-package.Rd 2014-04-14 21:09:50 UTC (rev 3366) @@ -7,39 +7,63 @@ } \description{ -\kbd{PortfolioAnalytics} provides an \R packaged to provide numerical solutions for portfolio problems with complex constraints and objective sets. The goal of the package is to aid practicioners and researchers in solving portfolio optimization problems with complex constraints and objectives that mirror real-world applications. +\kbd{PortfolioAnalytics} is an \R package to provide numerical solutions for portfolio problems with complex constraints and objective sets. The goal of the package is to aid practicioners and researchers in solving portfolio optimization problems with complex constraints and objectives that mirror real-world applications. -One of the goals of the packages is to provide a common interface to specify constraints and objectives that can be solved by any supported solver (i.e. optimization method). Currently supported optimization methods include random portfolios, differential evolution, particle swarm optimization, generalized simulated annealing, and linear and quadratic programming routines. Additional information on random portfolios is provided below. The differential evolution algorithm is implemented via the \kbd{DEoptim} package, the particle swarm optimization algorithm via the \kbd{pso} package, the generalized simulated annealing via the \kbd{GenSA} package, and linear and quadratic programming are implemented via the \kbd{ROI} package which acts as an interface to the \kbd{Rglpk} and \kbd{quadprog} packages. +One of the goals of the packages is to provide a common interface to specify constraints and objectives that can be solved by any supported solver (i.e. optimization method). Currently supported optimization methods include +\itemize{ + \item random portfolios + \item differential evolution + \item particle swarm optimization + \item generalized simulated annealing + \item linear and quadratic programming routines +} -A key strength of \kbd{PortfolioAnalytics} is the generalization of constraints and objectives that can be solved. The quadratic and linear programming solvers can solve a limited type of convex optimization problems. +The solver can be specified with the \code{optimize_method} argument in \code{optimize.portfolio} and \code{optimize.portfolio.rebalancing}. The \code{optimize_method} argument must be one of "random", "DEoptim", "pso", "GenSA", "ROI", "quadprog", "glpk", or "symphony". + +Additional information on random portfolios is provided below. The differential evolution algorithm is implemented via the \kbd{DEoptim} package, the particle swarm optimization algorithm via the \kbd{pso} package, the generalized simulated annealing via the \kbd{GenSA} package, and linear and quadratic programming are implemented via the \kbd{ROI} package which acts as an interface to the \kbd{Rglpk}, \kbd{Rsymphony}, and \kbd{quadprog} packages. + +A key strength of \kbd{PortfolioAnalytics} is the generalization of constraints and objectives that can be solved. + +If \code{optimize_method="ROI"} is specified, a default solver will be selected based on the optimization problem. The \code{glpk} solver is the default solver for LP and MILP optimization problems. The \code{quadprog} solver is the default solver for QP optimization problems. For example, \code{optimize_method = "quadprog"} can be specified and the optimization problem will be solved via ROI using the quadprog plugin package. + +The extension to ROI solves a limited type of convex optimization problems: \itemize{ - \item Maxmimize portfolio return subject leverage, box, group, position limit, target mean return, and/or factor exposure constraints on weights. - \item Minimize portfolio variance subject to leverage, box, group, turnover, and/or factor exposure constraints (otherwise known as global minimum variance portfolio). - \item Minimize portfolio variance subject to leverage, box, group, and/or factor exposure constraints and a desired portfolio return. - \item Maximize quadratic utility subject to leverage, box, group, target mean return, turnover, and/or factor exposure constraints and risk aversion parameter. - \item Minimize ETL subject to leverage, box, group, position limit, target mean return, and/or factor exposure constraints and target portfolio return. +\item{Maxmimize portfolio return subject leverage, box, group, position limit, target mean return, and/or factor exposure constraints on weights.} +\item{Minimize portfolio variance subject to leverage, box, group, turnover, and/or factor exposure constraints (otherwise known as global minimum variance portfolio).} +\item{Minimize portfolio variance subject to leverage, box, group, and/or factor exposure constraints and a desired portfolio return.} +\item{Maximize quadratic utility subject to leverage, box, group, target mean return, turnover, and/or factor exposure constraints and risk aversion parameter. +(The risk aversion parameter is passed into \code{optimize.portfolio} as an added argument to the \code{portfolio} object).} +\item{Maximize portfolio mean return per unit standard deviation (i.e. the Sharpe Ratio) can be done by specifying \code{maxSR=TRUE} in \code{optimize.portfolio}. +If both mean and StdDev are specified as objective names, the default action is to maximize quadratic utility, therefore \code{maxSR=TRUE} must be specified to maximize Sharpe Ratio.} +\item{Minimize portfolio ES/ETL/CVaR optimization subject to leverage, box, group, position limit, target mean return, and/or factor exposure constraints and target portfolio return.} +\item{Maximize portfolio mean return per unit ES/ETL/CVaR (i.e. the STARR Ratio) can be done by specifying \code{maxSTARR=TRUE} in \code{optimize.portfolio}. +If both mean and ES/ETL/CVaR are specified as objective names, the default action is to maximize mean return per unit ES/ETL/CVaR.} } +These problems also support a weight_concentration objective where concentration of weights as measured by HHI is added as a penalty term to the quadratic objective. -Many real-world portfolio optimization problems are global optimization problems, and therefore are not suitable for linear or quadratic programming routines. \kbd{PortfolioAnalytics} provides a random portfolio optimization method, and also utilizes the \R packages DEoptim, pso, and GenSA for solving non-convex global optimization problems. \kbd{PortfolioAnalytics} supports three methods of generating random portfolios. +Because these convex optimization problem are standardized, there is no need for a penalty term. The \code{multiplier} argument in \code{\link{add.objective}} passed into the complete constraint object are ingnored by the ROI solver. +Many real-world portfolio optimization problems are global optimization problems, and therefore are not suitable for linear or quadratic programming routines. \kbd{PortfolioAnalytics} provides a random portfolio optimization method and also utilizes the \R packages DEoptim, pso, and GenSA for solving non-convex global optimization problems. + +\kbd{PortfolioAnalytics} supports three methods of generating random portfolios. \itemize{ \item The sample method to generate random portfolios is based on an idea by Pat Burns. This is the most flexible method, but also the slowest, and can generate portfolios to satisfy leverage, box, group, and position limit constraints. - \item The simplex method to generate random portfolios is based on a paper by W. T. Shaw. The simplex method is useful to generate random portfolios with the full investment constraint, where the sum of the weights is equal to 1, and min box constraints. Values for min_sum and max_sum of the leverage constraint will be ignored, the sum of weights will equal 1. All other constraints such as the box constraint max, group and position limit constraints will be handled by elimination. If the constraints are very restrictive, this may result in very few feasible portfolios remaining. Another key point to note is that the solution may not be along the vertexes depending on the objective. For example, a risk budget objective will likely place the portfolio somewhere on the interior. + \item The simplex method to generate random portfolios is based on a paper by W. T. Shaw. The simplex method is useful to generate random portfolios with the full investment constraint (where the sum of the weights is equal to 1) and min box constraints. Values for min_sum and max_sum of the leverage constraint will be ignored, the sum of weights will equal 1. All other constraints such as the box constraint max, group and position limit constraints will be handled by elimination. If the constraints are very restrictive, this may result in very few feasible portfolios remaining. Another key point to note is that the solution may not be along the vertexes depending on the objective. For example, a risk budget objective will likely place the portfolio somewhere on the interior. \item The grid method to generate random portfolios is based on the \code{gridSearch} function in package \kbd{NMOF}. The grid search method only satisfies the min and max box constraints. The min_sum and max_sum leverage constraint will likely be violated and the weights in the random portfolios should be normalized. Normalization may cause the box constraints to be violated and will be penalized in \code{constrained_objective}. } -\kbd{PortfolioAnalytics} leverages the \kbd{PerformanceAnalytics} package for many common objective functions. The objective types in \kbd{PortfolioAnalytics} are designed to be used with \kbd{PerformanceAnalytics} functions, but any user supplied valid R function can be used as an objective. - -This summary attempts to provide an overview of how to construct a portfolio object with constraints and objectives, run the optimization, and chart the results. +\kbd{PortfolioAnalytics} leverages the \kbd{PerformanceAnalytics} package for many common objective functions. The objective types in \kbd{PortfolioAnalytics} are designed to be used with \kbd{PerformanceAnalytics} functions, but any user supplied valid \R function can be used as an objective. } \section{Optimization}{ -The portfolio object is instantiated with the \code{\link{portfolio.spec}} function. The main argument to \code{\link{portfolio.spec}} is \code{assets}. The \code{assets} argument can be a scalar value for the number of assets, a character vector of fund names, or a named vector of initial weights. +This summary attempts to provide an overview of how to construct a portfolio object with constraints and objectives, run the optimization, and chart the results. -Adding constraints to the portfolio object is done with \code{\link{add.constraint}}. The \code{\link{add.constraint}} function is the main interface for adding and/or updating constraints to the portfolio object. This function allows the user to specify the portfolio to add the constraints to, the type of constraints, arguments for the constraint, and whether or not to enable the constraint. If updating an existing constraint, the indexnum argument can be specified. +The portfolio object is initialized with the \code{\link{portfolio.spec}} function. The main argument to \code{\link{portfolio.spec}} is \code{assets}. The \code{assets} argument can be a scalar value for the number of assets, a character vector of fund names, or a named vector of initial weights. -Objectives can be added to the portfolio object with \code{\link{add.objective}}. The \code{\link{add.objective}} function is the main function for adding and/or updating objectives to the portfolio object. This function allows the user to specify the portfolio to add the objectives to, the type, name of the objective function, arguments to the objective function, and whether or not to enable the objective. If updating an existing constraint, the indexnum argument can be specified. +Adding constraints to the portfolio object is done with \code{\link{add.constraint}}. The \code{\link{add.constraint}} function is the main interface for adding and/or updating constraints to the portfolio object. This function allows the user to specify the portfolio to add the constraints to, the type of constraints, arguments for the constraint, and whether or not to enable the constraint. If updating an existing constraint, the \code{indexnum} argument can be specified. +Objectives can be added to the portfolio object with \code{\link{add.objective}}. The \code{\link{add.objective}} function is the main function for adding and/or updating objectives to the portfolio object. This function allows the user to specify the portfolio to add the objectives to, the type, name of the objective function, arguments to the objective function, and whether or not to enable the objective. If updating an existing objective, the \code{indexnum} argument can be specified. + With the constraints and objectives specified in the portfolio object, the portfolio object can be passed to \code{\link{optimize.portfolio}} or \code{\link{optimize.portfolio.rebalancing}} to run the optimization. Arguments to \code{\link{optimize.portfolio}} include asset returns, the portfolio obect specifying constraints and objectives, optimization method, and other parameters specific to the solver. \code{\link{optimize.portfolio.rebalancing}} adds support for backtesting portfolio optimization through time with rebalancing or rolling periods. } @@ -53,6 +77,16 @@ Multiple objects created via \code{\link{optimize.portfolio}} can be combined with \code{\link{combine.optimizations}} for visual comparison. The weights of the optimal portfolios can be plotted with \code{\link{chart.Weights}}. The optimal portfolios can be compared in risk-reward space with \code{\link{chart.RiskReward}}. The portfolio component risk contributions of the multiple optimal portfolios can be plotted with \code{\link{chart.RiskBudget}}. } +\section{Package Dependencies}{ +Several of the functions in the \kbd{PortfolioAnalytics} package require time series data of returns and the \code{\link[xts]{xts}} package is used for working with time series data. + +The \kbd{PerformanceAnalytics} package is used for many common objective functions. The objective types in \kbd{PortfolioAnalytics} are designed to be used with \kbd{PerformanceAnalytics} functions such as \code{\link[PerformanceAnalytics]{StdDev}}, \code{\link[PerformanceAnalytics]{VaR}}, and \code{\link[PerformanceAnalytics]{ES}}. + +The \kbd{foreach} and \kbd{iterators} packages are used extensively throughout the package to support parallel programming. The primary functions where \code{foreach} loops are used is \code{\link{optimize.portfolio}}, \code{\link{optimize.portfolio.rebalancing}}, and \code{\link{create.EfficientFrontier}}. + +In addition to a random portfolios optimzation method, \kbd{PortfolioAnalytics} supports backend solvers by leveraging the following packages: \kbd{DEoptim}, \kbd{pso}, \kbd{GenSA}, \kbd{ROI} and associated ROI plugin packages. +} + \section{Further Work}{ Continued work to improved charts and graphs. From noreply at r-forge.r-project.org Tue Apr 15 02:11:32 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 15 Apr 2014 02:11:32 +0200 (CEST) Subject: [Returnanalytics-commits] r3367 - in pkg/PortfolioAnalytics: R demo Message-ID: <20140415001132.35ACD1861D9@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-15 02:11:31 +0200 (Tue, 15 Apr 2014) New Revision: 3367 Modified: pkg/PortfolioAnalytics/R/extract.efficient.frontier.R pkg/PortfolioAnalytics/demo/demo_efficient_frontier.R Log: updates to efficient frontier code to minimize checks and allow a constraint only portfolio object. Modified: pkg/PortfolioAnalytics/R/extract.efficient.frontier.R =================================================================== --- pkg/PortfolioAnalytics/R/extract.efficient.frontier.R 2014-04-14 21:09:50 UTC (rev 3366) +++ pkg/PortfolioAnalytics/R/extract.efficient.frontier.R 2014-04-15 00:11:31 UTC (rev 3367) @@ -13,71 +13,73 @@ extract.efficient.frontier <- function (object=NULL, match.col='ES', from=NULL, to=NULL, by=0.005, n.portfolios=NULL, ..., R=NULL, portfolio=NULL, optimize_method='random') { - #TODO add a threshold argument for how close it has to be to count - # do we need to recalc the constrained_objective too? I don't think so. - if(!inherits(object, "optimize.portfolio")) stop("object passed in must of of class 'portfolio'") - - #set<-seq(from=from,to=to,by=by) - #set<-cbind(quantmod::Lag(set,1),as.matrix(set))[-1,] - if(is.null(object)){ - if(!is.null(R) & !is.null(portfolio)){ - portfolios<-optimize.portfolio(portfolio=portfolio, R=R, optimize_method=optimize_method[1], trace=TRUE, ...) - } else { - stop('you must specify a portfolio object and a return series or an objective of class optimize.portfolio') - } - } - - xtract<-extractStats(object) - columnnames=colnames(xtract) - # optimal portfolio stats from xtract - opt <- xtract[which.min(xtract[, "out"]),] - #if("package:multicore" %in% search() || require("multicore",quietly = TRUE)){ - # mclapply - #} - stopifnot("package:foreach" %in% search() || require("foreach",quietly = TRUE)) -# rtc = pmatch(return.col,columnnames) -# if(is.na(rtc)) { -# rtc = pmatch(paste(return.col,return.col,sep='.'),columnnames) -# } - mtc = pmatch(match.col,columnnames) - if(is.na(mtc)) { - mtc = pmatch(paste(match.col,match.col,sep='.'),columnnames) - } - if(is.na(mtc)) stop("could not match match.col with column name of extractStats output") - - if(is.null(from)){ - from <- min(xtract[, mtc]) - } - if(is.null(to)){ - to <- max(xtract[, mtc]) - } - if(!is.null(n.portfolios)){ - # create the sequence using length.out if the user has specified a value for the n.portfolios arg - set<-seq(from=from, to=to, length.out=n.portfolios) + #TODO add a threshold argument for how close it has to be to count + # do we need to recalc the constrained_objective too? I don't think so. + if(!inherits(object, "optimize.portfolio")) stop("object passed in must of of class 'portfolio'") + + #set<-seq(from=from,to=to,by=by) + #set<-cbind(quantmod::Lag(set,1),as.matrix(set))[-1,] + if(is.null(object)){ + if(!is.null(R) & !is.null(portfolio)){ + portfolios<-optimize.portfolio(portfolio=portfolio, R=R, optimize_method=optimize_method[1], trace=TRUE, ...) } else { - # fall back to using by to create the sequence - set<-seq(from=from, to=to, by=by) + stop('you must specify a portfolio object and a return series or an objective of class optimize.portfolio') } - - set<-cbind(quantmod::Lag(set,1),as.matrix(set))[-1,] - result <- foreach(i=1:nrow(set),.inorder=TRUE, .combine=rbind, .errorhandling='remove') %do% { - tmp<-xtract[which(xtract[,mtc]>=set[i,1] & xtract[,mtc]=set[i,1] & xtract[,mtc]= 1){ + # the portfolio object has a var, StdDev, or sd objective + var_obj <- portfolio$objectives[[var_idx]] + } else { + var_obj <- portfolio_risk_objective(name="var") } - # for a mean-var efficient frontier, there must be two objectives 1) "mean" and 2) "var" - if(!((length(objnames) >= 2) & ("var" %in% objnames | "StdDev" %in% objnames | "sd" %in% objnames) & ("mean" %in% objnames))){ - stop("The portfolio object must have both 'mean' and 'var', 'StdDev', or'sd' specified as objectives") - } + # Clear out the objectives in portfolio and add them here to simplify checks + # and so we can control the optimization along the efficient frontier. + portfolio$objectives <- list() + portfolio$objectives[[1]] <- var_obj + portfolio <- add.objective(portfolio=portfolio, type="return", name="mean") # If the user has passed in a portfolio object with return_constraint, we need to disable it for(i in 1:length(portfolio$constraints)){ @@ -128,9 +126,6 @@ ##### get the maximum return ##### - # set the risk_aversion to a very small number for equivalent to max return portfolio - # portfolio$objectives[[var_idx]]$risk_aversion <- 1e-6 - # Disable the risk objective portfolio$objectives[[var_idx]]$enabled <- FALSE @@ -141,9 +136,6 @@ ##### Get the return at the minimum variance portfolio ##### - # set the risk_aversion to a very large number equivalent to a minvar portfolio - # portfolio$objectives[[var_idx]]$risk_aversion <- 1e6 - # Disable the return objective portfolio$objectives[[mean_idx]]$enabled <- FALSE @@ -165,11 +157,12 @@ ret_constr_idx <- which(unlist(lapply(portfolio$constraints, function(x) inherits(x, "return_constraint")))) stopifnot("package:foreach" %in% search() || require("foreach",quietly = TRUE)) + stopifnot("package:iterators" %in% search() || require("iterators",quietly = TRUE)) if(!is.null(risk_aversion)){ # Enable the return objective so we are doing quadratic utility portfolio$objectives[[mean_idx]]$enabled <- TRUE - out <- foreach(i=1:length(risk_aversion), .inorder=TRUE, .combine=rbind, .errorhandling='remove') %dopar% { - portfolio$objectives[[var_idx]]$risk_aversion <- risk_aversion[i] + out <- foreach(lambda=iter(risk_aversion), .inorder=TRUE, .combine=rbind, .errorhandling='remove', .packages='PortfolioAnalytics') %dopar% { + portfolio$objectives[[var_idx]]$risk_aversion <- lambda extractStats(optimize.portfolio(R=R, portfolio=portfolio, optimize_method="ROI", ...=...)) } out <- cbind(out, risk_aversion) @@ -177,8 +170,8 @@ } else { # Enable the return constraint portfolio$constraints[[ret_constr_idx]]$enabled <- TRUE - out <- foreach(i=1:length(ret_seq), .inorder=TRUE, .combine=rbind, .errorhandling='remove') %dopar% { - portfolio$constraints[[ret_constr_idx]]$return_target <- ret_seq[i] + out <- foreach(ret=iter(ret_seq), .inorder=TRUE, .combine=rbind, .errorhandling='remove', .packages='PortfolioAnalytics') %dopar% { + portfolio$constraints[[ret_constr_idx]]$return_target <- ret opt <- optimize.portfolio(R=R, portfolio=portfolio, optimize_method="ROI", ...=...) c(sum(extractWeights(opt) * mean_ret), extractStats(opt)) } @@ -191,10 +184,10 @@ #' Generate the efficient frontier for a mean-etl portfolio #' #' This function generates the mean-ETL efficient frontier of a portfolio -#' specifying constraints and objectives. To generate the mean-ETL efficient -#' frontier, the portfolio must have two objectives 1) "mean" and 2) "ETL/ES/CVaR". If -#' the only objective in the \code{portfolio} object is ETL/ES/CVaR, the we will -#' add a mean objective. +#' specifying the constraints and objectives. The \code{portfolio} object +#' should have two objectives: 1) mean and 2) ES (or ETL or cVaR). If the +#' portfolio object does not contain these objectives, they will be added +#' using default parameters. #' #' @param portfolio a portfolio object with constraints and objectives created via \code{\link{portfolio.spec}} #' @param R an xts or matrix of asset returns @@ -210,26 +203,25 @@ # step 3: 'step' along the returns and run the optimization to calculate # the weights and objective measures along the efficient frontier - objnames <- unlist(lapply(portfolio$objectives, function(x) x$name)) - - if(length(objnames) == 1){ - if(objnames == "mean"){ - # The user has only passed in a mean objective, add ES objective to the portfolio - portfolio <- add.objective(portfolio=portfolio, type="risk", name="ES") - } else if(objnames %in% c("ETL", "ES", "CVaR")){ - # The user has only passed in ETL/ES/CVaR objective, add a mean objective - portfolio <- add.objective(portfolio=portfolio, type="return", name="mean") - } - # get the objective names again after we add an objective to the portfolio - objnames <- unlist(lapply(portfolio$objectives, function(x) x$name)) + # Use the portfolio_risk_objective from the portfolio if they have it + # check for a ETL, ES, or cVaR objective + etl_idx <- which(unlist(lapply(portfolio$objectives, function(x) x$name)) %in% c("ETL", "ES", "CVaR")) + if(length(etl_idx) >= 1){ + # the portfolio object has a ETL, ES, CVaR objective + etl_obj <- portfolio$objectives[[etl_idx]] + } else { + etl_obj <- portfolio_risk_objective(name="ES", arguments=list(p=0.95)) } - # for a mean-etl efficient frontier, there must be two objectives 1) "mean" and 2) "ETL/ES/CVaR" - # get the names of the objectives - if(!((length(objnames) == 2) & any(objnames %in% c("ETL", "ES", "CVaR")) & ("mean" %in% objnames))){ - stop("The portfolio object must have both 'mean' and 'var' specified as objectives") - } + # Clear out the objectives in portfolio and add them here to simplify checks + # and so we can control the optimization along the efficient frontier. + portfolio$objectives <- list() + portfolio$objectives[[1]] <- etl_obj + portfolio <- add.objective(portfolio=portfolio, type="return", name="mean") + # get the objective names from the portfolio object + objnames <- unlist(lapply(portfolio$objectives, function(x) x$name)) + # If the user has passed in a portfolio object with return_constraint, we need to disable it for(i in 1:length(portfolio$constraints)){ if(inherits(portfolio$constraints[[i]], "return_constraint")){ @@ -258,14 +250,15 @@ # length.out is the number of portfolios to create ret_seq <- seq(from=minret, to=maxret, length.out=n.portfolios) -# out <- matrix(0, nrow=length(ret_seq), ncol=length(extractStats(tmp))) -# for(i in 1:length(ret_seq)){ -# portfolio$objectives[[mean_idx]]$target <- ret_seq[i] -# out[i, ] <- extractStats(optimize.portfolio(R=R, portfolio=portfolio, optimize_method="ROI")) -# } + # out <- matrix(0, nrow=length(ret_seq), ncol=length(extractStats(tmp))) + # for(i in 1:length(ret_seq)){ + # portfolio$objectives[[mean_idx]]$target <- ret_seq[i] + # out[i, ] <- extractStats(optimize.portfolio(R=R, portfolio=portfolio, optimize_method="ROI")) + # } stopifnot("package:foreach" %in% search() || require("foreach",quietly = TRUE)) - out <- foreach(i=1:length(ret_seq), .inorder=TRUE, .combine=rbind, .errorhandling='remove') %dopar% { - portfolio$objectives[[mean_idx]]$target <- ret_seq[i] + stopifnot("package:iterators" %in% search() || require("iterators",quietly = TRUE)) + out <- foreach(ret=iter(ret_seq), .inorder=TRUE, .combine=rbind, .errorhandling='remove', .packages='PortfolioAnalytics') %dopar% { + portfolio$objectives[[mean_idx]]$target <- ret extractStats(optimize.portfolio(R=R, portfolio=portfolio, optimize_method="ROI", ef=TRUE, ...=...)) } colnames(out) <- names(stats) @@ -280,12 +273,16 @@ #' \item{"mean-var", "mean-sd", or "mean-StdDev":}{ This is a special case for #' an efficient frontier that can be created by a QP solver. #' The \code{portfolio} object should have two -#' objectives: 1) mean and 2) var. The efficient frontier will be created via +#' objectives: 1) mean and 2) var. If the portfolio object does not contain these +#' objectives, they will be added using default parameters. +#' The efficient frontier will be created via #' \code{\link{meanvar.efficient.frontier}}.} #' \item{"mean-ETL", "mean-ES", "mean-CVaR", "mean-etl":}{ This is a special #' case for an efficient frontier that can be created by an LP solver. #' The \code{portfolio} object should have two objectives: 1) mean -#' and 2) ETL/ES/CVaR. The efficient frontier will be created via +#' and 2) ETL/ES/CVaR. If the portfolio object does not contain these +#' objectives, they will be added using default parameters. +#' The efficient frontier is created via #' \code{\link{meanetl.efficient.frontier}}.} #' \item{"DEoptim":}{ This can handle more complex constraints and objectives #' than the simple mean-var and mean-ETL cases. For this type, we actually Modified: pkg/PortfolioAnalytics/demo/demo_efficient_frontier.R =================================================================== --- pkg/PortfolioAnalytics/demo/demo_efficient_frontier.R 2014-04-14 21:09:50 UTC (rev 3366) +++ pkg/PortfolioAnalytics/demo/demo_efficient_frontier.R 2014-04-15 00:11:31 UTC (rev 3367) @@ -27,19 +27,18 @@ group_min=0.05, group_max=0.7) -# initial objective -init <- add.objective(portfolio=init, type="return", name="mean") - # create mean-etl portfolio meanetl.portf <- add.objective(portfolio=init, type="risk", name="ES") +meanetl.portf <- add.objective(portfolio=meanetl.portf, type="return", name="mean") # create mean-var portfolio -meanvar.portf <- add.objective(portfolio=init, type="risk", name="var", risk_aversion=1e6) +meanvar.portf <- add.objective(portfolio=init, type="risk", name="var", risk_aversion=10) +meanvar.portf <- add.objective(portfolio=meanvar.portf, type="return", name="mean") # create efficient frontiers # mean-var efficient frontier -meanvar.ef <- create.EfficientFrontier(R=R, portfolio=meanvar.portf, type="mean-StdDev") +meanvar.ef <- create.EfficientFrontier(R=R, portfolio=init, type="mean-StdDev") meanvar.ef summary(meanvar.ef, digits=2) meanvar.ef$frontier @@ -113,7 +112,7 @@ chart.Weights.EF(ef, match.col="StdDev", colorset=bluemono, by.groups=TRUE) # mean-etl efficient frontier -meanetl.ef <- create.EfficientFrontier(R=R, portfolio=meanetl.portf, type="mean-ES") +meanetl.ef <- create.EfficientFrontier(R=R, portfolio=init, type="mean-ES") meanetl.ef summary(meanetl.ef) meanetl.ef$frontier @@ -136,8 +135,6 @@ # set up an initial portfolio with the full investment constraint and mean and var objectives init.portf <- portfolio.spec(assets=funds) init.portf <- add.constraint(portfolio=init.portf, type="full_investment") -init.portf <- add.objective(portfolio=init.portf, type="risk", name="var") -init.portf <- add.objective(portfolio=init.portf, type="return", name="mean") # long only constraints lo.portf <- add.constraint(portfolio=init.portf, type="long_only") @@ -154,10 +151,28 @@ group.portf <- add.constraint(portfolio=group.portf, type="long_only") # optimize.portfolio(R=R, portfolio=group.portf, optimize_method="ROI") -portf.list <- list(lo.portf, box.portf, group.portf) +portf.list <- combine.portfolios(list(lo.portf, box.portf, group.portf)) legend.labels <- c("Long Only", "Box", "Group + Long Only") chart.EfficientFrontierOverlay(R=R, portfolio_list=portf.list, type="mean-StdDev", match.col="StdDev", legend.loc="topleft", legend.labels=legend.labels, cex.legend=0.6, labels.assets=FALSE, pch.assets=18) +# Efficient frontier in mean-ES space with varying confidence leves for +# ES calculation +ES90 <- add.objective(portfolio=lo.portf, type="risk", name="ES", + arguments=list(p=0.9)) + +ES92 <- add.objective(portfolio=lo.portf, type="risk", name="ES", + arguments=list(p=0.92)) + +ES95 <- add.objective(portfolio=lo.portf, type="risk", name="ES", + arguments=list(p=0.95)) + +portf.list <- combine.portfolios(list(ES.90=ES90, ES.92=ES92, ES.95=ES95)) +legend.labels <- c("ES (p=0.9)", "ES (p=0.92)", "ES (p=0.95)") +chart.EfficientFrontierOverlay(R=R, portfolio_list=portf.list, type="mean-ES", + match.col="ES", legend.loc="topleft", + legend.labels=legend.labels, cex.legend=0.6, + labels.assets=FALSE, pch.assets=18) + From noreply at r-forge.r-project.org Tue Apr 15 03:49:35 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 15 Apr 2014 03:49:35 +0200 (CEST) Subject: [Returnanalytics-commits] r3368 - pkg/PortfolioAnalytics/man Message-ID: <20140415014936.4E196186B73@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-15 03:49:25 +0200 (Tue, 15 Apr 2014) New Revision: 3368 Modified: pkg/PortfolioAnalytics/man/create.EfficientFrontier.Rd pkg/PortfolioAnalytics/man/meanetl.efficient.frontier.Rd pkg/PortfolioAnalytics/man/meanvar.efficient.frontier.Rd Log: Updating man files for efficient frontier Modified: pkg/PortfolioAnalytics/man/create.EfficientFrontier.Rd =================================================================== --- pkg/PortfolioAnalytics/man/create.EfficientFrontier.Rd 2014-04-15 00:11:31 UTC (rev 3367) +++ pkg/PortfolioAnalytics/man/create.EfficientFrontier.Rd 2014-04-15 01:49:25 UTC (rev 3368) @@ -49,13 +49,17 @@ "mean-sd", or "mean-StdDev":}{ This is a special case for an efficient frontier that can be created by a QP solver. The \code{portfolio} object should have two objectives: - 1) mean and 2) var. The efficient frontier will be + 1) mean and 2) var. If the portfolio object does not + contain these objectives, they will be added using + default parameters. The efficient frontier will be created via \code{\link{meanvar.efficient.frontier}}.} \item{"mean-ETL", "mean-ES", "mean-CVaR", "mean-etl":}{ This is a special case for an efficient frontier that can be created by an LP solver. The \code{portfolio} object should have two objectives: 1) mean and 2) ETL/ES/CVaR. - The efficient frontier will be created via + If the portfolio object does not contain these + objectives, they will be added using default parameters. + The efficient frontier is created via \code{\link{meanetl.efficient.frontier}}.} \item{"DEoptim":}{ This can handle more complex constraints and objectives than the simple mean-var and Modified: pkg/PortfolioAnalytics/man/meanetl.efficient.frontier.Rd =================================================================== --- pkg/PortfolioAnalytics/man/meanetl.efficient.frontier.Rd 2014-04-15 00:11:31 UTC (rev 3367) +++ pkg/PortfolioAnalytics/man/meanetl.efficient.frontier.Rd 2014-04-15 01:49:25 UTC (rev 3368) @@ -23,11 +23,11 @@ } \description{ This function generates the mean-ETL efficient frontier - of a portfolio specifying constraints and objectives. To - generate the mean-ETL efficient frontier, the portfolio - must have two objectives 1) "mean" and 2) "ETL/ES/CVaR". - If the only objective in the \code{portfolio} object is - ETL/ES/CVaR, the we will add a mean objective. + of a portfolio specifying the constraints and objectives. + The \code{portfolio} object should have two objectives: + 1) mean and 2) ES (or ETL or cVaR). If the portfolio + object does not contain these objectives, they will be + added using default parameters. } \author{ Ross Bennett Modified: pkg/PortfolioAnalytics/man/meanvar.efficient.frontier.Rd =================================================================== --- pkg/PortfolioAnalytics/man/meanvar.efficient.frontier.Rd 2014-04-15 00:11:31 UTC (rev 3367) +++ pkg/PortfolioAnalytics/man/meanvar.efficient.frontier.Rd 2014-04-15 01:49:25 UTC (rev 3368) @@ -6,8 +6,8 @@ n.portfolios = 25, risk_aversion = NULL, ...) } \arguments{ - \item{portfolio}{a portfolio object with constraints and - objectives created via \code{\link{portfolio.spec}}} + \item{portfolio}{a portfolio object with constraints + created via \code{\link{portfolio.spec}}} \item{R}{an xts or matrix of asset returns} @@ -29,10 +29,11 @@ } \description{ This function generates the mean-variance efficient - frontier of a portfolio specifying constraints and - objectives. To generate the mean-var efficient frontier, - the portfolio must have two objectives 1) "mean" and 2) - "var". + frontier of a portfolio specifying the constraints and + objectives. The \code{portfolio} object should have two + objectives: 1) mean and 2) var (or sd or StdDev). If the + portfolio object does not contain these objectives, they + will be added using default parameters. } \author{ Ross Bennett From noreply at r-forge.r-project.org Tue Apr 15 18:49:32 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 15 Apr 2014 18:49:32 +0200 (CEST) Subject: [Returnanalytics-commits] r3369 - in pkg/PortfolioAnalytics: R man Message-ID: <20140415164933.032A518670D@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-15 18:49:32 +0200 (Tue, 15 Apr 2014) New Revision: 3369 Modified: pkg/PortfolioAnalytics/R/constraints.R pkg/PortfolioAnalytics/R/objective.R pkg/PortfolioAnalytics/man/add.constraint.Rd pkg/PortfolioAnalytics/man/add.objective.Rd pkg/PortfolioAnalytics/man/print.summary.optimize.portfolio.rebalancing.Rd Log: adding examples to add.constraint and add.objective Modified: pkg/PortfolioAnalytics/R/constraints.R =================================================================== --- pkg/PortfolioAnalytics/R/constraints.R 2014-04-15 01:49:25 UTC (rev 3368) +++ pkg/PortfolioAnalytics/R/constraints.R 2014-04-15 16:49:32 UTC (rev 3369) @@ -255,6 +255,29 @@ #' #' # Add target mean return constraint #' pspec <- add.constraint(portfolio=pspec, type="return", return_target=0.007) +#' +#' # Example using the indexnum argument +#' portf <- portfolio.spec(assets=fund.names) +#' portf <- add.constraint(portf, type="full_investment") +#' portf <- add.constraint(portf, type="long_only") +#' +#' # indexnum corresponds to the index number of the constraint +#' # The full_investment constraint was the first constraint added and has +#' # indexnum=1 +#' portf$constraints[[1]] +#' +#' # View the constraint with indexnum=2 +#' portf$constraints[[2]] +#' +#' # Update the constraint to relax the sum of weights constraint +#' portf <- add.constraint(portf, type="weight_sum", +#' min_sum=0.99, max_sum=1.01, +#' indexnum=1) +#' +#' # Update the constraint to modify the box constraint +#' portf <- add.constraint(portf, type="box", +#' min=0.1, max=0.8, +#' indexnum=2) #' @export add.constraint <- function(portfolio, type, enabled=TRUE, message=FALSE, ..., indexnum=NULL){ # Check to make sure that the portfolio passed in is a portfolio object Modified: pkg/PortfolioAnalytics/R/objective.R =================================================================== --- pkg/PortfolioAnalytics/R/objective.R 2014-04-15 01:49:25 UTC (rev 3368) +++ pkg/PortfolioAnalytics/R/objective.R 2014-04-15 16:49:32 UTC (rev 3369) @@ -223,12 +223,60 @@ #' @param arguments default arguments to be passed to an objective function when executed #' @param enabled TRUE/FALSE #' @param \dots any other passthru parameters -#' @param indexnum if you are updating a specific constraint, the index number in the $objectives list to update +#' @param indexnum if you are updating a specific objective, the index number in the $objectives list to update #' @author Brian G. Peterson and Ross Bennett #' @aliases add.objective_v2 add.objective_v1 #' @seealso \code{\link{objective}}, \code{\link{portfolio.spec}} #' @rdname add.objective #' @name add.objective +#' @examples +#' data(edhec) +#' returns <- edhec[,1:4] +#' fund.names <- colnames(returns) +#' portf <- portfolio.spec(assets=fund.names) +#' # Add some basic constraints +#' portf <- add.constraint(portf, type="full_investment") +#' portf <- add.constraint(portf, type="long_only") +#' +#' # Creates a new portfolio object using portf and adds a quadratic utility +#' # objective. This will add two objectives to the portfolio object; 1) mean and +#' # 2) var. The risk aversion parameter is commonly referred to as lambda in the +#' # quadratic utility formulation that controls how much the portfolio variance +#' # is penalized. +#' portf.maxQU <- add.objective(portf, type="quadratic_utility", +#' risk_aversion=0.25) +#' +#' # Creates a new portfolio object using portf and adds mean as an objective +#' portf.maxMean <- add.objective(portf, type="return", name="mean") +#' +#' # Creates a new portfolio object using portf and adds StdDev as an objective +#' portf.minStdDev <- add.objective(portf, type="risk", name="StdDev") +#' +#' # Creates a new portfolio object using portf and adds ES as an objective. +#' # Note that arguments to ES are passed in as a named list. +#' portf.minES <- add.objective(portf, type="risk", name="ES", +#' arguments=list(p=0.925, clean="boudt")) +#' +#' # Creates a new portfolio object using portf.minES and adds a risk budget +#' # objective with limits on component risk contribution. +#' # Note that arguments to ES are passed in as a named list. +#' portf.RiskBudgetES <- add.objective(portf.minES, type="risk_budget", name="ES", +#' arguments=list(p=0.925, clean="boudt"), +#' min_prisk=0, max_prisk=0.6) +#' +#' # Creates a new portfolio object using portf.minES and adds a risk budget +#' # objective with equal component risk contribution. +#' # Note that arguments to ES are passed in as a named list. +#' portf.EqRiskES <- add.objective(portf.minES, type="risk_budget", name="ES", +#' arguments=list(p=0.925, clean="boudt"), +#' min_concentration=TRUE) +#' +#' # Creates a new portfolio object using portf and adds a weight_concentration +#' # objective. The conc_aversion parameter controls how much concentration is +#' # penalized. The portfolio concentration is defined as the Herfindahl Hirschman +#' # Index of the weights. +#' portf.conc <- add.objective(portf, type="weight_concentration", +#' name="HHI", conc_aversion=0.01) #' @export add.objective <- add.objective_v2 Modified: pkg/PortfolioAnalytics/man/add.constraint.Rd =================================================================== --- pkg/PortfolioAnalytics/man/add.constraint.Rd 2014-04-15 01:49:25 UTC (rev 3368) +++ pkg/PortfolioAnalytics/man/add.constraint.Rd 2014-04-15 16:49:32 UTC (rev 3369) @@ -102,6 +102,29 @@ # Add target mean return constraint pspec <- add.constraint(portfolio=pspec, type="return", return_target=0.007) + +# Example using the indexnum argument +portf <- portfolio.spec(assets=fund.names) +portf <- add.constraint(portf, type="full_investment") +portf <- add.constraint(portf, type="long_only") + +# indexnum corresponds to the index number of the constraint +# The full_investment constraint was the first constraint added and has +# indexnum=1 +portf$constraints[[1]] + +# View the constraint with indexnum=2 +portf$constraints[[2]] + +# Update the constraint to relax the sum of weights constraint +portf <- add.constraint(portf, type="weight_sum", +min_sum=0.99, max_sum=1.01, +indexnum=1) + +# Update the constraint to modify the box constraint +portf <- add.constraint(portf, type="box", +min=0.1, max=0.8, +indexnum=2) } \author{ Ross Bennett Modified: pkg/PortfolioAnalytics/man/add.objective.Rd =================================================================== --- pkg/PortfolioAnalytics/man/add.objective.Rd 2014-04-15 01:49:25 UTC (rev 3368) +++ pkg/PortfolioAnalytics/man/add.objective.Rd 2014-04-15 16:49:32 UTC (rev 3369) @@ -36,9 +36,8 @@ \item{\dots}{any other passthru parameters} - \item{indexnum}{if you are updating a specific - constraint, the index number in the $objectives list to - update} + \item{indexnum}{if you are updating a specific objective, + the index number in the $objectives list to update} } \description{ This function is the main function for adding and @@ -56,6 +55,55 @@ Objectives of type 'turnover' and 'minmax' are also supported. } +\examples{ +data(edhec) +returns <- edhec[,1:4] +fund.names <- colnames(returns) +portf <- portfolio.spec(assets=fund.names) +# Add some basic constraints +portf <- add.constraint(portf, type="full_investment") +portf <- add.constraint(portf, type="long_only") + +# Creates a new portfolio object using portf and adds a quadratic utility +# objective. This will add two objectives to the portfolio object; 1) mean and +# 2) var. The risk aversion parameter is commonly referred to as lambda in the +# quadratic utility formulation that controls how much the portfolio variance +# is penalized. +portf.maxQU <- add.objective(portf, type="quadratic_utility", + risk_aversion=0.25) + +# Creates a new portfolio object using portf and adds mean as an objective +portf.maxMean <- add.objective(portf, type="return", name="mean") + +# Creates a new portfolio object using portf and adds StdDev as an objective +portf.minStdDev <- add.objective(portf, type="risk", name="StdDev") + +# Creates a new portfolio object using portf and adds ES as an objective. +# Note that arguments to ES are passed in as a named list. +portf.minES <- add.objective(portf, type="risk", name="ES", + arguments=list(p=0.925, clean="boudt")) + +# Creates a new portfolio object using portf.minES and adds a risk budget +# objective with limits on component risk contribution. +# Note that arguments to ES are passed in as a named list. +portf.RiskBudgetES <- add.objective(portf.minES, type="risk_budget", name="ES", + arguments=list(p=0.925, clean="boudt"), + min_prisk=0, max_prisk=0.6) + +# Creates a new portfolio object using portf.minES and adds a risk budget +# objective with equal component risk contribution. +# Note that arguments to ES are passed in as a named list. +portf.EqRiskES <- add.objective(portf.minES, type="risk_budget", name="ES", + arguments=list(p=0.925, clean="boudt"), + min_concentration=TRUE) + +# Creates a new portfolio object using portf and adds a weight_concentration +# objective. The conc_aversion parameter controls how much concentration is +# penalized. The portfolio concentration is defined as the Herfindahl Hirschman +# Index of the weights. +portf.conc <- add.objective(portf, type="weight_concentration", + name="HHI", conc_aversion=0.01) +} \author{ Brian G. Peterson and Ross Bennett } Modified: pkg/PortfolioAnalytics/man/print.summary.optimize.portfolio.rebalancing.Rd =================================================================== --- pkg/PortfolioAnalytics/man/print.summary.optimize.portfolio.rebalancing.Rd 2014-04-15 01:49:25 UTC (rev 3368) +++ pkg/PortfolioAnalytics/man/print.summary.optimize.portfolio.rebalancing.Rd 2014-04-15 16:49:32 UTC (rev 3369) @@ -2,8 +2,7 @@ \alias{print.summary.optimize.portfolio.rebalancing} \title{Printing summary output of optimize.portfolio.rebalancing} \usage{ - \method{print}{summary.optimize.portfolio.rebalancing} - (x, ..., digits = 4) + \method{print}{summary.optimize.portfolio.rebalancing}(x, ..., digits = 4) } \arguments{ \item{x}{an object of class From noreply at r-forge.r-project.org Tue Apr 15 19:30:19 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 15 Apr 2014 19:30:19 +0200 (CEST) Subject: [Returnanalytics-commits] r3370 - pkg/FactorAnalytics/R Message-ID: <20140415173019.A7568186EB2@r-forge.r-project.org> Author: chenyian Date: 2014-04-15 19:30:19 +0200 (Tue, 15 Apr 2014) New Revision: 3370 Modified: pkg/FactorAnalytics/R/plot.TimeSeriesFactorModel.r Log: fix bug in plot.TimeSeriesFactorModel.r Modified: pkg/FactorAnalytics/R/plot.TimeSeriesFactorModel.r =================================================================== --- pkg/FactorAnalytics/R/plot.TimeSeriesFactorModel.r 2014-04-15 16:49:32 UTC (rev 3369) +++ pkg/FactorAnalytics/R/plot.TimeSeriesFactorModel.r 2014-04-15 17:30:19 UTC (rev 3370) @@ -377,7 +377,7 @@ } # function to extract contribution to sd from list getCSD = function(x) { - x$cr.fm + x$cSd.fm } # extract contributions to SD from list cr.sd = sapply(factor.sd.decomp.list, getCSD) @@ -397,7 +397,8 @@ beta = as.matrix(x$beta[i,]) fitted = alpha+as.matrix(plot.data[,factor.names])%*%beta residual = plot.data[,i]-fitted - tmpData = cbind(plot.data[idx,i], plot.data[idx,factor.names], + tmpData = cbind(coredata(plot.data[idx,i]), + coredata(plot.data[idx,factor.names]), (residual[idx,]/sqrt(x$resid.variance[i])) ) colnames(tmpData)[c(1,length(tmpData))] = c(i, "residual") factor.es.decomp.list[[i]] = @@ -411,19 +412,21 @@ for (i in asset.names) { # check for missing values in fund data idx = which(!is.na(plot.data[,i])) - tmpData = cbind(plot.data[idx,i], plot.data[idx,factor.names], + tmpData = cbind(coredata(plot.data[idx,i]), + coredata(plot.data[idx,factor.names]), residuals(x$asset.fit[[i]])/sqrt(x$resid.variance[i])) - colnames(tmpData)[c(1,length(tmpData))] = c(i, "residual") + colnames(tmpData)[c(1,dim(tmpData)[2])] = c(i, "residual") factor.es.decomp.list[[i]] = factorModelEsDecomposition(tmpData, x$beta[i,], - x$resid.variance[i], tail.prob=0.05) + x$resid.variance[i], tail.prob=0.05, + VaR.method=VaR.method) } } # stacked bar charts of percent contributions to SD getCETL = function(x) { - x$cES + x$cES.fm } # report as positive number cr.etl = sapply(factor.es.decomp.list, getCETL) @@ -443,7 +446,8 @@ beta = as.matrix(x$beta[i,]) fitted = alpha+as.matrix(plot.data[,factor.names])%*%beta residual = plot.data[,i]-fitted - tmpData = cbind(plot.data[idx,i], plot.data[idx,factor.names], + tmpData = cbind(coredata(plot.data[idx,i]), + coredata(plot.data[idx,factor.names]), (residual[idx,]/sqrt(x$resid.variance[i])) ) colnames(tmpData)[c(1,length(tmpData))] = c(i, "residual") factor.VaR.decomp.list[[i]] = @@ -456,9 +460,10 @@ for (i in asset.names) { # check for missing values in fund data idx = which(!is.na(plot.data[,i])) - tmpData = cbind(plot.data[idx,i], plot.data[idx,factor.names], + tmpData = cbind(coredata(plot.data[idx,i]), + coredata(plot.data[idx,factor.names]), residuals(x$asset.fit[[i]])/sqrt(x$resid.variance[i])) - colnames(tmpData)[c(1,length(tmpData))] = c(i, "residual") + colnames(tmpData)[c(1,dim(tmpData)[2])] = c(i, "residual") factor.VaR.decomp.list[[i]] = factorModelVaRDecomposition(tmpData, x$beta[i,], From noreply at r-forge.r-project.org Tue Apr 15 19:49:26 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 15 Apr 2014 19:49:26 +0200 (CEST) Subject: [Returnanalytics-commits] r3371 - pkg/FactorAnalytics/R Message-ID: <20140415174926.989C018682D@r-forge.r-project.org> Author: chenyian Date: 2014-04-15 19:49:26 +0200 (Tue, 15 Apr 2014) New Revision: 3371 Modified: pkg/FactorAnalytics/R/fitTimeSeriesFactorModel.R Log: fix a bug in add.up.market.beta in fitTimeSeriesFactorModel.R Modified: pkg/FactorAnalytics/R/fitTimeSeriesFactorModel.R =================================================================== --- pkg/FactorAnalytics/R/fitTimeSeriesFactorModel.R 2014-04-15 17:30:19 UTC (rev 3370) +++ pkg/FactorAnalytics/R/fitTimeSeriesFactorModel.R 2014-04-15 17:49:26 UTC (rev 3371) @@ -146,9 +146,9 @@ for (i in assets.names) { reg.df = na.omit(reg.xts[, c(i, factors.names)]) if(add.up.market.returns == TRUE) { - up.beta <- apply(reg.xts[,excess.market.returns.name],1,max,0) - reg.df = merge(reg.df,up.beta) - } + reg.df$up.beta = reg.df[,excess.market.returns.name] + reg.df$up.beta[reg.df$up.beta <0] <- rep(0,sum(reg.df$up.beta<0)) + } if(add.quadratic.term == TRUE) { quadratic.term <- reg.xts[,excess.market.returns.name]^2 reg.df = merge(reg.df,quadratic.term) From noreply at r-forge.r-project.org Tue Apr 15 21:06:05 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 15 Apr 2014 21:06:05 +0200 (CEST) Subject: [Returnanalytics-commits] r3372 - pkg/FactorAnalytics/R Message-ID: <20140415190605.925FE187341@r-forge.r-project.org> Author: chenyian Date: 2014-04-15 21:06:04 +0200 (Tue, 15 Apr 2014) New Revision: 3372 Modified: pkg/FactorAnalytics/R/plot.StatFactorModel.r Log: fix bug in plot.StatFactorModel.r Modified: pkg/FactorAnalytics/R/plot.StatFactorModel.r =================================================================== --- pkg/FactorAnalytics/R/plot.StatFactorModel.r 2014-04-15 17:49:26 UTC (rev 3371) +++ pkg/FactorAnalytics/R/plot.StatFactorModel.r 2014-04-15 19:06:04 UTC (rev 3372) @@ -400,7 +400,7 @@ } # function to extract component contribution to sd from list getCSD = function(x) { - x$cr.fm + x$cSd.fm } # extract contributions to SD from list cr.sd = sapply(factor.sd.decomp.list, getCSD) From noreply at r-forge.r-project.org Fri Apr 18 17:05:31 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 18 Apr 2014 17:05:31 +0200 (CEST) Subject: [Returnanalytics-commits] r3373 - in pkg/PortfolioAnalytics: . vignettes Message-ID: <20140418150531.9C6B5187362@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-18 17:05:31 +0200 (Fri, 18 Apr 2014) New Revision: 3373 Modified: pkg/PortfolioAnalytics/DESCRIPTION pkg/PortfolioAnalytics/vignettes/risk_budget_optimization.Rnw Log: Update to DESCRIPTION file for PerformanceAnalytics version and risk budget vignette to use quarterly rebalancing. Modified: pkg/PortfolioAnalytics/DESCRIPTION =================================================================== --- pkg/PortfolioAnalytics/DESCRIPTION 2014-04-15 19:06:04 UTC (rev 3372) +++ pkg/PortfolioAnalytics/DESCRIPTION 2014-04-18 15:05:31 UTC (rev 3373) @@ -12,7 +12,7 @@ R (>= 2.14.0), zoo, xts (>= 0.8), - PerformanceAnalytics (>= 1.0.0) + PerformanceAnalytics (>= 1.1.4) Suggests: quantmod, DEoptim(>= 2.2.1), Modified: pkg/PortfolioAnalytics/vignettes/risk_budget_optimization.Rnw =================================================================== --- pkg/PortfolioAnalytics/vignettes/risk_budget_optimization.Rnw 2014-04-15 19:06:04 UTC (rev 3372) +++ pkg/PortfolioAnalytics/vignettes/risk_budget_optimization.Rnw 2014-04-18 15:05:31 UTC (rev 3373) @@ -316,12 +316,11 @@ As an example, consider the minimum CVaR concentration portfolio, with estimation from inception and monthly rebalancing. Since we require a minimum estimation length of total number of observations -1, we can optimize the portfolio only for the last two months. <>= -library(iterators) set.seed(1234) out <- optimize.portfolio.rebalancing(R=indexes, portfolio=ObjSpec, optimize_method="DEoptim", search_size=5000, - rebalance_on="months", - training_period=nrow(indexes)-10, + rebalance_on="quarters", + training_period=nrow(indexes)-12, traceDE=0) @ From noreply at r-forge.r-project.org Sat Apr 19 06:03:18 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sat, 19 Apr 2014 06:03:18 +0200 (CEST) Subject: [Returnanalytics-commits] r3374 - pkg/PortfolioAnalytics/inst/tests Message-ID: <20140419040319.3DEAA187558@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-19 06:03:15 +0200 (Sat, 19 Apr 2014) New Revision: 3374 Added: pkg/PortfolioAnalytics/inst/tests/test_cplex_gmv.R pkg/PortfolioAnalytics/inst/tests/test_cplex_maxMean.R pkg/PortfolioAnalytics/inst/tests/test_cplex_minES.R pkg/PortfolioAnalytics/inst/tests/test_cplex_qu.R pkg/PortfolioAnalytics/inst/tests/test_glpk_maxMean.R pkg/PortfolioAnalytics/inst/tests/test_glpk_minES.R pkg/PortfolioAnalytics/inst/tests/test_qp_gmv.R pkg/PortfolioAnalytics/inst/tests/test_qp_qu.R Removed: pkg/PortfolioAnalytics/inst/tests/test_roi_max_ret.R pkg/PortfolioAnalytics/inst/tests/test_roi_min_etl.R pkg/PortfolioAnalytics/inst/tests/test_roi_min_var.R pkg/PortfolioAnalytics/inst/tests/test_roi_qu.R Log: Removing bad test files and adding improved test files. Specifically testing output of PortfolioAnalytics with output of solver (e.g. PortfolioAnalytics using ROI.plugin.glpk against using Rglpk directly) Added: pkg/PortfolioAnalytics/inst/tests/test_cplex_gmv.R =================================================================== --- pkg/PortfolioAnalytics/inst/tests/test_cplex_gmv.R (rev 0) +++ pkg/PortfolioAnalytics/inst/tests/test_cplex_gmv.R 2014-04-19 04:03:15 UTC (rev 3374) @@ -0,0 +1,166 @@ +library(PortfolioAnalytics) +library(Rcplex) +library(ROI) +library(ROI.plugin.cplex) +library(testthat) + +# Test that PortfolioAnalytics with ROI.plugin.cplex solutions equal Rcplex solutions +context("GMV Portfolios: PortfolioAnalytics with ROI.plugin.cplex and Rcplex") + +# args(Rcplex) +# ?Rcplex + +##### Data ##### +data(edhec) +R <- edhec[, 1:5] +funds <- colnames(R) +m <- ncol(R) + +##### Parameters ##### +portf <- portfolio.spec(funds) +portf <- add.constraint(portf, type="full_investment") +portf <- add.constraint(portf, type="box", min=-Inf, max=Inf) +portf <- add.objective(portf, type="risk", name="var") + +# Quadratic part of objective function +objQ <- 2 * cov(R) + +# Linear part of objective function +objL <- rep(0, m) + +# Constraints matrix +Amat <- matrix(1, nrow=1, ncol=m) + +# right hand side of constraints +rhs <- 1 + +# direction of inequality of constraints +dir <- "E" + +##### Unconstrained ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +lb <- rep(-Inf, m) +ub <- rep(Inf, m) + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Unconstrained: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt)) +}) + +test_that("Unconstrained: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +##### Long Only ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +lb <- rep(0, m) +ub <- rep(1, m) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Long Only: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt)) +}) + +test_that("Long Only: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Long Only: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt >= lb) & all(opt.rcplex$xopt <= ub), is_true()) +}) + +test_that("Long Only: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +##### Box ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +lb <- rep(0.05, m) +ub <- rep(0.55, m) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + + +test_that("Box: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt)) +}) + +test_that("Box: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Box: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt >= lb) & all(opt.rcplex$xopt <= ub), is_true()) +}) + +test_that("Box: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +##### Box with Shorting ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +lb <- rep(-0.05, m) +ub <- rep(0.55, m) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + + +test_that("Box with Shorting: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt)) +}) + +test_that("Box with Shorting: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Box with Shorting: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt >= lb) & all(opt.rcplex$xopt <= ub), is_true()) +}) + +test_that("Box with Shorting: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +Rcplex.close() Added: pkg/PortfolioAnalytics/inst/tests/test_cplex_maxMean.R =================================================================== --- pkg/PortfolioAnalytics/inst/tests/test_cplex_maxMean.R (rev 0) +++ pkg/PortfolioAnalytics/inst/tests/test_cplex_maxMean.R 2014-04-19 04:03:15 UTC (rev 3374) @@ -0,0 +1,140 @@ +library(PortfolioAnalytics) +library(Rcplex) +library(ROI) +library(ROI.plugin.cplex) +library(testthat) + +# Test that ROI.plugin.cplex solutions equal Rcplex solutions +context("Maximum Mean Return Portfolios: PortfolioAnalytics with ROI.plugin.cplex and Rcplex") + +# args(Rcplex) +# ?Rcplex + +##### Data ##### +data(edhec) +R <- edhec[, 1:5] +funds <- colnames(R) +m <- ncol(R) + +##### Parameters ##### +portf <- portfolio.spec(funds) +portf <- add.constraint(portf, type="full_investment") +portf <- add.constraint(portf, type="box", min=0, max=1) +portf <- add.objective(portf, type="return", name="mean") + +# Quadratic part of objective function +objQ <- NULL + +# Linear part of objective function +objL <- -colMeans(R) + +# Constraints matrix +Amat <- matrix(1, nrow=1, ncol=m) + +# right hand side of constraints +rhs <- 1 + +# direction of inequality of constraints +dir <- "E" + + +##### Long Only ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +lb <- rep(0, m) +ub <- rep(1, m) + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Long Only: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt)) +}) + +test_that("Long Only: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Long Only: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt >= lb) & all(opt.rcplex$xopt <= ub), is_true()) +}) + +test_that("Long Only: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +##### Box ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +lb <- rep(0.05, m) +ub <- rep(0.55, m) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Box: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt)) +}) + +test_that("Box: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Box: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt >= lb) & all(opt.rcplex$xopt <= ub), is_true()) +}) + +test_that("Box: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +##### Box with Shorting ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +lb <- rep(-0.05, m) +ub <- rep(0.55, m) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Box with Shorting: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt)) +}) + +test_that("Box with Shorting: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Box with Shorting: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt >= lb) & all(opt.rcplex$xopt <= ub), is_true()) +}) + +test_that("Box with Shorting: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +Rcplex.close() + Added: pkg/PortfolioAnalytics/inst/tests/test_cplex_minES.R =================================================================== --- pkg/PortfolioAnalytics/inst/tests/test_cplex_minES.R (rev 0) +++ pkg/PortfolioAnalytics/inst/tests/test_cplex_minES.R 2014-04-19 04:03:15 UTC (rev 3374) @@ -0,0 +1,184 @@ +library(PortfolioAnalytics) +library(Rcplex) +library(ROI) +library(ROI.plugin.cplex) +library(testthat) + +# Test that ROI.plugin.cplex solutions equal Rcplex solutions +context("Minimum ES Portfolios: PortfolioAnalytics with ROI.plugin.cplex and Rcplex") + +# args(Rcplex) +# ?Rcplex + +##### Data ##### +data(edhec) +R <- edhec[, 1:5] +funds <- colnames(R) + +##### Parameters ##### +m <- ncol(R) +n <- nrow(R) +alpha <- 0.05 + +portf <- portfolio.spec(funds) +portf <- add.constraint(portf, type="full_investment") +portf <- add.constraint(portf, type="box", min=-Inf, max=Inf) +portf <- add.objective(portf, type="risk", name="ES", arguments=list(p=1-alpha)) + +# Quadratic part of objective function +objQ <- NULL + +# Linear part of objective function +objL <- c(rep(0, m), rep(1 / (alpha * n), n), 1) + +# Constraints matrix +Amat <- cbind(rbind(1, zoo::coredata(R)), + rbind(0, cbind(diag(n), 1))) + +# right hand side of constraints +rhs <- c(1, rep(0, n)) + +# direction of inequality of constraints +dir <- c("E", rep("G", n)) + +##### Unconstrained ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +min_box <- rep(-Inf, m) +max_box <- rep(Inf, m) + +lb <- c(min_box, rep(0, n), -1) +ub <- c(max_box, rep(Inf, n), 1) + + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + + +test_that("Unconstrained: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt[1:m])) +}) + +test_that("Unconstrained: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + + +##### Long Only ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +min_box <- rep(0, m) +max_box <- rep(1, m) + +lb <- c(min_box, rep(0, n), -1) +ub <- c(max_box, rep(Inf, n), 1) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- min_box +portf$constraints[[2]]$max <- max_box + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Long Only: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt[1:m])) +}) + +test_that("Long Only: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= min_box) & all(weights <= max_box), is_true()) +}) + +test_that("Long Only: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt[1:m] >= min_box) & all(opt.rcplex$xopt[1:m] <= max_box), is_true()) +}) + +test_that("Long Only: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +##### Box ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +min_box <- rep(0.05, m) +max_box <- rep(0.55, m) + +lb <- c(min_box, rep(0, n), -1) +ub <- c(max_box, rep(Inf, n), 1) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- min_box +portf$constraints[[2]]$max <- max_box + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Box: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt[1:m])) +}) + +test_that("Box: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= min_box) & all(weights <= max_box), is_true()) +}) + +test_that("Box: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt[1:m] >= min_box) & all(opt.rcplex$xopt[1:m] <= max_box), is_true()) +}) + +test_that("Box: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +##### Box with Shorting ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +min_box <- rep(-0.05, m) +max_box <- rep(0.55, m) + +lb <- c(min_box, rep(0, n), -1) +ub <- c(max_box, rep(Inf, n), 1) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- min_box +portf$constraints[[2]]$max <- max_box + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Box with Shorting: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt[1:m])) +}) + +test_that("Box with Shorting: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= min_box) & all(weights <= max_box), is_true()) +}) + +test_that("Box with Shorting: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt[1:m] >= min_box) & all(opt.rcplex$xopt[1:m] <= max_box), is_true()) +}) + +test_that("Box with Shorting: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +Rcplex.close() + Added: pkg/PortfolioAnalytics/inst/tests/test_cplex_qu.R =================================================================== --- pkg/PortfolioAnalytics/inst/tests/test_cplex_qu.R (rev 0) +++ pkg/PortfolioAnalytics/inst/tests/test_cplex_qu.R 2014-04-19 04:03:15 UTC (rev 3374) @@ -0,0 +1,171 @@ +library(PortfolioAnalytics) +library(Rcplex) +library(ROI) +library(ROI.plugin.cplex) +library(testthat) + +# Test that PortfolioAnalytics with ROI.plugin.cplex solutions equal Rcplex solutions +context("Maximum Quadratic Utility Portfolios: PortfolioAnalytics with ROI.plugin.cplex and Rcplex") + +# args(Rcplex) +# ?Rcplex + +##### Data ##### +data(edhec) +R <- edhec[, 1:5] +funds <- colnames(R) +m <- ncol(R) + +##### Parameters ##### + +# risk aversion parameter +lambda <- 1 + +portf <- portfolio.spec(funds) +portf <- add.constraint(portf, type="full_investment") +portf <- add.constraint(portf, type="box", min=-Inf, max=Inf) +portf <- add.objective(portf, type="risk", name="var", risk_aversion=lambda) +portf <- add.objective(portf, type="return", name="mean") + +# Quadratic part of objective function +objQ <- lambda * 2 * cov(R) + +# Linear part of objective function +objL <- -colMeans(R) + +# Constraints matrix +Amat <- matrix(1, nrow=1, ncol=m) + +# right hand side of constraints +rhs <- 1 + +# direction of inequality of constraints +dir <- "E" + +##### Unconstrained ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +lb <- rep(-Inf, m) +ub <- rep(Inf, m) + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Unconstrained: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt)) +}) + +test_that("Unconstrained: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +##### Long Only ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +lb <- rep(0, m) +ub <- rep(1, m) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Long Only: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt)) +}) + +test_that("Long Only: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Long Only: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt >= lb) & all(opt.rcplex$xopt <= ub), is_true()) +}) + +test_that("Long Only: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +##### Box ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +lb <- rep(0.05, m) +ub <- rep(0.55, m) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + + +test_that("Box: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt)) +}) + +test_that("Box: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Box: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt >= lb) & all(opt.rcplex$xopt <= ub), is_true()) +}) + +test_that("Box: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +##### Box with Shorting ##### +# Upper and lower bounds (i.e. box constraints) +# Rcplex bounds +lb <- rep(-0.05, m) +ub <- rep(0.55, m) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + +# Solve optimization with Rcplex +opt.rcplex <- Rcplex(cvec=objL, Amat=Amat, bvec=rhs, Qmat=objQ, lb=lb, ub=ub, + sense=dir, control=list(trace=0)) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="cplex") +weights <- as.numeric(extractWeights(opt.pa)) + + +test_that("Box with Shorting: PortfolioAnalytics and Rcplex solution weights are equal", { + expect_that(weights, equals(opt.rcplex$xopt)) +}) + +test_that("Box with Shorting: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Box with Shorting: Rcplex bounds are respected", { + expect_that(all(opt.rcplex$xopt >= lb) & all(opt.rcplex$xopt <= ub), is_true()) +}) + +test_that("Box with Shorting: PortfolioAnalytics and Rcplex solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.rcplex$obj)) +}) + +Rcplex.close() Added: pkg/PortfolioAnalytics/inst/tests/test_glpk_maxMean.R =================================================================== --- pkg/PortfolioAnalytics/inst/tests/test_glpk_maxMean.R (rev 0) +++ pkg/PortfolioAnalytics/inst/tests/test_glpk_maxMean.R 2014-04-19 04:03:15 UTC (rev 3374) @@ -0,0 +1,141 @@ +library(PortfolioAnalytics) +library(ROI) +library(ROI.plugin.glpk) +library(Rglpk) +library(testthat) + +# Test that ROI.plugin.glpk solutions equal Rglpk solutions +context("Maximum Mean Return Portfolios: PortfolioAnalytics with ROI.plugin.glpk and Rglpk") + + +##### Data ##### +data(edhec) +R <- edhec[, 1:5] +funds <- colnames(R) + +##### Parameters ##### +m <- ncol(R) + +portf <- portfolio.spec(funds) +portf <- add.constraint(portf, type="full_investment") +portf <- add.constraint(portf, type="box", min=-Inf, max=Inf) +portf <- add.objective(portf, type="return", name="mean") + +# Linear part of objective function +objL <- -colMeans(R) + +# Constraints matrix +Amat <- matrix(1, nrow=1, ncol=m) + +# right hand side of constraints +rhs <- 1 + +# direction of inequality of constraints +dir <- "==" + +##### Long Only ##### +# Upper and lower bounds (i.e. box constraints) +lb <- rep(0, m) +ub <- rep(1, m) + +bnds <- list(lower = list(ind = seq.int(1L, m), val = lb), + upper = list(ind = seq.int(1L, m), val = ub)) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + +# Solve optimization with Rglpk +opt.glpk <- Rglpk_solve_LP(obj=objL, mat=Amat, dir=dir, rhs=rhs, bounds=bnds) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="glpk") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Long Only: PortfolioAnalytics and Rglpk solution weights are equal", { + expect_that(weights, equals(opt.glpk$solution[1:m])) +}) + +test_that("Long Only: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Long Only: Rglpk bounds are respected", { + expect_that(all(opt.glpk$solution[1:m] >= lb) & all(opt.glpk$solution[1:m] <= ub), is_true()) +}) + +test_that("Long Only: PortfolioAnalytics and Rglpk solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.glpk$optimum)) +}) + +##### Box ##### +# Upper and lower bounds (i.e. box constraints) +lb <- rep(0.05, m) +ub <- rep(0.55, m) + +bnds <- list(lower = list(ind = seq.int(1L, m), val = lb), + upper = list(ind = seq.int(1L, m), val = ub)) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + +# Solve optimization with Rglpk +opt.glpk <- Rglpk_solve_LP(obj=objL, mat=Amat, dir=dir, rhs=rhs, bounds=bnds) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="glpk") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Box: PortfolioAnalytics and Rglpk solution weights are equal", { + expect_that(weights, equals(opt.glpk$solution[1:m])) +}) + +test_that("Box: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Box: Rglpk bounds are respected", { + expect_that(all(opt.glpk$solution[1:m] >= lb) & all(opt.glpk$solution[1:m] <= ub), is_true()) +}) + +test_that("Box: PortfolioAnalytics and Rglpk solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.glpk$optimum)) +}) + +##### Box with Shorting ##### +# Upper and lower bounds (i.e. box constraints) +lb <- rep(-0.05, m) +ub <- rep(0.55, m) + +bnds <- list(lower = list(ind = seq.int(1L, m), val = lb), + upper = list(ind = seq.int(1L, m), val = ub)) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + +# Solve optimization with Rglpk +opt.glpk <- Rglpk_solve_LP(obj=objL, mat=Amat, dir=dir, rhs=rhs, bounds=bnds) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="glpk") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Box with Shorting: PortfolioAnalytics and Rglpk solution weights are equal", { + expect_that(weights, equals(opt.glpk$solution[1:m])) +}) + +test_that("Box with Shorting: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= lb) & all(weights <= ub), is_true()) +}) + +test_that("Box with Shorting: Rglpk bounds are respected", { + expect_that(all(opt.glpk$solution[1:m] >= lb) & all(opt.glpk$solution[1:m] <= ub), is_true()) +}) + +test_that("Box with Shorting: PortfolioAnalytics and Rglpk solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.glpk$optimum)) +}) + + Added: pkg/PortfolioAnalytics/inst/tests/test_glpk_minES.R =================================================================== --- pkg/PortfolioAnalytics/inst/tests/test_glpk_minES.R (rev 0) +++ pkg/PortfolioAnalytics/inst/tests/test_glpk_minES.R 2014-04-19 04:03:15 UTC (rev 3374) @@ -0,0 +1,153 @@ +library(PortfolioAnalytics) +library(ROI) +library(ROI.plugin.glpk) +library(Rglpk) +library(testthat) + +# Test that ROI.plugin.glpk solutions equal Rglpk solutions +context("Minimum ES Portfolios: PortfolioAnalytics with ROI.plugin.glpk and Rglpk") + + +##### Data ##### +data(edhec) +R <- edhec[, 1:5] +funds <- colnames(R) + +##### Parameters ##### +m <- ncol(R) +n <- nrow(R) +alpha <- 0.05 + +portf <- portfolio.spec(funds) +portf <- add.constraint(portf, type="full_investment") +portf <- add.constraint(portf, type="box", min=-Inf, max=Inf) +portf <- add.objective(portf, type="risk", name="ES", arguments=list(p=1-alpha)) + +# Linear part of objective function +objL <- c(rep(0, m), rep(1 / (alpha * n), n), 1) + +# Constraints matrix +Amat <- cbind(rbind(1, zoo::coredata(R)), + rbind(0, cbind(diag(n), 1))) + +# right hand side of constraints +rhs <- c(1, rep(0, n)) + +# direction of inequality of constraints +dir <- c("==", rep(">=", n)) + +##### Long Only ##### +# Upper and lower bounds (i.e. box constraints) +min_box <- rep(0, m) +max_box <- rep(1, m) + +lb <- c(min_box, rep(0, n), -1) +ub <- c(max_box, rep(Inf, n), 1) + +bnds <- list(lower = list(ind = seq.int(1L, m+n+1), val = lb), + upper = list(ind = seq.int(1L, m+n+1), val = ub)) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- min_box +portf$constraints[[2]]$max <- max_box + +# Solve optimization with Rglpk +opt.glpk <- Rglpk_solve_LP(obj=objL, mat=Amat, dir=dir, rhs=rhs, bounds=bnds) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="glpk") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Long Only: PortfolioAnalytics and Rglpk solution weights are equal", { + expect_that(weights, equals(opt.glpk$solution[1:m])) +}) + +test_that("Long Only: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= min_box) & all(weights <= max_box), is_true()) +}) + +test_that("Long Only: Rglpk bounds are respected", { + expect_that(all(opt.glpk$solution[1:m] >= min_box) & all(opt.glpk$solution[1:m] <= max_box), is_true()) +}) + +test_that("Long Only: PortfolioAnalytics and Rglpk solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.glpk$optimum)) +}) + +##### Box ##### +# Upper and lower bounds (i.e. box constraints) +min_box <- rep(0.05, m) +max_box <- rep(0.55, m) + +lb <- c(min_box, rep(0, n), -1) +ub <- c(max_box, rep(Inf, n), 1) + +bnds <- list(lower = list(ind = seq.int(1L, m+n+1), val = lb), + upper = list(ind = seq.int(1L, m+n+1), val = ub)) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- min_box +portf$constraints[[2]]$max <- max_box + +# Solve optimization with Rglpk +opt.glpk <- Rglpk_solve_LP(obj=objL, mat=Amat, dir=dir, rhs=rhs, bounds=bnds) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="glpk") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Box: PortfolioAnalytics and Rglpk solution weights are equal", { + expect_that(weights, equals(opt.glpk$solution[1:m])) +}) + +test_that("Box: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= min_box) & all(weights <= max_box), is_true()) +}) + +test_that("Box: Rglpk bounds are respected", { + expect_that(all(opt.glpk$solution[1:m] >= min_box) & all(opt.glpk$solution[1:m] <= max_box), is_true()) +}) + +test_that("Box: PortfolioAnalytics and Rglpk solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.glpk$optimum)) +}) + +##### Box with Shorting ##### +# Upper and lower bounds (i.e. box constraints) +min_box <- rep(-0.05, m) +max_box <- rep(0.55, m) + +lb <- c(min_box, rep(0, n), -1) +ub <- c(max_box, rep(Inf, n), 1) + +bnds <- list(lower = list(ind = seq.int(1L, m+n+1), val = lb), + upper = list(ind = seq.int(1L, m+n+1), val = ub)) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- min_box +portf$constraints[[2]]$max <- max_box + +# Solve optimization with Rglpk +opt.glpk <- Rglpk_solve_LP(obj=objL, mat=Amat, dir=dir, rhs=rhs, bounds=bnds) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="glpk") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Box with Shorting: PortfolioAnalytics and Rglpk solution weights are equal", { + expect_that(weights, equals(opt.glpk$solution[1:m])) +}) + +test_that("Box with Shorting: PortfolioAnalytics bounds are respected", { + expect_that(all(weights >= min_box) & all(weights <= max_box), is_true()) +}) + +test_that("Box with Shorting: Rglpk bounds are respected", { + expect_that(all(opt.glpk$solution[1:m] >= min_box) & all(opt.glpk$solution[1:m] <= max_box), is_true()) +}) + +test_that("Box with Shorting: PortfolioAnalytics and Rglpk solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.glpk$optimum)) +}) + + Added: pkg/PortfolioAnalytics/inst/tests/test_qp_gmv.R =================================================================== --- pkg/PortfolioAnalytics/inst/tests/test_qp_gmv.R (rev 0) +++ pkg/PortfolioAnalytics/inst/tests/test_qp_gmv.R 2014-04-19 04:03:15 UTC (rev 3374) @@ -0,0 +1,162 @@ +library(PortfolioAnalytics) +library(ROI) +library(ROI.plugin.quadprog) +library(quadprog) +library(testthat) + +# Test that PortfolioAnalytics with ROI.plugin.quadprog solutions equal quadprog solutions +context("GMV Portfolios: PortfolioAnalytics with ROI.plugin.quadprog and quadprog") + + +##### Data ##### +data(edhec) +R <- edhec[, 1:5] +funds <- colnames(R) +m <- ncol(R) + +##### Parameters ##### +portf <- portfolio.spec(funds) +portf <- add.constraint(portf, type="full_investment") +portf <- add.constraint(portf, type="box", min=-Inf, max=Inf) +portf <- add.objective(portf, type="risk", name="var") + +# Quadratic part of objective function +objQ <- 2 * cov(R) + +# Linear part of objective function +objL <- rep(0, m) + +# Constraints matrix +Amat <- matrix(1, nrow=1, ncol=m) + +# right hand side of constraints +rhs <- 1 + + +##### Unconstrained ##### + +# Solve optimization with quadprog +opt.qp <- solve.QP(Dmat=objQ, dvec=objL, Amat=t(Amat), bvec=rhs, meq=1) + +# Solve optimization with PortfolioAnalytics +opt.pa <- optimize.portfolio(R, portf, optimize_method="quadprog") +weights <- as.numeric(extractWeights(opt.pa)) + +test_that("Unconstrained: PortfolioAnalytics and quadprog solution weights are equal", { + expect_that(weights, equals(opt.qp$solution)) +}) + +test_that("Unconstrained: PortfolioAnalytics and quadprog solution objective values are equal", { + expect_that(opt.pa$out, equals(opt.qp$value)) +}) + +##### Long Only ##### +# Upper and lower bounds (i.e. box constraints) +lb <- rep(0, m) +ub <- rep(1, m) + +Amat <- rbind(1, diag(m), -diag(m)) +rhs <- c(1, lb, -ub) + +# Update box constraints in portfolio +portf$constraints[[2]]$min <- lb +portf$constraints[[2]]$max <- ub + [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/returnanalytics -r 3374 From noreply at r-forge.r-project.org Sun Apr 20 18:38:03 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 20 Apr 2014 18:38:03 +0200 (CEST) Subject: [Returnanalytics-commits] r3375 - in pkg/PortfolioAnalytics: . R man Message-ID: <20140420163803.6FA22186E01@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-20 18:38:03 +0200 (Sun, 20 Apr 2014) New Revision: 3375 Modified: pkg/PortfolioAnalytics/DESCRIPTION pkg/PortfolioAnalytics/R/optFUN.R pkg/PortfolioAnalytics/R/optimize.portfolio.R pkg/PortfolioAnalytics/man/etl_milp_opt.Rd pkg/PortfolioAnalytics/man/etl_opt.Rd pkg/PortfolioAnalytics/man/gmv_opt.Rd pkg/PortfolioAnalytics/man/gmv_opt_ptc.Rd pkg/PortfolioAnalytics/man/gmv_opt_toc.Rd pkg/PortfolioAnalytics/man/maxret_milp_opt.Rd pkg/PortfolioAnalytics/man/maxret_opt.Rd Log: Adding ROI.plugin.cplex to Suggests and support for control argument in ROI_solve Modified: pkg/PortfolioAnalytics/DESCRIPTION =================================================================== --- pkg/PortfolioAnalytics/DESCRIPTION 2014-04-19 04:03:15 UTC (rev 3374) +++ pkg/PortfolioAnalytics/DESCRIPTION 2014-04-20 16:38:03 UTC (rev 3375) @@ -25,6 +25,7 @@ ROI.plugin.glpk (>= 0.0.2), ROI.plugin.quadprog (>= 0.0.2), ROI.plugin.symphony (>= 0.0.2), + ROI.plugin.cplex (>= 0.0.2), pso, GenSA, corpcor, Modified: pkg/PortfolioAnalytics/R/optFUN.R =================================================================== --- pkg/PortfolioAnalytics/R/optFUN.R 2014-04-19 04:03:15 UTC (rev 3374) +++ pkg/PortfolioAnalytics/R/optFUN.R 2014-04-20 16:38:03 UTC (rev 3375) @@ -13,10 +13,12 @@ #' @param lambda_hhi concentration aversion parameter #' @param conc_groups list of vectors specifying the groups of the assets. #' @param solver solver to use +#' @param control list of solver control parameters #' @author Ross Bennett -gmv_opt <- function(R, constraints, moments, lambda, target, lambda_hhi, conc_groups, solver="quadprog"){ - stopifnot("package:ROI" %in% search() || require("ROI", quietly = TRUE)) - stopifnot("package:ROI.plugin.quadprog" %in% search() || require("ROI.plugin.quadprog", quietly = TRUE)) +gmv_opt <- function(R, constraints, moments, lambda, target, lambda_hhi, conc_groups, solver="quadprog", control=NULL){ + stopifnot("package:ROI" %in% search() || require("ROI", quietly=TRUE)) + plugin <- paste0("ROI.plugin.", solver) + stopifnot(paste0("package:", plugin) %in% search() || require(plugin, quietly=TRUE, character.only=TRUE)) # Check for cleaned returns in moments if(!is.null(moments$cleanR)) R <- moments$cleanR @@ -129,7 +131,7 @@ opt.prob <- OP(objective=ROI_objective, constraints=L_constraint(L=Amat, dir=dir.vec, rhs=rhs.vec), bounds=bnds) - result <- try(ROI_solve(x=opt.prob, solver=solver), silent=TRUE) + result <- try(ROI_solve(x=opt.prob, solver=solver, control=control), silent=TRUE) # result <- try(solve.QP(Dmat=Dmat, dvec=dvec, Amat=t(Amat), bvec=rhs.vec, meq=meq), silent=TRUE) if(inherits(x=result, "try-error")) stop(paste("No solution found:", result)) @@ -171,10 +173,12 @@ #' @param moments object of moments computed based on objective functions #' @param target target return value #' @param solver solver to use +#' @param control list of solver control parameters #' @author Ross Bennett -maxret_opt <- function(R, moments, constraints, target, solver="glpk"){ +maxret_opt <- function(R, moments, constraints, target, solver="glpk", control=NULL){ stopifnot("package:ROI" %in% search() || require("ROI",quietly = TRUE)) - stopifnot("package:ROI.plugin.glpk" %in% search() || require("ROI.plugin.glpk",quietly = TRUE)) + plugin <- paste0("ROI.plugin.", solver) + stopifnot(paste0("package:", plugin) %in% search() || require(plugin, quietly=TRUE, character.only=TRUE)) # Check for cleaned returns in moments if(!is.null(moments$cleanR)) R <- moments$cleanR @@ -235,7 +239,8 @@ opt.prob <- OP(objective=ROI_objective, constraints=L_constraint(L=Amat, dir=dir.vec, rhs=rhs.vec), bounds=bnds) - roi.result <- ROI_solve(x=opt.prob, solver=solver) + roi.result <- try(ROI_solve(x=opt.prob, solver=solver, control=control), silent=TRUE) + if(inherits(roi.result, "try-error")) stop(paste("No solution found:", roi.result)) # roi.result <- Rglpk_solve_LP(obj=objL, mat=Amat, dir=dir.vec, rhs=rhs.vec, bounds=bnds) @@ -276,10 +281,12 @@ #' @param moments object of moments computed based on objective functions #' @param target target return value #' @param solver solver to use +#' @param control list of solver control parameters #' @author Ross Bennett -maxret_milp_opt <- function(R, constraints, moments, target, solver="glpk"){ +maxret_milp_opt <- function(R, constraints, moments, target, solver="glpk", control=NULL){ stopifnot("package:ROI" %in% search() || require("ROI",quietly = TRUE)) - stopifnot("package:ROI.plugin.glpk" %in% search() || require("ROI.plugin.glpk",quietly = TRUE)) + plugin <- paste0("ROI.plugin.", solver) + stopifnot(paste0("package:", plugin) %in% search() || require(plugin, quietly=TRUE, character.only=TRUE)) # Check for cleaned returns in moments if(!is.null(moments$cleanR)) R <- moments$cleanR @@ -369,7 +376,7 @@ opt.prob <- OP(objective=ROI_objective, constraints=L_constraint(L=Amat, dir=dir, rhs=rhs), bounds=bnds, types=types) - roi.result <- try(ROI_solve(x=opt.prob, solver=solver), silent=TRUE) + roi.result <- try(ROI_solve(x=opt.prob, solver=solver, control=control), silent=TRUE) if(inherits(roi.result, "try-error")) stop(paste("No solution found:", roi.result)) # Weights @@ -400,10 +407,12 @@ #' @param target target return value #' @param alpha alpha value for ETL/ES/CVaR #' @param solver solver to use +#' @param control list of solver control parameters #' @author Ross Bennett -etl_opt <- function(R, constraints, moments, target, alpha, solver="glpk"){ +etl_opt <- function(R, constraints, moments, target, alpha, solver="glpk", control=NULL){ stopifnot("package:ROI" %in% search() || require("ROI",quietly = TRUE)) - stopifnot("package:ROI.plugin.glpk" %in% search() || require("ROI.plugin.glpk",quietly = TRUE)) + plugin <- paste0("ROI.plugin.", solver) + stopifnot(paste0("package:", plugin) %in% search() || require(plugin, quietly=TRUE, character.only=TRUE)) # Check for cleaned returns in moments if(!is.null(moments$cleanR)) R <- moments$cleanR @@ -456,7 +465,7 @@ opt.prob <- OP(objective=ROI_objective, constraints=L_constraint(L=Amat, dir=dir.vec, rhs=rhs.vec), bounds=bnds) - roi.result <- try(ROI_solve(x=opt.prob, solver=solver), silent=TRUE) + roi.result <- try(ROI_solve(x=opt.prob, solver=solver, control=control), silent=TRUE) if(inherits(x=roi.result, "try-error")) stop(paste("No solution found:", roi.result)) weights <- roi.result$solution[1:N] @@ -498,10 +507,12 @@ #' @param target target return value #' @param alpha alpha value for ETL/ES/CVaR #' @param solver solver to use +#' @param control list of solver control parameters #' @author Ross Bennett -etl_milp_opt <- function(R, constraints, moments, target, alpha, solver="glpk"){ +etl_milp_opt <- function(R, constraints, moments, target, alpha, solver="glpk", control=NULL){ stopifnot("package:ROI" %in% search() || require("ROI",quietly = TRUE)) - stopifnot("package:ROI.plugin.glpk" %in% search() || require("ROI.plugin.glpk",quietly = TRUE)) + plugin <- paste0("ROI.plugin.", solver) + stopifnot(paste0("package:", plugin) %in% search() || require(plugin, quietly=TRUE, character.only=TRUE)) # Check for cleaned returns in moments if(!is.null(moments$cleanR)) R <- moments$cleanR @@ -605,7 +616,8 @@ opt.prob <- OP(objective=ROI_objective, constraints=L_constraint(L=tmpAmat, dir=dir, rhs=rhs), bounds=bnds, types=types) - roi.result <- ROI_solve(x=opt.prob, solver=solver) + roi.result <- try(ROI_solve(x=opt.prob, solver=solver, control=control), silent=TRUE) + if(inherits(roi.result, "try-error")) stop(paste("No solution found:", roi.result)) # The Rglpk solvers status returns an an integer with status information # about the solution returned: 0 if the optimal solution was found, a @@ -654,12 +666,14 @@ #' @param target target return value #' @param init_weights initial weights to compute turnover #' @param solver solver to use +#' @param control list of solver control parameters #' @author Ross Bennett -gmv_opt_toc <- function(R, constraints, moments, lambda, target, init_weights, solver="quadprog"){ +gmv_opt_toc <- function(R, constraints, moments, lambda, target, init_weights, solver="quadprog", control=NULL){ # function for minimum variance or max quadratic utility problems stopifnot("package:corpcor" %in% search() || require("corpcor",quietly = TRUE)) stopifnot("package:ROI" %in% search() || require("ROI", quietly = TRUE)) - stopifnot("package:ROI.plugin.quadprog" %in% search() || require("ROI.plugin.quadprog", quietly = TRUE)) + plugin <- paste0("ROI.plugin.", solver) + stopifnot(paste0("package:", plugin) %in% search() || require(plugin, quietly=TRUE, character.only=TRUE)) # Check for cleaned returns in moments if(!is.null(moments$cleanR)) R <- moments$cleanR @@ -766,8 +780,7 @@ opt.prob <- OP(objective=ROI_objective, constraints=L_constraint(L=Amat, dir=dir, rhs=rhs)) - roi.result <- try(ROI_solve(x=opt.prob, solver=solver), silent=TRUE) - + roi.result <- try(ROI_solve(x=opt.prob, solver=solver, control=control), silent=TRUE) if(inherits(roi.result, "try-error")) stop(paste("No solution found:", roi.result)) wts <- roi.result$solution @@ -810,13 +823,15 @@ #' @param target target return value #' @param init_weights initial weights to compute turnover #' @param solver solver to use +#' @param control list of solver control parameters #' @author Ross Bennett -gmv_opt_ptc <- function(R, constraints, moments, lambda, target, init_weights, solver="quadprog"){ +gmv_opt_ptc <- function(R, constraints, moments, lambda, target, init_weights, solver="quadprog", control=NULL){ # function for minimum variance or max quadratic utility problems # modifying ProportionalCostOpt function from MPO package stopifnot("package:corpcor" %in% search() || require("corpcor", quietly = TRUE)) stopifnot("package:ROI" %in% search() || require("ROI", quietly = TRUE)) - stopifnot("package:ROI.plugin.quadprog" %in% search() || require("ROI.plugin.quadprog", quietly = TRUE)) + plugin <- paste0("ROI.plugin.", solver) + stopifnot(paste0("package:", plugin) %in% search() || require(plugin, quietly=TRUE, character.only=TRUE)) # Check for cleaned returns in moments if(!is.null(moments$cleanR)) R <- moments$cleanR @@ -911,8 +926,7 @@ opt.prob <- OP(objective=ROI_objective, constraints=L_constraint(L=Amat, dir=dir, rhs=rhs)) - roi.result <- try(ROI_solve(x=opt.prob, solver=solver), silent=TRUE) - + roi.result <- try(ROI_solve(x=opt.prob, solver=solver, control=control), silent=TRUE) if(inherits(roi.result, "try-error")) stop(paste("No solution found:", roi.result)) wts <- roi.result$solution @@ -948,31 +962,31 @@ # This function uses optimize() to find the target return value that # results in the maximum starr ratio (mean / ES). # returns the target return value -mean_etl_opt <- function(R, constraints, moments, alpha, solver){ +mean_etl_opt <- function(R, constraints, moments, alpha, solver, control){ # create a copy of the moments that can be modified tmp_moments <- moments # Find the maximum return if(!is.null(constraints$max_pos)){ - max_ret <- maxret_milp_opt(R=R, constraints=constraints, moments=moments, target=NA, solver=solver) + max_ret <- maxret_milp_opt(R=R, constraints=constraints, moments=moments, target=NA, solver=solver, control=control) } else { - max_ret <- maxret_opt(R=R, moments=moments, constraints=constraints, target=NA, solver=solver) + max_ret <- maxret_opt(R=R, moments=moments, constraints=constraints, target=NA, solver=solver, control=control) } max_mean <- as.numeric(-max_ret$out) # Find the minimum return tmp_moments$mean <- -1 * moments$mean if(!is.null(constraints$max_pos)){ - min_ret <- maxret_milp_opt(R=R, constraints=constraints, moments=tmp_moments, target=NA, solver=solver) + min_ret <- maxret_milp_opt(R=R, constraints=constraints, moments=tmp_moments, target=NA, solver=solver, control=control) } else { - min_ret <- maxret_opt(R=R, constraints=constraints, moments=tmp_moments, target=NA, solver=solver) + min_ret <- maxret_opt(R=R, constraints=constraints, moments=tmp_moments, target=NA, solver=solver, control=control) } min_mean <- as.numeric(min_ret$out) # use optimize() to find the target return value that maximizes sharpe ratio opt <- try(optimize(f=starr_obj_fun, R=R, constraints=constraints, solver=solver, moments=moments, alpha=alpha, - lower=min_mean, upper=max_mean, + lower=min_mean, upper=max_mean, control=control, maximum=TRUE, tol=.Machine$double.eps), silent=TRUE) if(inherits(opt, "try-error")){ @@ -984,13 +998,15 @@ # Function to calculate the starr ratio. # Used as the objective function for optimize() -starr_obj_fun <- function(target_return, R, constraints, moments, alpha, solver){ +starr_obj_fun <- function(target_return, R, constraints, moments, alpha, solver, control){ if(!is.null(constraints$max_pos)){ opt <- etl_milp_opt(R=R, constraints=constraints, moments=moments, - target=target_return, alpha=alpha, solver=solver) + target=target_return, alpha=alpha, solver=solver, + control=control) } else { opt <- etl_opt(R=R, constraints=constraints, moments=moments, - target=target_return, alpha=alpha, solver=solver) + target=target_return, alpha=alpha, solver=solver, + control=control) } weights <- matrix(opt$weights, ncol=1) opt_mean <- as.numeric(t(weights) %*% matrix(moments$mean, ncol=1)) @@ -1132,10 +1148,10 @@ # Function to calculate the sharpe ratio. # Used as the objective function for optimize() -sharpe_obj_fun <- function(target_return, R, constraints, moments, lambda_hhi=NULL, conc_groups=NULL, solver="quadprog"){ +sharpe_obj_fun <- function(target_return, R, constraints, moments, lambda_hhi=NULL, conc_groups=NULL, solver="quadprog", control=control){ opt <- gmv_opt(R=R, constraints=constraints, moments=moments, lambda=1, - target=target_return, lambda_hhi=lambda_hhi, - conc_groups=conc_groups, solver=solver) + target=target_return, lambda_hhi=lambda_hhi, + conc_groups=conc_groups, solver=solver, control=control) weights <- opt$weights opt_mean <- as.numeric(t(weights) %*% matrix(moments$mean, ncol=1)) opt_sd <- as.numeric(sqrt(t(weights) %*% moments$var %*% weights)) @@ -1146,25 +1162,25 @@ # This function uses optimize() to find the target return value that # results in the maximum sharpe ratio (mean / sd). # returns the target return value -max_sr_opt <- function(R, constraints, moments, lambda_hhi, conc_groups, solver){ +max_sr_opt <- function(R, constraints, moments, lambda_hhi, conc_groups, solver, control){ # create a copy of the moments that can be modified tmp_moments <- moments # Find the maximum return max_ret <- maxret_opt(R=R, moments=moments, constraints=constraints, - target=NA, solver="glpk") + target=NA, solver=solver, control=control) max_mean <- as.numeric(-max_ret$out) # Find the minimum return tmp_moments$mean <- -1 * moments$mean min_ret <- maxret_opt(R=R, moments=tmp_moments, constraints=constraints, - target=NA, solver="glpk") + target=NA, solver=solver, control=control) min_mean <- as.numeric(min_ret$out) # use optimize() to find the target return value that maximizes sharpe ratio opt <- try(optimize(f=sharpe_obj_fun, R=R, constraints=constraints, solver=solver, lambda_hhi=lambda_hhi, - conc_groups=conc_groups, moments=moments, + conc_groups=conc_groups, moments=moments, control=control, lower=min_mean, upper=max_mean, maximum=TRUE, tol=.Machine$double.eps), silent=TRUE) Modified: pkg/PortfolioAnalytics/R/optimize.portfolio.R =================================================================== --- pkg/PortfolioAnalytics/R/optimize.portfolio.R 2014-04-19 04:03:15 UTC (rev 3374) +++ pkg/PortfolioAnalytics/R/optimize.portfolio.R 2014-04-20 16:38:03 UTC (rev 3375) @@ -757,8 +757,11 @@ roi_solvers <- c("ROI", "quadprog", "glpk", "symphony", "ipop", "cplex") if(optimize_method %in% roi_solvers){ + # check for a control argument for list of solver control arguments + if(hasArg(control)) control=match.call(expand.dots=TRUE)$control else control=NULL + # This takes in a regular portfolio object and extracts the constraints and - # objectives and converts them for input. to a closed form solver using + # objectives and converts them for input. to a closed form solver using # ROI as an interface. moments <- list(mean=rep(0, N)) alpha <- 0.05 @@ -840,14 +843,14 @@ constraints$ptc <- NULL } if(!is.null(constraints$turnover_target) & is.null(constraints$ptc)){ - qp_result <- gmv_opt_toc(R=R, constraints=constraints, moments=moments, lambda=lambda, target=target, init_weights=portfolio$assets, solver=solver) + qp_result <- gmv_opt_toc(R=R, constraints=constraints, moments=moments, lambda=lambda, target=target, init_weights=portfolio$assets, solver=solver, control=control) weights <- qp_result$weights # obj_vals <- constrained_objective(w=weights, R=R, portfolio, trace=TRUE, normalize=FALSE)$objective_measures obj_vals <- qp_result$obj_vals out <- list(weights=weights, objective_measures=obj_vals, opt_values=obj_vals, out=qp_result$out, call=call) } if(!is.null(constraints$ptc) & is.null(constraints$turnover_target)){ - qp_result <- gmv_opt_ptc(R=R, constraints=constraints, moments=moments, lambda=lambda, target=target, init_weights=portfolio$assets, solver=solver) + qp_result <- gmv_opt_ptc(R=R, constraints=constraints, moments=moments, lambda=lambda, target=target, init_weights=portfolio$assets, solver=solver, control=control) weights <- qp_result$weights # obj_vals <- constrained_objective(w=weights, R=R, portfolio, trace=TRUE, normalize=FALSE)$objective_measures obj_vals <- qp_result$obj_vals @@ -857,12 +860,12 @@ # if(hasArg(ef)) ef=match.call(expand.dots=TRUE)$ef else ef=FALSE if(hasArg(maxSR)) maxSR=match.call(expand.dots=TRUE)$maxSR else maxSR=FALSE if(maxSR){ - target <- max_sr_opt(R=R, constraints=constraints, moments=moments, lambda_hhi=lambda_hhi, conc_groups=conc_groups, solver=solver) + target <- max_sr_opt(R=R, constraints=constraints, moments=moments, lambda_hhi=lambda_hhi, conc_groups=conc_groups, solver=solver, control=control) # need to set moments$mean=0 here because quadratic utility and target return is sensitive to returning no solution tmp_moments_mean <- moments$mean moments$mean <- rep(0, length(moments$mean)) } - roi_result <- gmv_opt(R=R, constraints=constraints, moments=moments, lambda=lambda, target=target, lambda_hhi=lambda_hhi, conc_groups=conc_groups, solver=solver) + roi_result <- gmv_opt(R=R, constraints=constraints, moments=moments, lambda=lambda, target=target, lambda_hhi=lambda_hhi, conc_groups=conc_groups, solver=solver, control=control) weights <- roi_result$weights # obj_vals <- constrained_objective(w=weights, R=R, portfolio, trace=TRUE, normalize=FALSE)$objective_measures obj_vals <- roi_result$obj_vals @@ -887,14 +890,14 @@ # Maximize return if the only objective specified is mean if(!is.null(constraints$max_pos) | !is.null(constraints$leverage)) { # This is an MILP problem if max_pos is specified as a constraint - roi_result <- maxret_milp_opt(R=R, constraints=constraints, moments=moments, target=target, solver=solver) + roi_result <- maxret_milp_opt(R=R, constraints=constraints, moments=moments, target=target, solver=solver, control=control) weights <- roi_result$weights # obj_vals <- constrained_objective(w=weights, R=R, portfolio, trace=TRUE, normalize=FALSE)$objective_measures obj_vals <- roi_result$obj_vals out <- list(weights=weights, objective_measures=obj_vals, opt_values=obj_vals, out=roi_result$out, call=call) } else { # Maximize return LP problem - roi_result <- maxret_opt(R=R, constraints=constraints, moments=moments, target=target, solver=solver) + roi_result <- maxret_opt(R=R, constraints=constraints, moments=moments, target=target, solver=solver, control=control) weights <- roi_result$weights # obj_vals <- constrained_objective(w=weights, R=R, portfolio, trace=TRUE, normalize=FALSE)$objective_measures obj_vals <- roi_result$obj_vals @@ -918,12 +921,12 @@ # Minimize sample ETL/ES/CVaR if CVaR, ETL, or ES is specified as an objective if(length(moments) == 2 & all(moments$mean != 0) & ef==FALSE & maxSTARR){ # This is called by meanetl.efficient.frontier and we do not want that for efficient frontiers, need to have ef==FALSE - target <- mean_etl_opt(R=R, constraints=constraints, moments=moments, alpha=alpha, solver=solver) + target <- mean_etl_opt(R=R, constraints=constraints, moments=moments, alpha=alpha, solver=solver, control=control) meanetl <- TRUE } if(!is.null(constraints$max_pos)) { # This is an MILP problem if max_pos is specified as a constraint - roi_result <- etl_milp_opt(R=R, constraints=constraints, moments=moments, target=target, alpha=alpha, solver=solver) + roi_result <- etl_milp_opt(R=R, constraints=constraints, moments=moments, target=target, alpha=alpha, solver=solver, control=control) weights <- roi_result$weights # obj_vals <- constrained_objective(w=weights, R=R, portfolio, trace=TRUE, normalize=FALSE)$objective_measures # obj_vals <- roi_result$obj_vals @@ -934,7 +937,7 @@ out <- list(weights=weights, objective_measures=obj_vals, opt_values=obj_vals, out=roi_result$out, call=call) } else { # Minimize sample ETL/ES/CVaR LP Problem - roi_result <- etl_opt(R=R, constraints=constraints, moments=moments, target=target, alpha=alpha, solver=solver) + roi_result <- etl_opt(R=R, constraints=constraints, moments=moments, target=target, alpha=alpha, solver=solver, control=control) weights <- roi_result$weights # obj_vals <- constrained_objective(w=weights, R=R, portfolio, trace=TRUE, normalize=FALSE)$objective_measures # obj_vals <- roi_result$obj_vals Modified: pkg/PortfolioAnalytics/man/etl_milp_opt.Rd =================================================================== --- pkg/PortfolioAnalytics/man/etl_milp_opt.Rd 2014-04-19 04:03:15 UTC (rev 3374) +++ pkg/PortfolioAnalytics/man/etl_milp_opt.Rd 2014-04-20 16:38:03 UTC (rev 3375) @@ -3,7 +3,7 @@ \title{Minimum ETL MILP Optimization} \usage{ etl_milp_opt(R, constraints, moments, target, alpha, - solver = "glpk") + solver = "glpk", control = NULL) } \arguments{ \item{R}{xts object of asset returns} @@ -19,6 +19,8 @@ \item{alpha}{alpha value for ETL/ES/CVaR} \item{solver}{solver to use} + + \item{control}{list of solver control parameters} } \description{ This function is called by optimize.portfolio to solve Modified: pkg/PortfolioAnalytics/man/etl_opt.Rd =================================================================== --- pkg/PortfolioAnalytics/man/etl_opt.Rd 2014-04-19 04:03:15 UTC (rev 3374) +++ pkg/PortfolioAnalytics/man/etl_opt.Rd 2014-04-20 16:38:03 UTC (rev 3375) @@ -3,7 +3,7 @@ \title{Minimum ETL LP Optimization} \usage{ etl_opt(R, constraints, moments, target, alpha, - solver = "glpk") + solver = "glpk", control = NULL) } \arguments{ \item{R}{xts object of asset returns} @@ -19,6 +19,8 @@ \item{alpha}{alpha value for ETL/ES/CVaR} \item{solver}{solver to use} + + \item{control}{list of solver control parameters} } \description{ This function is called by optimize.portfolio to solve Modified: pkg/PortfolioAnalytics/man/gmv_opt.Rd =================================================================== --- pkg/PortfolioAnalytics/man/gmv_opt.Rd 2014-04-19 04:03:15 UTC (rev 3374) +++ pkg/PortfolioAnalytics/man/gmv_opt.Rd 2014-04-20 16:38:03 UTC (rev 3375) @@ -3,7 +3,8 @@ \title{GMV/QU QP Optimization} \usage{ gmv_opt(R, constraints, moments, lambda, target, - lambda_hhi, conc_groups, solver = "quadprog") + lambda_hhi, conc_groups, solver = "quadprog", + control = NULL) } \arguments{ \item{R}{xts object of asset returns} @@ -24,6 +25,8 @@ of the assets.} \item{solver}{solver to use} + + \item{control}{list of solver control parameters} } \description{ This function is called by optimize.portfolio to solve Modified: pkg/PortfolioAnalytics/man/gmv_opt_ptc.Rd =================================================================== --- pkg/PortfolioAnalytics/man/gmv_opt_ptc.Rd 2014-04-19 04:03:15 UTC (rev 3374) +++ pkg/PortfolioAnalytics/man/gmv_opt_ptc.Rd 2014-04-20 16:38:03 UTC (rev 3375) @@ -3,7 +3,7 @@ \title{GMV/QU QP Optimization with Proportional Transaction Cost Constraint} \usage{ gmv_opt_ptc(R, constraints, moments, lambda, target, - init_weights, solver = "quadprog") + init_weights, solver = "quadprog", control = NULL) } \arguments{ \item{R}{xts object of asset returns} @@ -21,6 +21,8 @@ \item{init_weights}{initial weights to compute turnover} \item{solver}{solver to use} + + \item{control}{list of solver control parameters} } \description{ This function is called by optimize.portfolio to solve Modified: pkg/PortfolioAnalytics/man/gmv_opt_toc.Rd =================================================================== --- pkg/PortfolioAnalytics/man/gmv_opt_toc.Rd 2014-04-19 04:03:15 UTC (rev 3374) +++ pkg/PortfolioAnalytics/man/gmv_opt_toc.Rd 2014-04-20 16:38:03 UTC (rev 3375) @@ -3,7 +3,7 @@ \title{GMV/QU QP Optimization with Turnover Constraint} \usage{ gmv_opt_toc(R, constraints, moments, lambda, target, - init_weights, solver = "quadprog") + init_weights, solver = "quadprog", control = NULL) } \arguments{ \item{R}{xts object of asset returns} @@ -21,6 +21,8 @@ \item{init_weights}{initial weights to compute turnover} \item{solver}{solver to use} + + \item{control}{list of solver control parameters} } \description{ This function is called by optimize.portfolio to solve Modified: pkg/PortfolioAnalytics/man/maxret_milp_opt.Rd =================================================================== --- pkg/PortfolioAnalytics/man/maxret_milp_opt.Rd 2014-04-19 04:03:15 UTC (rev 3374) +++ pkg/PortfolioAnalytics/man/maxret_milp_opt.Rd 2014-04-20 16:38:03 UTC (rev 3375) @@ -3,7 +3,7 @@ \title{Maximum Return MILP Optimization} \usage{ maxret_milp_opt(R, constraints, moments, target, - solver = "glpk") + solver = "glpk", control = NULL) } \arguments{ \item{R}{xts object of asset returns} @@ -17,6 +17,8 @@ \item{target}{target return value} \item{solver}{solver to use} + + \item{control}{list of solver control parameters} } \description{ This function is called by optimize.portfolio to solve Modified: pkg/PortfolioAnalytics/man/maxret_opt.Rd =================================================================== --- pkg/PortfolioAnalytics/man/maxret_opt.Rd 2014-04-19 04:03:15 UTC (rev 3374) +++ pkg/PortfolioAnalytics/man/maxret_opt.Rd 2014-04-20 16:38:03 UTC (rev 3375) @@ -3,7 +3,7 @@ \title{Maximum Return LP Optimization} \usage{ maxret_opt(R, moments, constraints, target, - solver = "glpk") + solver = "glpk", control = NULL) } \arguments{ \item{R}{xts object of asset returns} @@ -17,6 +17,8 @@ \item{target}{target return value} \item{solver}{solver to use} + + \item{control}{list of solver control parameters} } \description{ This function is called by optimize.portfolio to solve From noreply at r-forge.r-project.org Mon Apr 21 05:48:01 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 21 Apr 2014 05:48:01 +0200 (CEST) Subject: [Returnanalytics-commits] r3376 - pkg/PortfolioAnalytics/R Message-ID: <20140421034801.E7804186B46@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-21 05:47:59 +0200 (Mon, 21 Apr 2014) New Revision: 3376 Modified: pkg/PortfolioAnalytics/R/extract.efficient.frontier.R Log: Adding check for hhi objective in mean-var efficient frontier Modified: pkg/PortfolioAnalytics/R/extract.efficient.frontier.R =================================================================== --- pkg/PortfolioAnalytics/R/extract.efficient.frontier.R 2014-04-20 16:38:03 UTC (rev 3375) +++ pkg/PortfolioAnalytics/R/extract.efficient.frontier.R 2014-04-21 03:47:59 UTC (rev 3376) @@ -101,15 +101,24 @@ var_idx <- which(unlist(lapply(portfolio$objectives, function(x) x$name)) %in% c("var", "StdDev", "sd")) if(length(var_idx) >= 1){ # the portfolio object has a var, StdDev, or sd objective - var_obj <- portfolio$objectives[[var_idx]] + var_obj <- portfolio$objectives[[var_idx[1]]] } else { var_obj <- portfolio_risk_objective(name="var") } + hhi_idx <- which(unlist(lapply(portfolio$objectives, function(x) x$name)) == "HHI") + if(length(hhi_idx) >= 1){ + # the portfolio object has an HHI objective + hhi_obj <- portfolio$objectives[[hhi_idx[1]]] + } else { + hhi_obj <- NULL + } + # Clear out the objectives in portfolio and add them here to simplify checks # and so we can control the optimization along the efficient frontier. portfolio$objectives <- list() portfolio$objectives[[1]] <- var_obj + portfolio$objectives[[2]] <- hhi_obj portfolio <- add.objective(portfolio=portfolio, type="return", name="mean") # If the user has passed in a portfolio object with return_constraint, we need to disable it @@ -123,11 +132,14 @@ var_idx <- which(unlist(lapply(portfolio$objectives, function(x) x$name)) %in% c("var", "StdDev", "sd")) # get the index number of the mean objective mean_idx <- which(unlist(lapply(portfolio$objectives, function(x) x$name)) == "mean") + # get the index number of the hhi objective + hhi_idx <- which(unlist(lapply(portfolio$objectives, function(x) x$name)) == "HHI") ##### get the maximum return ##### - # Disable the risk objective + # Disable the risk objective and hhi objective if applicable portfolio$objectives[[var_idx]]$enabled <- FALSE + if(length(hhi_idx) >= 1) portfolio$objectives[[hhi_idx]]$enabled <- FALSE # run the optimization to get the maximum return tmp <- optimize.portfolio(R=R, portfolio=portfolio, optimize_method="ROI", ...=...) @@ -139,8 +151,9 @@ # Disable the return objective portfolio$objectives[[mean_idx]]$enabled <- FALSE - # Enable the risk objective + # Enable the risk objective and hhi objective if applicable portfolio$objectives[[var_idx]]$enabled <- TRUE + if(length(hhi_idx) >= 1) portfolio$objectives[[hhi_idx]]$enabled <- TRUE # Run the optimization to get the global minimum variance portfolio with the # given constraints. @@ -208,7 +221,7 @@ etl_idx <- which(unlist(lapply(portfolio$objectives, function(x) x$name)) %in% c("ETL", "ES", "CVaR")) if(length(etl_idx) >= 1){ # the portfolio object has a ETL, ES, CVaR objective - etl_obj <- portfolio$objectives[[etl_idx]] + etl_obj <- portfolio$objectives[[etl_idx[1]]] } else { etl_obj <- portfolio_risk_objective(name="ES", arguments=list(p=0.95)) } From noreply at r-forge.r-project.org Sun Apr 27 04:53:28 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 27 Apr 2014 04:53:28 +0200 (CEST) Subject: [Returnanalytics-commits] r3377 - in pkg/PortfolioAnalytics/sandbox/RFinance2014: . R Message-ID: <20140427025328.DF851186FE5@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-27 04:53:24 +0200 (Sun, 27 Apr 2014) New Revision: 3377 Added: pkg/PortfolioAnalytics/sandbox/RFinance2014/R/charting.R Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/makefile pkg/PortfolioAnalytics/sandbox/RFinance2014/optimization_analysis.R pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.md pkg/PortfolioAnalytics/sandbox/RFinance2014/slides.pdf pkg/PortfolioAnalytics/sandbox/RFinance2014/slidy_presentation.html Log: Updating presentation Added: pkg/PortfolioAnalytics/sandbox/RFinance2014/R/charting.R =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/R/charting.R (rev 0) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/R/charting.R 2014-04-27 02:53:24 UTC (rev 3377) @@ -0,0 +1,99 @@ +nvd3WeightsPlot <- function(object, + type=c("stackedAreaChart", "multiBarChart") + ){ + type <- match.arg(type) + + # extract the weights and turn into a data.frame + weights <- extractWeights(object) + weights.df <- reshape2::melt( + data.frame(date=format(index(weights)), weights), + id.vars = 1, + variable.name = "stock", + value.name = "weight" + ) + weights.df$date <- as.Date(weights.df$date) + + # plot + n1 <- rCharts::nPlot( + weight ~ date, + group = "stock", + data = weights.df, + type = type + ) + n1$xAxis( + tickFormat = "#!function(d){ + return d3.time.format('%b %Y')(new Date(d * 24 * 60 * 60 * 1000)) + }!#" + ) + n1$yAxis( + tickFormat = "#!function(d){ + return d3.format('0.2%')(d) + }!#" + ) + return(n1) +} + +nvd3RiskPlot <- function(object, + type=c("stackedAreaChart", "multiBarChart") + ){ + type <- match.arg(type) + + # extract the risk budget pct_contrib and turn into a data.frame + tmp <- extractObjectiveMeasures(object) + rb <- tmp[,grep("pct_contrib", colnames(tmp))] + colnames(rb) <- gsub("^.*\\.", "", colnames(rb)) + rb.df <- reshape2::melt( + data.frame(date=as.Date(format(index(rb))), rb), + id.vars = 1, + variable.name = "fund", + value.name = "risk" + ) + + # plot + n1 <- rCharts::nPlot( + risk ~ date, + group = "fund", + data = rb.df, + type = type + ) + n1$xAxis( + tickFormat = "#!function(d){ + return d3.time.format('%b %Y')(new Date(d * 24 * 60 * 60 * 1000)) + }!#" + ) + n1$yAxis( + tickFormat = "#!function(d){ + return d3.format('0.2%')(d) + }!#" + ) + return(n1) +} + +# require(rCharts) +# weights <- extractWeights(opt.minVarSample) +# weights.df <- reshape2::melt( +# data.frame( +# date=format(index(weights)), +# weights +# ), +# id.vars = 1, +# variable.name = "stock", +# value.name = "weight" +# ) +# +# d1 <- dPlot( +# weight ~ date, +# groups = "stock", +# data = weights.df, +# type = "bubble" #area, bar, or bubble +# ) +# d1$xAxis( +# type = "addTimeAxis", +# inputFormat = "%Y-%m-%d", +# outputFormat = "%b %Y" +# ) +# d1$yAxis( +# outputFormat = "0.2%", +# orderBy = "weight" +# ) +# d1 \ No newline at end of file Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/makefile =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/makefile 2014-04-21 03:47:59 UTC (rev 3376) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/makefile 2014-04-27 02:53:24 UTC (rev 3377) @@ -13,8 +13,12 @@ # Generate slidy presentation from markdown file slidy_presentation.html: $(RFILES) $(OUT_FILES) presentation.md - pandoc -t slidy -s presentation.md -o slidy_presentation.html + pandoc -t slidy -s --mathjax presentation.md -o slidy_presentation.html +# Generate slidy presentation from markdown file +slides.pdf: $(RFILES) $(OUT_FILES) presentation.md + pandoc -t -S beamer ?-slide-level 2 presentation.md -o slides.pdf + # Generate markdown file from R markdown file presentation.md: presentation.Rmd Rscript -e "library(knitr); knit('presentation.Rmd')" @@ -38,6 +42,9 @@ lwShrink.Rout: R/lwShrink.R R CMD BATCH --vanilla R/lwShrink.R +charting.Rout: R/charting.R + R CMD BATCH --vanilla R/charting.R + # Use Rscript to run the necessary R files as an alternative to R CMD BATCH runR: Rscript data_prep.R @@ -52,4 +59,5 @@ rm -f optimization_results/*.rda rm -f *.md rm -f *.html + rm -f cache/* \ No newline at end of file Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/optimization_analysis.R =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/optimization_analysis.R 2014-04-21 03:47:59 UTC (rev 3376) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/optimization_analysis.R 2014-04-27 02:53:24 UTC (rev 3377) @@ -1,6 +1,8 @@ library(PortfolioAnalytics) library(methods) +source("R/charting.R") + # Set the directory where the optimization results are saved results.dir <- "optimization_results" figures.dir <- "optimization_figures" @@ -15,10 +17,17 @@ chart.Weights(opt.minVarSample, main="minVarSample Weights", legend.loc=NULL) dev.off() +w1 <- nvd3WeightsPlot(opt.minVarSample) +save(w1, file=paste(figures.dir, "w1.rda", sep="/")) + + png(paste(figures.dir, "weights_minVarLW.png", sep="/")) chart.Weights(opt.minVarLW, main="minVarLW Weights", legend.loc=NULL) dev.off() +w2 <- nvd3WeightsPlot(opt.minVarLW) +save(w2, file=paste(figures.dir, "w2.rda", sep="/")) + # Compute the returns and chart the performance summary ret.minVarSample <- summary(opt.minVarSample)$portfolio_returns ret.minVarRobust <- summary(opt.minVarLW)$portfolio_returns @@ -65,8 +74,9 @@ # plot the feasible space par(mar=c(7,4,4,1)+0.1) plot(xtract.ES, xtract.mean, col="gray", + main="Minimum ES Portfolios", xlab="ES", ylab="Mean", - ylim=c(0.005, 0.008), + ylim=c(0.005, 0.007), xlim=c(0.015, 0.085)) # min ES @@ -92,7 +102,7 @@ text(x=opt.minES[[3]]$objective_measures$ES$MES, y=opt.minES[[3]]$objective_measures$mean, labels="Min ES EqRB", pos=4, col="darkgreen", cex=0.8) -# par(mar=c(7,4,4,1)+0.1) +par(mar=c(5,4,4,1)+0.1) dev.off() # Chart the risk contribution @@ -146,6 +156,13 @@ charts.PerformanceSummary(ret.bt.opt) dev.off() +### +# interactive plot of risk budgets through time using nvd3 +# nvd3RiskPlot(bt.opt.minES[[1]]) +# nvd3RiskPlot(bt.opt.minES[[2]]) +# nvd3RiskPlot(bt.opt.minES[[3]]) +### + ##### Example 4 ##### load(file=paste(results.dir, "opt.crra.rda", sep="/")) load(file=paste(results.dir, "bt.opt.crra.rda", sep="/")) Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R 2014-04-21 03:47:59 UTC (rev 3376) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/optimize.R 2014-04-27 02:53:24 UTC (rev 3377) @@ -62,8 +62,8 @@ # Add constraints # weights sum to 1 portf.minvar <- add.constraint(portf.init, type="full_investment") -# box constraints such that no stock has weight less than 1% or greater than 20% -portf.minvar <- add.constraint(portf.minvar, type="box", min=0.01, max=0.2) +# box constraints +portf.minvar <- add.constraint(portf.minvar, type="box", min=0.01, max=0.45) # Add objective # objective to minimize portfolio variance @@ -368,7 +368,15 @@ x.assets <- StdDev(R) y.assets <- colMeans(R) - + ### + # create an interactive plot using rCharts and nvd3 scatterChart + # tmp1 <- data.frame(name="sample", mean=rp1_mean, sd=rp1_StdDev) + # tmp2 <- data.frame(name="simplex", mean=rp2_mean, sd=rp2_StdDev) + # tmp3 <- data.frame(name="grid", mean=rp3_mean, sd=rp3_StdDev) + # tmp <- rbind(tmp1, tmp2, tmp3) + # n1 <- nPlot(mean ~ sd, group="name", data=tmp, type="scatterChart") + # n1 + ### x.lower <- min(x.assets) * 0.9 x.upper <- max(x.assets) * 1.1 y.lower <- min(y.assets) * 0.9 Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd 2014-04-21 03:47:59 UTC (rev 3376) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.Rmd 2014-04-27 02:53:24 UTC (rev 3377) @@ -1,14 +1,32 @@ -% R/Finance 2014: Complex Portfolio Optimization with PortfolioAnalytics -% Ross Bennett -% May 16, 2014 +--- +title : Complex Portfolio Optimization with PortfolioAnalytics +subtitle : R/Finance 2014 +author : Ross Bennett +date : May 16, 2014 +--- -# Overview +```{r, echo=FALSE, message=FALSE} +library(PortfolioAnalytics) +``` + + +## Overview * Discuss Portfolio Optimization * Introduce PortfolioAnalytics * Demonstrate PortfolioAnalytics with Examples -# Portfolio Optimization + +--- + ## Modern Portfolio Theory "Modern" Portfolio Theory (MPT) was introduced by Harry Markowitz in 1952. @@ -22,9 +40,11 @@ How do we define risk? What about more complex objectives? +--- + ## Portfolio Optimization Objectives * Minimize Risk * Volatility @@ -43,10 +63,9 @@ The challenge here is knowing what solver to use and the capabilities/limits of the chosen solver. Talk about pros/cons of closed-form solvers vs. global solvers and what objectives can be solved. --> -# PortfolioAnalytics +--- -## Overview - +## PortfolioAnalytics Overview PortfolioAnalytics is an R package designed to provide numerical solutions and visualizations for portfolio optimization problems with complex constraints and objectives. * Support for multiple constraint and objective types @@ -69,9 +88,9 @@ - Periodic rebalancing and analyzing out of sample performance will help refine objectives and constraints --> +--- ## Support Multiple Solvers - Linear and Quadratic Programming Solvers * R Optimization Infrastructure (ROI) @@ -90,6 +109,8 @@ Brief explanation of each solver and what optimization problems (constraints and objectives) are supported --> +--- + ## Random Portfolios PortfolioAnalytics has three methods to generate random portfolios. @@ -107,18 +128,25 @@ The grid method to generate random portfolios is based on the gridSearch function in NMOF package. The grid search method only satisfies the min and max box constraints. The min_sum and max_sum leverage constraint will likely be violated and the weights in the random portfolios should be normalized. Normalization may cause the box constraints to be violated and will be penalized in constrained_objective. --> +--- + ## Comparison of Random Portfolio Methods ![](optimization_figures/rp_plot.png) + + +--- + ## Random Portfolios: Simplex Method ![](optimization_figures/fev_plot.png) +--- ## Workflow -TODO: Add a nice graphic here (Guy might have one) +![](misc_figures/workflow.png) -Specify a Portfolio --> Add Constraints --> Add Objectives --> Run Optimization --> Analyze Results - +--- -# Example 1 +## Workflow: Specify Portfolio +```{r} +args(portfolio.spec) +``` -## Data Setup +--- + +## Workflow: Add Constraints +```{r} +args(add.constraint) +``` + +Supported Constraint Types + +* Sum of Weights +* Box +* Group +* Turnover +* Diversification +* Position Limit +* Return +* Factor Exposure + +--- + +## Workflow: Add Objectives +```{r} +args(add.objective) +``` + +Supported Objective types + +* Return +* Risk +* Risk Budget +* Weight Concentration + +--- + +## Workflow: Run Optimization +```{r} +args(optimize.portfolio) +args(optimize.portfolio.rebalancing) +``` + +Supported Optimization Methods + +* ROI +* random +* DEoptim +* pso +* GenSA + +--- + +## Workflow: Analyze Results + +Charting Functions + +* plot +* chart.Concentration +* chart.EfficientFrontier +* chart.RiskBudget +* chart.RiskReward +* chart.Weights + +Extract Functions + +* extractObjectiveMeasures +* extractStats +* extractWeights + + + +--- + +## Example 1: Data Setup Here we will look at portfolio optimization in the context of stocks. * Selection of large cap, mid cap, and small cap stocks from CRSP data @@ -145,16 +250,26 @@ smallcap_weekly[,1:5]) ``` +--- + ## Distribution of Monthly Returns ![](data_figures/equity_box.png) +--- + ## Minimum Variance Portfolio -Consider a portfolio of stocks. Our objective to minimize portfolio variance subect to full investment and box constraints. We will use out of sample backtesting to compare the sample covariance matrix estimate and a Ledoit-Wolf shinkage estimate. +Here we consider a portfolio of stocks. Our objective is to minimize portfolio variance subect to full investment and box constraints. We will use out of sample backtesting to compare the sample covariance matrix estimate and a Ledoit-Wolf shinkage estimate. +$$ +\min_{w} w^{T} \Sigma w +$$ + +--- + ## Specify Portfolio ```{r,eval=FALSE} # Specify an initial portfolio @@ -165,8 +280,8 @@ portf.minvar <- add.constraint(portf.init, type="full_investment") # Add box constraint such that no asset can have a weight of greater than -# 20% or less than 1% -portf.minvar <- add.constraint(portf.minvar, type="box", min=0.01, max=0.2) +# 45% or less than 1% +portf.minvar <- add.constraint(portf.minvar, type="box", min=0.01, max=0.45) # Add objective to minimize portfolio variance portf.minvar <- add.objective(portf.minvar, type="risk", name="var") @@ -176,6 +291,8 @@ Talk a little about adding constraints and objectives --> +--- + ## Ledoit-Wolf Shrinkage Estimate The default function for `momentFUN` is `set.portfolio.moments`. We need to write our own function to estimate the covariance matrix. ```{r, eval=FALSE} @@ -187,39 +304,32 @@ } ``` -## Backtesting Parameters -```{r, eval=FALSE} -# Set rebalancing frequency -rebal.freq <- "quarters" +--- -# Training Period -training <- 400 - -# Trailing Period -trailing <- 250 -``` - - ## Run Optimization ```{r, eval=FALSE, tidy=FALSE} # Backtest using sample covariance matrix estimate opt.minVarSample <- optimize.portfolio.rebalancing(equity.data, portf.minvar, optimize_method="ROI", - rebalance_on=rebal.freq, - training_period=training, - trailing_periods=trailing) + rebalance_on="quarters", + training_period=400, + trailing_periods=250) # Backtest using Ledoit-Wolf shrinkage covariance matrix estimate opt.minVarLW <- optimize.portfolio.rebalancing(equity.data, portf.minvar, optimize_method="ROI", momentFUN=lw.sigma, - rebalance_on=rebal.freq, - training_period=training, - trailing_periods=trailing) + rebalance_on="quarters", + training_period=400, + trailing_periods=250) ``` + + +--- + ## Chart Weights Through Time ```{r, eval=FALSE} chart.Weights(opt.minVarSample, main="minVarSample Weights", legend.loc=NULL) @@ -228,6 +338,8 @@ ![](optimization_figures/weights_minVarSample.png) ![](optimization_figures/weights_minVarLW.png) +--- + ## Returns Compute the portfolio rebalancing returns and chart the performance. ```{r, eval=FALSE} @@ -237,20 +349,20 @@ colnames(ret.minVar) <- c("Sample", "LW") charts.PerformanceSummary(ret.minVar) ``` - -## Performance Summary ![](optimization_figures/ret_minVar.png) -# Example 2 +--- -## Market Neutral Portfolio +## Example 2: Market Neutral Portfolio Here we consider a portfolio of stocks. Our objective is to maximize portfolio return with a target of 0.0015 and minimize portfolio StdDev with a target of 0.02 subject to dollar neutral, beta, box, and position limit constraints. We will use the same data considered in Example 1. -## Specify Portfolio: Contraints +--- + +## Specify Portfolio: Constraints ```{r, eval=FALSE, tidy=FALSE} portf.init <- portfolio.spec(stocks) @@ -277,6 +389,8 @@ explain the constraints --> +--- + ## Specify Portfolio: Objectives ```{r,eval=FALSE, tidy=FALSE} # Add objective to maximize portfolio return with a target of 0.0015 @@ -292,6 +406,8 @@ explain the objectives, specifically the target --> +--- + ## Run Optimization ```{r, eval=FALSE, tidy=FALSE} # Generate random portfolios @@ -307,16 +423,17 @@ generate a set of random portfolios and then pass directly to optimize.portfolio. Could just specify optimize_method = "random" and will automatically generate for you. --> +--- + ## Plot Results ```{r, eval=FALSE, tidy=FALSE} plot(opt.dn, main="Dollar Neutral Portfolio", risk.col="StdDev", neighbors=10) ``` ![](optimization_figures/opt_dn.png) +--- -# Example 3 - -## Data Setup +## Example 3: Data Setup Here we will look at portfolio optimization in the context of portfolio of hedge funds. * EDHEC-Risk Alternative Indexes @@ -328,7 +445,6 @@ * Emerging Markets (EM) * Global Macro (GM) -## Data ```{r, eval=FALSE, tidy=FALSE} R <- edhec[,c("Convertible.Arbitrage", "Equity.Market.Neutral", "Fixed.Income.Arbitrage", @@ -337,14 +453,18 @@ colnames(R) <- c("CA", "EMN", "FIA", "CTAG", "EM", "GM") ``` +--- + ## Monthly Returns ![](data_figures/relative_barvar.png) ![](data_figures/directional_barvar.png) +--- ## Distribution of Monthly Returns ![](data_figures/edhec_box.png) +--- ## Minimum Expected Shortfall Consider an allocation to hedge funds using the EDHEC-Risk Alternative Index as a proxy. This will be an extended example starting with an objective to minimize modified expected shortfall, then add risk budget percent contribution limit, and finally add equal risk contribution limit. @@ -353,12 +473,16 @@ * Minimize Expected Shortfall with Risk Budget Limit * Minimize Expected Shortfall with Equal Risk Contribution -Add risk budget objective to minimize concentration of percentage component contribution to risk. Concentration is defined as the Herfindahl-Hirschman Index (HHI). $\sum_i x_i^2$ +Add risk budget objective to minimize concentration of percentage component contribution to risk. Concentration is defined as the Herfindahl Hirschman Index (HHI). +$$ \sum_{i=1}^n x_i^2 $$ + +--- + ## Specify Initial Portfolio ```{r, eval=FALSE, tidy=FALSE} # Specify an initial portfolio @@ -384,6 +508,8 @@ basic comments about setting up an initial portfolio --> +--- + ## Add Objectives ```{r, eval=FALSE, tidy=FALSE} # Add objective to minimize expected shortfall @@ -407,6 +533,7 @@ Key points here are that we are creating 3 new portfolios by reusing the initial portfolio and we are relaxing the box constraints because we are no longer concerned with controlling weight concentration. We have limits on risk contribution. --> +--- ## Run Optimization ```{r, eval=FALSE, tidy=FALSE} @@ -424,9 +551,13 @@ explain how portf is a list of portfolios and passed to optimize.portfolio --> +--- + ## Plot in Risk-Return Space ![](optimization_figures/opt_minES.png) +--- + ## Chart Risk Budgets ```{r, eval=FALSE, tidy=FALSE} chart.RiskBudget(opt.minES[[2]], main="Risk Budget Limit", @@ -438,6 +569,8 @@ ![](optimization_figures/rb_minES.png) ![](optimization_figures/eqrb_minES.png) +--- + ## Set Rebalancing Parameters and Run Backtest ```{r, eval=FALSE, tidy=FALSE} # Set rebalancing frequency @@ -458,18 +591,25 @@ traceDE=0) ``` +--- + ## Min ES Risk Contributions and Weights Through Time ![](optimization_figures/risk_minES.png) ![](optimization_figures/weights_minES.png) +--- + ## Min ES Risk Budget Limit Risk Contributions and Weights Through Time ![](optimization_figures/risk_minESRB.png) ![](optimization_figures/weights_minESRB.png) +--- + ## Min ES Equal Component Contribution Risk Contributions and Weights Through Time ![](optimization_figures/risk_minESEqRB.png) ![](optimization_figures/weights_minESEqRB.png) +--- ## Compute Returns and Chart Performance ```{r, eval=FALSE, tidy=FALSE} @@ -480,18 +620,23 @@ ``` ![](optimization_figures/ret_minES.png) +--- -# Example 4 - -## Maximize CRRA +## Example 4: Maximize CRRA Consider an allocation to hedge funds using the EDHEC-Risk Alternative Index as a proxy. Our objective to maximize the fourth order expansion of the Constant Relative Risk Aversion (CRRA) expected utility function as in the Boudt paper and Martinelli paper. We use the same data as Example 3. -TODO: Add equation +$$ +EU_{\lambda}(w) = - \frac{\lambda}{2} m_{(2)}(w) + +\frac{\lambda (\lambda + 1)}{6} m_{(3)}(w) - +\frac{\lambda (\lambda + 1) (\lambda + 2)}{24} m_{(4)}(w) +$$ +--- + ## Define a function to compute CRRA ```{r, eval=FALSE, tidy=FALSE} CRRA <- function(R, weights, lambda, sigma, m3, m4){ @@ -511,6 +656,8 @@ The function arguments should have 'R' as the name of the returns and 'weights' as the name of the weights. 'R' and 'weights' are automatically matched, any other function arguments can be passed in through arguments in add.objective. --> +--- + ## Specify Portfolio ```{r, eval=FALSE, tidy=FALSE} # Specify portfolio @@ -528,12 +675,20 @@ # Add objective to maximize CRRA portf.crra <- add.objective(portf.crra, type="return", name="CRRA", arguments=list(lambda=10)) + +# I just want these for plotting +# Set multiplier=0 so that it is calculated, but does not affect the optimization +portf.crra <- add.objective(portf.crra, type="return", name="mean", multiplier=0) +portf.crra <- add.objective(portf.crra, type="risk", name="ES", multiplier=0) +portf.crra <- add.objective(portf.crra, type="risk", name="StdDev", multiplier=0) ``` +--- + ## Run Optimization ```{r, eval=FALSE, tidy=FALSE} opt.crra <- optimize.portfolio(R, portf.crra, optimize_method="DEoptim", @@ -541,14 +696,31 @@ momentFUN="crra.moments") ``` +```{r, echo=FALSE} +load("optimization_results/opt.crra.rda") +``` +```{r, tidy=FALSE, cache=TRUE} +opt.crra +``` + + +--- + ## Chart Results +```{r, eval=FALSE} +chart.RiskReward(opt.crra, risk.col="ES") +chart.RiskReward(opt.crra, risk.col="StdDev") +``` + ![](optimization_figures/crra_RR_ES.png) ![](optimization_figures/crra_RR_StdDev.png) +--- + ## Run Backtest and Compute Returns ```{r, eval=FALSE, tidy=FALSE} bt.opt.crra <- optimize.portfolio.rebalancing(R, portf.crra, @@ -568,6 +740,8 @@ Run optimization and extract the portfolio rebalancing returns from the summary method --> +--- + ## Chart Performance ```{r, eval=FALSE, tidy=FALSE} charts.PerformanceSummary(cbind(ret.bt.opt, ret.crra), @@ -575,8 +749,14 @@ ``` ![](optimization_figures/ret_crra.png) -# Conclusion +--- +## Conclusion +TODO + +* Overview of what was covered +* Additional information and plans for PortfolioAnalytics + ## Acknowledgements Many thanks to @@ -591,7 +771,10 @@ - Google for funding the Google Summer of Code for PortfolioAnalytics and many other proposals for R --> -## References +--- + +## References and Useful Links + * [ROI](http://cran.r-project.org/web/packages/ROI/index.html) * [DEoptim](http://cran.r-project.org/web/packages/DEoptim/index.html) * [pso](http://cran.r-project.org/web/packages/pso/index.html) @@ -602,4 +785,4 @@ * Martinelli paper * Boudt paper * [PortfolioAnalytics on R-Forge](https://r-forge.r-project.org/projects/returnanalytics/) -* Shiny App? +* [Shiny App](http://spark.rstudio.com/rossbennett3/PortfolioOptimization/) Modified: pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.md =================================================================== --- pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.md 2014-04-21 03:47:59 UTC (rev 3376) +++ pkg/PortfolioAnalytics/sandbox/RFinance2014/presentation.md 2014-04-27 02:53:24 UTC (rev 3377) @@ -1,14 +1,31 @@ -% R/Finance 2014: Complex Portfolio Optimization with PortfolioAnalytics -% Ross Bennett -% May 16, 2014 +--- +title : Complex Portfolio Optimization with PortfolioAnalytics +subtitle : R/Finance 2014 +author : Ross Bennett +date : May 16, 2014 +--- -# Overview + + + + +## Overview * Discuss Portfolio Optimization * Introduce PortfolioAnalytics * Demonstrate PortfolioAnalytics with Examples -# Portfolio Optimization + +--- + ## Modern Portfolio Theory "Modern" Portfolio Theory (MPT) was introduced by Harry Markowitz in 1952. @@ -22,9 +39,11 @@ How do we define risk? What about more complex objectives? +--- + ## Portfolio Optimization Objectives * Minimize Risk * Volatility @@ -43,10 +62,9 @@ The challenge here is knowing what solver to use and the capabilities/limits of the chosen solver. Talk about pros/cons of closed-form solvers vs. global solvers and what objectives can be solved. --> -# PortfolioAnalytics +--- -## Overview - +## PortfolioAnalytics Overview PortfolioAnalytics is an R package designed to provide numerical solutions and visualizations for portfolio optimization problems with complex constraints and objectives. * Support for multiple constraint and objective types @@ -69,9 +87,9 @@ - Periodic rebalancing and analyzing out of sample performance will help refine objectives and constraints --> +--- ## Support Multiple Solvers - Linear and Quadratic Programming Solvers * R Optimization Infrastructure (ROI) @@ -90,6 +108,8 @@ Brief explanation of each solver and what optimization problems (constraints and objectives) are supported --> +--- + ## Random Portfolios PortfolioAnalytics has three methods to generate random portfolios. @@ -107,18 +127,25 @@ The grid method to generate random portfolios is based on the gridSearch function in NMOF package. The grid search method only satisfies the min and max box constraints. The min_sum and max_sum leverage constraint will likely be violated and the weights in the random portfolios should be normalized. Normalization may cause the box constraints to be violated and will be penalized in constrained_objective. --> +--- + ## Comparison of Random Portfolio Methods ![](optimization_figures/rp_plot.png) + + +--- + ## Random Portfolios: Simplex Method ![](optimization_figures/fev_plot.png) +--- ## Workflow -TODO: Add a nice graphic here (Guy might have one) +![](misc_figures/workflow.png) -Specify a Portfolio --> Add Constraints --> Add Objectives --> Run Optimization --> Analyze Results - +--- -# Example 1 +## Workflow: Specify Portfolio -## Data Setup +```r +args(portfolio.spec) +``` + +``` +## function (assets = NULL, category_labels = NULL, weight_seq = NULL, +## message = FALSE) +## NULL +``` + + +--- + +## Workflow: Add Constraints + +```r +args(add.constraint) +``` + +``` +## function (portfolio, type, enabled = TRUE, message = FALSE, ..., +## indexnum = NULL) +## NULL +``` + + +Supported Constraint Types + +* Sum of Weights +* Box +* Group +* Turnover +* Diversification +* Position Limit +* Return +* Factor Exposure + +--- + +## Workflow: Add Objectives + +```r +args(add.objective) +``` + +``` +## function (portfolio, constraints = NULL, type, name, arguments = NULL, +## enabled = TRUE, ..., indexnum = NULL) +## NULL +``` + + +Supported Objective types + +* Return +* Risk +* Risk Budget +* Weight Concentration + +--- + +## Workflow: Run Optimization + +```r +args(optimize.portfolio) +``` + +``` +## function (R, portfolio = NULL, constraints = NULL, objectives = NULL, +## optimize_method = c("DEoptim", "random", "ROI", "pso", "GenSA"), +## search_size = 20000, trace = FALSE, ..., rp = NULL, momentFUN = "set.portfolio.moments", +## message = FALSE) +## NULL +``` + +```r +args(optimize.portfolio.rebalancing) +``` + +``` +## function (R, portfolio = NULL, constraints = NULL, objectives = NULL, +## optimize_method = c("DEoptim", "random", "ROI"), search_size = 20000, +## trace = FALSE, ..., rp = NULL, rebalance_on = NULL, training_period = NULL, +## trailing_periods = NULL) +## NULL +``` + + +Supported Optimization Methods + +* ROI +* random +* DEoptim +* pso +* GenSA + +--- + +## Workflow: Analyze Results + +Charting Functions + +* plot +* chart.Concentration +* chart.EfficientFrontier +* chart.RiskBudget +* chart.RiskReward +* chart.Weights + +Extract Functions + +* extractObjectiveMeasures +* extractStats +* extractWeights + + + +--- + +## Example 1: Data Setup Here we will look at portfolio optimization in the context of stocks. * Selection of large cap, mid cap, and small cap stocks from CRSP data @@ -147,16 +296,26 @@ ``` +--- + ## Distribution of Monthly Returns ![](data_figures/equity_box.png) +--- + ## Minimum Variance Portfolio -Consider a portfolio of stocks. Our objective to minimize portfolio variance subect to full investment and box constraints. We will use out of sample backtesting to compare the sample covariance matrix estimate and a Ledoit-Wolf shinkage estimate. +Here we consider a portfolio of stocks. Our objective is to minimize portfolio variance subect to full investment and box constraints. We will use out of sample backtesting to compare the sample covariance matrix estimate and a Ledoit-Wolf shinkage estimate. +$$ +\min_{w} w^{T} \Sigma w +$$ + +--- + ## Specify Portfolio ```r @@ -168,8 +327,8 @@ portf.minvar <- add.constraint(portf.init, type = "full_investment") # Add box constraint such that no asset can have a weight of greater than -# 20% or less than 1% -portf.minvar <- add.constraint(portf.minvar, type = "box", min = 0.01, max = 0.2) +# 45% or less than 1% +portf.minvar <- add.constraint(portf.minvar, type = "box", min = 0.01, max = 0.45) # Add objective to minimize portfolio variance portf.minvar <- add.objective(portf.minvar, type = "risk", name = "var") @@ -180,6 +339,8 @@ Talk a little about adding constraints and objectives --> +--- + ## Ledoit-Wolf Shrinkage Estimate The default function for `momentFUN` is `set.portfolio.moments`. We need to write our own function to estimate the covariance matrix. @@ -193,43 +354,34 @@ ``` -## Backtesting Parameters +--- -```r -# Set rebalancing frequency -rebal.freq <- "quarters" - -# Training Period -training <- 400 - -# Trailing Period -trailing <- 250 -``` - - - ## Run Optimization ```r # Backtest using sample covariance matrix estimate opt.minVarSample <- optimize.portfolio.rebalancing(equity.data, portf.minvar, optimize_method="ROI", - rebalance_on=rebal.freq, - training_period=training, - trailing_periods=trailing) + rebalance_on="quarters", + training_period=400, + trailing_periods=250) # Backtest using Ledoit-Wolf shrinkage covariance matrix estimate [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/returnanalytics -r 3377 From noreply at r-forge.r-project.org Mon Apr 28 23:43:21 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 28 Apr 2014 23:43:21 +0200 (CEST) Subject: [Returnanalytics-commits] r3378 - in pkg/PortfolioAnalytics: R vignettes Message-ID: <20140428214321.DDCAD18444D@r-forge.r-project.org> Author: rossbennett34 Date: 2014-04-28 23:43:21 +0200 (Mon, 28 Apr 2014) New Revision: 3378 Modified: pkg/PortfolioAnalytics/R/charts.DE.R pkg/PortfolioAnalytics/R/charts.risk.R pkg/PortfolioAnalytics/vignettes/DesignThoughts.Rnw Log: Minor fix to charting functions Add index entry to vignette Modified: pkg/PortfolioAnalytics/R/charts.DE.R =================================================================== --- pkg/PortfolioAnalytics/R/charts.DE.R 2014-04-27 02:53:24 UTC (rev 3377) +++ pkg/PortfolioAnalytics/R/charts.DE.R 2014-04-28 21:43:21 UTC (rev 3378) @@ -226,7 +226,7 @@ # Only attempt to draw trajectory if rows is greater than or equal to 1 # There may be some corner cases where nrow(w.traj) is equal to 0, # resulting in a 'subscript out of bounds' error. - if(rows >= 1){ + if(rows >= 2){ rr = matrix(nrow=rows, ncol=2) ## maybe rewrite as an apply statement by row on w.traj rtc = NULL Modified: pkg/PortfolioAnalytics/R/charts.risk.R =================================================================== --- pkg/PortfolioAnalytics/R/charts.risk.R 2014-04-27 02:53:24 UTC (rev 3377) +++ pkg/PortfolioAnalytics/R/charts.risk.R 2014-04-28 21:43:21 UTC (rev 3378) @@ -221,6 +221,7 @@ rbcols <- grep(paste(match.col, "contribution", sep="."), colnames(rebal.obj)) if(length(rbcols) < 1) stop(paste("No ", match.col, ".contribution columns.", sep="")) rbdata <- rebal.obj[, rbcols] + colnames(rbdata) <- gsub("^.*\\.", "", colnames(rbdata)) chart.StackedBar(w=rbdata, ylab=paste(match.col, "Contribution", sep=" "), main=main, ...) } @@ -228,6 +229,7 @@ rbcols <- grep(paste(match.col, "pct_contrib", sep="."), colnames(rebal.obj)) if(length(rbcols) < 1) stop(paste("No ", match.col, ".pct_contrib columns.", sep="")) rbdata <- rebal.obj[, rbcols] + colnames(rbdata) <- gsub("^.*\\.", "", colnames(rbdata)) chart.StackedBar(w=rbdata, ylab=paste(match.col, "% Contribution", sep=" "), main=main, ...) } } Modified: pkg/PortfolioAnalytics/vignettes/DesignThoughts.Rnw =================================================================== --- pkg/PortfolioAnalytics/vignettes/DesignThoughts.Rnw 2014-04-27 02:53:24 UTC (rev 3377) +++ pkg/PortfolioAnalytics/vignettes/DesignThoughts.Rnw 2014-04-28 21:43:21 UTC (rev 3378) @@ -67,6 +67,8 @@ \newcommand{\comm}[1]{\begin{quote}{\large \bf (#1)}\end{quote}} +% \VignetteIndexEntry{Design Thoughts of the PortfolioAnalytics Package} + \begin{document} \vspace{-2cm} %\baselineskip=20pt