API Docs

Manual, tutorials and complete function reference

Introduction to Portfolio Optimization
With Multiple Constraints


This tutorial focuses on Markowitz portfolio optimization at the intraday time scale. Using optimization procedures of the PortfolioEffect Quant Library we construct and compare optimal portfolios. Our focus here is on showing how to create optimizer object that meets certain optimization goal and add subsequent optimization constraints.

R Code Matlab Code
Creating Portfolio

Let's create a portfolio with three positions that use an interval from 2014-09-17 to 2014-09-21 as a holding period. Portfolio metrics mode is set to static, because classic portfolio optimization does not take past history of rebalancing into account.

require(PortfolioEffectHFT)

portfolio=portfolio_create("SPY", "2014-11-19 09:30:00", "2014-11-19 16:00:00")
portfolio_settings(portfolio,portfolioMetricsMode="price",resultsSamplingInterval='1m')
position_AAPL=position_add(portfolio,"AAPL",1000)
position_GOOG=position_add(portfolio,"GOOG",1000)
position_SPY=position_add(portfolio,"SPY",1000)

plot(portfolio)
Jensen's Alphas of Positions
paren = @(x, varargin) x(varargin{:});

portfolio=portfolio_create('index','SPY', 'fromTime', '2014-11-19 09:30:00', 'toTime', '2014-11-19 16:00:00');
portfolio_settings(portfolio,'portfolioMetricsMode','price','resultsSamplingInterval','1m');
portfolio_addPosition(portfolio,'AAPL',100);
portfolio_addPosition(portfolio,'GOOG',100);
portfolio_addPosition(portfolio,'SPY',100);

plot(portfolio);
Jensen's Alphas of Positions

Performing Portfolio Optimization

At the next step, we specify our optimization goal, which is to minimize portfolio variance in this example. Resulting portfolio optimizer object could be further adjusted by additional optimization constraints. In this example, we add a lower boundary constraint on portfolio's expected return.

optimizer=optimization_goal(variance(portfolio),direction="min")
optimizer=optimization_constraint(optimizer,value(portfolio),'=',10^9)
optimizer=optimization_constraint(optimizer,expected_return(portfolio),">=",0)
optimPortfolioOneConstraints=optimization_run(optimizer)

plot(optimPortfolioOneConstraints)

Optimal Position Weights
optimizer=optimization_goal(portfolio,'Variance','minimize');
optimizer=optimization_constraint_portfolioValue(optimizer,10^9);
optimizer=optimization_constraint_expectedReturn(optimizer,'>=',0);
optimPortfolioOneConstraints=optimization_run(optimizer);

close
plot(optimPortfolioOneConstraints)
Optimal Position Weights

Chaining Optimization Constraints

One could chain several portfolio optimization constraints, so that the optimal portfolio have to meet all of the imposed conditions. Here are are adding an extra lower limit on the sum of absolute weights of Apple and Google positions. In real-world portfolios such a constraint could be used to control concentration risk.

optimizer=optimization_constraint(optimizer,weight_transform(portfolio,"sum_abs_weight",c(position_AAPL,position_GOOG)),">=",0.5)

optimPortfolioTwoConstraints=optimization_run(optimizer)
plot(optimPortfolioTwoConstraints)
Alphas of The Two Portfolios
optimizer=optimization_constraint_sumOfAbsWeights(optimizer,'>=',0.5,cellstr(['AAPL';'GOOG']));
optimPortfolioTwoConstraints=optimization_run(optimizer);

close
plot(optimPortfolioTwoConstraints)
Alphas of The Two Portfolios

Portfolio Expected Return

Both of our optimal portfolios has expected return as one of their constraints. Chart shows that constraint is generally met by both portfolios except at some short time intervals. One could also notice that portfolio with two constraints has higher expected returns across the range.

plot(expected_return(optimPortfolioOneConstraints),"Portfolio Expected Return",legend="Optimal Portfolio, with Constraints:\nReturn>=0")+
  plot(expected_return(optimPortfolioTwoConstraints),legend="Optimal Portfolio, with Constraints:\nReturn>=0, Sum of Abs Weights AAPL and GOOG >=0.5")
Forecast Errors
close
figure('position',[800 200 1000 700])
util_plot2d(portfolio_expectedReturn(optimPortfolioOneConstraints),'Optimal Portfolio, with Constraints:Return>=0.02','Title','Portfolio Expected Return')+...
util_line2d(portfolio_expectedReturn(optimPortfolioTwoConstraints),'Optimal Portfolio, with Constraints:Return>=0.02, Sum of Abs Weights AAPL and GOOG >=0.5')
Forecast Errors

Portfolio Variance

Portfolio variance is set as our minimization goal. Chart of variance values of the two optimal portfolios shows that portfolio with two constraints generally has a higher return variance.

plot(variance(optimPortfolioOneConstraints),"Portfolio Variance",legend="Optimal Portfolio, with Constraints:\nReturn>=0")+
  plot(variance(optimPortfolioTwoConstraints),legend="Optimal Portfolio, with Constraints:\nReturn>=0, \nSum of Abs Weights AAPL and GOOG >=0.5")
Forecast Errors
util_plot2d(portfolio_variance(optimPortfolioOneConstraints),'Optimal Portfolio, with Constraints:Return>=0.02','Title','Portfolio Variance')+...
util_line2d(portfolio_variance(optimPortfolioTwoConstraints),'Optimal Portfolio, with Constraints:Return>=0.02, Sum of Abs Weights AAPL and GOOG >=0.5')
Forecast Errors

Sum of Absolute Weights

Sum of absolute weights of Apple and Google is used as a constraint in the second portfolio. Chart below shows that this constrant is effective for the second portfolio, but is ignored in the first one.

sumOfAbsWeightsOptimPortfolio=abs(compute(weight(portfolio_getPosition(optimPortfolioOneConstraints,"AAPL")))[[1]][,2])+abs(compute(weight(portfolio_getPosition(optimPortfolioOneConstraints,"GOOG")))[[1]][,2])
sumOfAbsWeightsOptimPortfolioTwoConstraints=abs(compute(weight(portfolio_getPosition(optimPortfolioTwoConstraints,"AAPL")))[[1]][,2])+abs(compute(weight(portfolio_getPosition(optimPortfolioTwoConstraints,"GOOG")))[[1]][,2])
timeUTC=compute(weight(portfolio_getPosition(optimPortfolioOneConstraints,"AAPL")))[[1]][,1]

util_plot2d(cbind(timeUTC,sumOfAbsWeightsOptimPortfolio),"Portfolio Sum Of Abs Weigth AAPL and GOOG",legend="Optimal Portfolio, with Constraints:\nReturn>=0")+
  util_line2d(cbind(timeUTC,sumOfAbsWeightsOptimPortfolioTwoConstraints),legend="Optimal Portfolio, with Constraints:\nReturn>=0, \nSum of Abs Weights AAPL and GOOG >=0.5")
Forecast Errors
sumOfAbsWeightsOptimPortfolio=abs(paren(position_weight(optimPortfolioOneConstraints,'AAPL'),:,2))+abs(paren(position_weight(optimPortfolioOneConstraints,'GOOG'),:,2));
sumOfAbsWeightsOptimPortfolioTwoConstraints=abs(paren(position_weight(optimPortfolioTwoConstraints,'AAPL'),:,2))+abs(paren(position_weight(optimPortfolioTwoConstraints,'GOOG'),:,2));
timeUTC = paren(position_weight(optimPortfolioOneConstraints,'AAPL'),:,1);

util_plot2d([timeUTC,sumOfAbsWeightsOptimPortfolio],'Optimal Portfolio, with Constraints:Return>=0.02','Title','Portfolio Sum Of Abs Weigth AAPL and GOOG')+...
util_line2d([timeUTC,sumOfAbsWeightsOptimPortfolioTwoConstraints],'Optimal Portfolio, with Constraints:Return>=0.02, Sum of Abs Weights AAPL and GOOG >=0.5')
Forecast Errors