Home > Portfolio Construction, R > Portfolio Optimization: Specify constraints with GNU MathProg language

## Portfolio Optimization: Specify constraints with GNU MathProg language

I have previously described a few examples of portfolio construction:

I created a number of helper functions to simplify process of making the constraints( i.e. minimum / maximum investment constraints, fully invested constraint – weights must sum to 1, and etc.)

• new.constraints

However, even with help of these functions, the process of describing the constraints is not simple and user-friendly. Fortunately, there is an alternative way to specify linear constraints using GNU MathProg language. MathProg resembles a subset of AMPL. To find more about GNU MathProg language, I recommend reading following resources:

Let’s start by solving a simple portfolio construction problem using helper functions to specify the constraints.

```###############################################################################
# Load Systematic Investor Toolbox (SIT)
# https://systematicinvestor.wordpress.com/systematic-investor-toolbox/
###############################################################################
con = gzcon(url('http://www.systematicportfolio.com/sit.gz', 'rb'))
source(con)
close(con)

#*****************************************************************
#******************************************************************

#--------------------------------------------------------------------------
# Create historical input assumptions
#--------------------------------------------------------------------------
tickers = dow.jones.components()
ia = aa.test.create.ia.custom(tickers, dates = '2000::2010')

#--------------------------------------------------------------------------
# Create Constraints & Solve QP problem
#--------------------------------------------------------------------------
n = ia\$n

# 0 <= x.i <= 1
constraints = new.constraints(n, lb = 0, ub = 1)

# SUM x.i = 1
constraints = add.constraints(rep(1, n), 1, type = '=', constraints)

# Solve QP problem
x = min.var.portfolio(ia, constraints)

# plot weights
barplot(100*x, las=2, main='Minimum Variance Portfolio')
``` Now let’s create a GNU MathProg language model that will impose the same constraints. Please copy and save the following model description in the “model1.mod” file:

```###############################################################################
set SYMBOLS ;

# set min/max weights for individual stocks
var weight{i in SYMBOLS} >= 0, <= 1 ;

# objective function, NOT USED
minimize alpha : sum{i in SYMBOLS} weight[i] ;

# weights must sum to 1 (fully invested)
subject to fully_invested : sum{i in SYMBOLS} weight[i] = 1 ;

data;

set SYMBOLS :=  AA AXP BA BAC CAT CSCO CVX DD DIS GE HD HPQ IBM INTC JNJ JPM KFT KO MCD MMM MRK MSFT PFE PG T TRV UTX VZ WMT XOM ;
###############################################################################
```

Next, let’s use this model to find minimum variance portfolio.

```	#*****************************************************************
#******************************************************************

#--------------------------------------------------------------------------
# Read GNU MathProg model/Setup constraints/Solve QP problem
#--------------------------------------------------------------------------
model.file = 'model1.mod'

# convert GNU MathProg model to constraint used in solve.QP
constraints = Rglpk.create.constraints(model)\$constraints

# Solve QP problem
x = min.var.portfolio(ia, constraints)

# plot weights
barplot(100*x, las=2, main='Minimum Variance Portfolio using GNU MathProg model')
``` Next, let’s describe the problem from the Minimum Investment and Number of Assets Portfolio Cardinality Constraints post. Please copy and save the following model description in the “model2.mod” file:

```###############################################################################
set SYMBOLS ;

# set min/max weights for individual stocks
var weight{i in SYMBOLS} >= 0, <= 1 ;

# add binary, 1 if held, 0 if not held
var held{SYMBOLS} binary;

# objective function, NOT USED
minimize alpha : sum{i in SYMBOLS} weight[i] ;

# weights must sum to 1 (fully invested)
subject to fully_invested : sum{i in SYMBOLS} weight[i] = 1 ;

# min weight constraint for individual asset
subject to MinWgt {i in SYMBOLS} : weight[i] >= 0.025 * held[i];

# max weight constraint for individual asset
subject to MaxWgt {i in SYMBOLS} : weight[i] <= .20 * held[i] ;

# number of stocks in portfolio
subject to MaxAssetsLB : 0 <= sum {i in SYMBOLS} held[i] ;
subject to MaxAssetsUB : sum {i in SYMBOLS} held[i] <= 6 ;

data;

set SYMBOLS :=  AA AXP BA BAC CAT CSCO CVX DD DIS GE HD HPQ IBM INTC JNJ JPM KFT KO MCD MMM MRK MSFT PFE PG T TRV UTX VZ WMT XOM ;
###############################################################################
```

Next, let’s use this model to find minimum variance portfolio.

```	#--------------------------------------------------------------------------
# Read GNU MathProg model/Setup constraints/Solve QP problem
#--------------------------------------------------------------------------
model.file = 'model2.mod'

# convert GNU MathProg model to constraint used in solve.QP
constraints = Rglpk.create.constraints(model)\$constraints

# Solve QP problem
x = min.var.portfolio(ia, constraints)

# plot weights
barplot(100*x, las=2, main='Minimum Variance Portfolio using GNU MathProg model \n with Minimum Investment and Number of Assets Constraints')
``` I described another interesting portfolio construction problem in the 130/30 Portfolio Construction post. Please copy and save the following model description in the “model3.mod” file:

```###############################################################################
set SYMBOLS ;

# set min/max weights for individual stocks
var long {i in SYMBOLS} >= 0, <= 0.8 ;
var short{i in SYMBOLS} >= 0, <= 0.5 ;

# add binary, 1 if long, 0 if short
var islong{SYMBOLS} binary;

# objective function, NOT USED
minimize alpha : sum{i in SYMBOLS} long[i] ;

# weights must sum to 1 (fully invested)
subject to fully_invested : sum{i in SYMBOLS} (long[i] - short[i]) = 1 ;

# leverage is 1.6 = longs + shorts
subject to leverage : sum{i in SYMBOLS} (long[i] + short[i]) = 1.6 ;

# force long and short to be mutually exclusive (only one of them is greater then 0 for each i)
subject to long_flag  {i in SYMBOLS} : long[i]  <= islong[i] ;
subject to short_flag {i in SYMBOLS} : short[i] <= (1 - islong[i]) ;

data;

set SYMBOLS :=  AA AXP BA BAC CAT CSCO CVX DD DIS GE HD HPQ IBM INTC JNJ JPM KFT KO MCD MMM MRK MSFT PFE PG T TRV UTX VZ WMT XOM ;
###############################################################################
```

Next, let’s use this model to find minimum variance portfolio.

```	#--------------------------------------------------------------------------
# Read GNU MathProg model/Setup constraints/Solve QP problem
#--------------------------------------------------------------------------
model.file = 'model3.mod'

# convert GNU MathProg model to constraint used in solve.QP
constraints = Rglpk.create.constraints(model)\$constraints

# Solve QP problem, modify Input Assumptions to include short positions

# Compute total weight = longs - short
x = x[1:ia\$n] - x[-c(1:ia\$n)]

# plot weights
barplot(100*x, las=2, main='Minimum Variance Portfolio using GNU MathProg model \n with 130:30 Constraints')
``` Another interesting portfolio construction problem is limiting portfolio turnover, or limiting minimum trade size and number of trades. Following model is restricting the trade size to be between 5% and 20% and no more than 8 trades. Please copy and save the following model description in the “model4.mod” file:

```###############################################################################
set SYMBOLS ;

param CurWgt{SYMBOLS} ;

# set min/max weights for individual stocks
var weight{i in SYMBOLS} >= 0, <= 1 ;

var TradePos{i in SYMBOLS} >= 0 ;
var TradeNeg{i in SYMBOLS} >= 0 ;

# objective function, NOT USED
minimize alpha : sum{i in SYMBOLS} weight[i] ;

# weights must sum to 1 (fully invested)
subject to fully_invested : sum{i in SYMBOLS} weight[i] = 1 ;

# setup Trades for individual asset

# min trade size constraint for individual asset

# number of trades in portfolio
subject to MaxTrade : sum {i in SYMBOLS} trade[i] <= 8 ;

data;

set SYMBOLS :=  AA AXP BA BAC CAT CSCO CVX DD DIS GE ;

param : CurWgt:=
AA	0.1
AXP	0.1
BA	0.1
BAC	0.1
CAT	0.1
CSCO	0.1
CVX	0.1
DD	0.1
DIS	0.1
GE	0.1
;
###############################################################################
```

Next, let’s use this model to find minimum variance portfolio.

```	#--------------------------------------------------------------------------
# Read GNU MathProg model/Setup constraints/Solve QP problem
#--------------------------------------------------------------------------
model.file = 'model4.mod'

# reduce problem size
ia = aa.test.create.ia.custom(tickers[1:10], dates = '2000::2010')

# convert GNU MathProg model to constraint used in solve.QP
constraints = Rglpk.create.constraints(model)\$constraints

# Solve QP problem
x = min.var.portfolio(ia, constraints)

# plot weights
barplot(100*x, las=2, main='Minimum Variance Portfolio using GNU MathProg model \n with Turnover Constraints')
``` BA and GE are held constant at 10% and other 8 stocks are traded with trade size at least 5% and no more than 20%.

Please let me know what other type of constraints you like to impose during portfolio construction process.

To view the complete source code for this example, please have a look at the portopt.mathprog.test() function in aa.gmpl.r at github.

Categories: Portfolio Construction, R
1. March 15, 2012 at 4:09 pm

How would you define equal risk contribution?
Minimizing the risk and imposing budget contraints or Minimizing the difference between each risk contribution and total risk?

What about increasing a specific risk budget under certain environments (for instance doubling the equity risk contribution when the yield curve is positive sloping?)

Paolo

2. March 16, 2012 at 3:13 pm

Similarly, how would you construct an equal-contribution-to-risk portfolio that is also leveraged to target an overall variance or expected return level?
Again, nice post…

3. March 17, 2012 at 1:50 am

Unfortunately, there is no way to formulate risk contribution constraints as linear constraints (both QP and LP only support linear constraints).

For the readers benefits, following are the references for the risk contribution constraints:

1. March 19, 2012 at 5:01 am