Introduction to PortfolioAnalytics
[This article was first published on FOSS Trading, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
portfolio.spec, add.constraint, and add.objective. library(PortfolioAnalytics) data(edhec) returns <- edhec[, 1:6] funds <- colnames(returns)Here we create a portfolio object with
portfolio.spec. The assets argument is a required argument to the portfolio.spec function. assets can be a character vector with the names of the assets, a named numeric vector, or a scalar value specifying the number of assets. If a character vector or scalar value is passed in for assets, equal weights will be created for the initial portfolio weights. init.portfolio <- portfolio.spec(assets = funds)The
portfolio object is an S3 class that contains portfolio level data as well as the constraints and objectives for the optimization problem. You can see that the constraints and objectives lists are currently empty, but we will add sets of constraints and objectives with add.constraint and add.objective. print.default(init.portfolio) ## $assets ## Convertible Arbitrage CTA Global Distressed Securities ## 0.1667 0.1667 0.1667 ## Emerging Markets Equity Market Neutral Event Driven ## 0.1667 0.1667 0.1667 ## ## $category_labels ## NULL ## ## $weight_seq ## NULL ## ## $constraints ## list() ## ## $objectives ## list() ## ## $call ## portfolio.spec(assets = funds) ## ## attr(,"class") ## [1] "portfolio.spec" "portfolio"Here we add the full investment constraint. The full investment constraint is a special case of the leverage constraint that specifies the weights must sum to 1 and is specified with the alias
type="full_investment" as shown below. init.portfolio <- add.constraint(portfolio = init.portfolio, type = "full_investment")Now we add box constraint to specify a long only portfolio. The long only constraint is a special case of a box constraint where the lower bound of the weights of each asset is equal to 0 and the upper bound of the weights of each asset is equal to 1. This is specified with
type="long_only" as shown below. The box constraint also allows for per asset weights to be specified. init.portfolio <- add.constraint(portfolio = init.portfolio, type = "long_only")The following constraint types are supported:
- leverage
- box
- group
- position_limit1
- turnover2
- diversification
- return
- factor_exposure
- transaction_cost2
- Not supported for problems formulated as quadratic programming problems solved with
optimize_method="ROI". - Not supported for problems formulated as linear programming problems solved with
optimize_method="ROI".
init.portfolio and adds the objectives specified below to minSD.portfolio and meanES.portfolio while leaving init.portfolio unchanged. This is useful for testing multiple portfolios with different objectives using the same constraints because the constraints only need to be specified once and several new portfolios can be created using an initial portfolio object. # Add objective for portfolio to minimize portfolio standard deviation
minSD.portfolio <- add.objective(portfolio=init.portfolio,
type="risk",
name="StdDev")
# Add objectives for portfolio to maximize mean per unit ES
meanES.portfolio <- add.objective(portfolio=init.portfolio,
type="return",
name="mean")
meanES.portfolio <- add.objective(portfolio=meanES.portfolio,
type="risk",
name="ES")
Note that the name argument in add.objective can be any valid R function. Several functions are provided in the PerformanceAnalytics package that can be specified as the name argument such as ES/ETL/CVaR, StdDev, etc. The following objective types are supported:- return
- risk
- risk_budget
- weight_concentration
add.constraint and add.objective functions were designed to be very flexible and modular so that constraints and objectives can easily be specified and added to portfolio objects. PortfolioAnalytics provides a print method so that we can easily view the assets, constraints, and objectives that we have specified for the portfolio. print(minSD.portfolio) ## ************************************************** ## PortfolioAnalytics Portfolio Specification ## ************************************************** ## ## Call: ## portfolio.spec(assets = funds) ## ## Assets ## Number of assets: 6 ## ## Asset Names ## [1] "Convertible Arbitrage" "CTA Global" "Distressed Securities" ## [4] "Emerging Markets" "Equity Market Neutral" "Event Driven" ## ## Constraints ## Number of constraints: 2 ## Number of enabled constraints: 2 ## Enabled constraint types ## - full_investment ## - long_only ## Number of disabled constraints: 0 ## ## Objectives ## Number of objectives: 1 ## Number of enabled objectives: 1 ## Enabled objective names ## - StdDev ## Number of disabled objectives: 0 print(meanES.portfolio) ## ************************************************** ## PortfolioAnalytics Portfolio Specification ## ************************************************** ## ## Call: ## portfolio.spec(assets = funds) ## ## Assets ## Number of assets: 6 ## ## Asset Names ## [1] "Convertible Arbitrage" "CTA Global" "Distressed Securities" ## [4] "Emerging Markets" "Equity Market Neutral" "Event Driven" ## ## Constraints ## Number of constraints: 2 ## Number of enabled constraints: 2 ## Enabled constraint types ## - full_investment ## - long_only ## Number of disabled constraints: 0 ## ## Objectives ## Number of objectives: 2 ## Number of enabled objectives: 2 ## Enabled objective names ## - mean ## - ES ## Number of disabled objectives: 0Now that we have portfolios set up with the desired constraints and objectives, we use
optimize.portfolio to run the optimizations. The examples below use optimize_method="ROI", but several other solvers are supported including the following: - DEoptim (differential evolution)
- random portfolios
- sample
- simplex
- grid
- GenSA (generalized simulated annealing)
- pso (particle swarm optimization)
- ROI (R Optimization Infrastructure)
- Rglpk
- quadprog
optimize_method="ROI". # Run the optimization for the minimum standard deviation portfolio
minSD.opt <- optimize.portfolio(R = returns, portfolio = minSD.portfolio,
optimize_method = "ROI", trace = TRUE)
print(minSD.opt)
## ***********************************
## PortfolioAnalytics Optimization
## ***********************************
##
## Call:
## optimize.portfolio(R = returns, portfolio = minSD.portfolio,
## optimize_method = "ROI", trace = TRUE)
##
## Optimal Weights:
## Convertible Arbitrage CTA Global Distressed Securities
## 0.0000 0.0652 0.0000
## Emerging Markets Equity Market Neutral Event Driven
## 0.0000 0.9348 0.0000
##
## Objective Measure:
## StdDev
## 0.008855
The objective to maximize mean return per ES can be formulated as a linear programming problem and can be solved quickly with optimize_method="ROI". # Run the optimization for the maximize mean per unit ES
meanES.opt <- optimize.portfolio(R = returns, portfolio = meanES.portfolio,
optimize_method = "ROI", trace = TRUE)
print(meanES.opt)
## ***********************************
## PortfolioAnalytics Optimization
## ***********************************
##
## Call:
## optimize.portfolio(R = returns, portfolio = meanES.portfolio,
## optimize_method = "ROI", trace = TRUE)
##
## Optimal Weights:
## Convertible Arbitrage CTA Global Distressed Securities
## 0.0000 0.2940 0.2509
## Emerging Markets Equity Market Neutral Event Driven
## 0.0000 0.4552 0.0000
##
## Objective Measure:
## mean
## 0.006635
##
##
## ES
## 0.01837
The PortfolioAnalytics package provides functions for charting to better understand the optimization problem through visualization. The plot function produces a plot of of the optimal weights and the optimal portfolio in risk-return space. The optimal weights and chart in risk-return space can be plotted separately with chart.Weights and chart.RiskReward. plot(minSD.opt, risk.col="StdDev", chart.assets=TRUE,
main="Min SD Optimization",
ylim=c(0, 0.0083), xlim=c(0, 0.06))
plot(meanES.opt, chart.assets=TRUE,
main="Mean ES Optimization",
ylim=c(0, 0.0083), xlim=c(0, 0.16))
This post demonstrates how to construct a portfolio object, add constraints, and add objectives for two simple optimization problems; one to minimize portfolio standard devation and another to maximize mean return per unit expected shortfall. We then run optimizations on both portfolio objects and plot the results of each portfolio optimization. Although this post demonstrates fairly simple constraints and objectives, PortfolioAnalytics supports complex constraints and objectives as well as many other features that will be covered in subsequent posts. The PortfolioAnalytics package is part of the ReturnAnalytics project on R-Forge. For additional examples and information, refer to the several vignettes and demos are provided in the package.
To leave a comment for the author, please follow the link and comment on their blog: FOSS Trading.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

