Using Quadratic Programming for Portfolio Optimization

This week’s update of the Extreme Optimization Numerical Libraries for .NET includes the ability to solve quadratic programming (QP) problems. These are optimization problems where the objective function is a quadratic function and the solution is subject to linear constraints.

Our QP solver uses an active set method, and can be used to solve programs with thousands of variables. Quadratic programming has many applications in finance, economics, agriculture, and other areas. It also serves as the core of some methods for nonlinear programming such as Sequential Quadratic Programming (SQP).

We created some QuickStart samples that demonstrates how to use the new functionality:

In this post, I’d like to illustrate an application in finance: portfolio optimization.

Say we have a set of assets. We know the historical average return and variances of each asset. We also know the correlations between the assets. With this information, we can look for the combination of assets that best meets our objectives. In this case, our goal will be to minimize the risk while achieving a minimal return. Now let’s see how we can model this.

The unknowns in our model will be the amount to be invested in each asset, which we’ll denote by xi. All values together form the vector x. We will assume that all xi ≥ 0.

We can use the variance of the value of the portfolio as a measure for the risk. A larger variance means that the probability of a large loss also increases, which is what we want to avoid. If we denote the variance-covariance matrix of the assets by R, then the variance of the asset value is xTRx. This is what we want to minimize.

Now let’s look at the constraints. We obviously have a budget, so the sum of all amounts must be less than or equal to our budget. Say our budget is $10,000, then we must have Σ xi ≤ 10,000. We also want a minimum expected return on our investment, say 10%. If ri is the return associated with asset i, then the total expected return for our investment is Σ ri xi, and we want this value to be at least 10% of our total budget, or $1,000.

So, in summary, our model looks like this:

MinimizexTRx
Subject toΣ xi ≤ 10000
Σ ri xi ≥ 1000 xi ≥ 0

The last thing we need to do is formulate this quadratic program in terms of the optimization classes in the Numerical Libraries for .NET. The QuickStart samples show three ways of doing this: you can define the model directly in terms of vectors and matrices; you can build the model from scratch, or you can read it from a model definition file in MPS format. Since the problem above is already pretty much expressed in terms of vectors and matrices, we’ll use that approach here.

Quadratic programming problems are represented by the QuadraticProgram class. One of the constructors lets you create a model in so-called standard form. A quadratic program in standard form looks like this:

Minimizec0 + cTx + ½xTHx
Subject toAEx = bE
AIxbI
lxu

where c_0 is a scalar, H, A_E_, and A_I_ are matrices, and all other values are vectors. The subscript _E denotes quality constraints, while the subscript I denotes inequality constraints. In our case, we don’t have equality constraints.

As a concrete example, we will work with four assets with returns 5%, -20%, 15% and 30%, respectively. Our budget is $10,000, and the minimum return is 10%. The implementation is quite straightforward. Noteworthy is that, since in the standard form the right hand side is an upper bound, we have to change the sign of the minimum return constraint which had a lower bound right-hand side.

Here’s the C# code:

// The linear term in the objective function: Vector c = Vector.CreateConstant(4, 0.0); // The quaratic term in the objective function: Matrix R = Matrix.CreateSymmetric(4, new double[] { 0.08,-0.05,-0.05,-0.05, -0.05, 0.16,-0.02,-0.02, -0.05,-0.02, 0.35, 0.06, -0.05,-0.02, 0.06, 0.35 }, MatrixTriangle.Upper); // The coefficients of the constraints: Matrix A = Matrix.Create(2, 4, new double[] { 1, 1, 1, 1, -0.05, 0.2, -0.15, -0.30 }, MatrixElementOrder.RowMajor); // The right-hand sides of the constraints: Vector b = Vector.Create(10000, -1000); // We’re now ready to call the constructor. // The last parameter specifies the number of equality // constraints. QuadraticProgram qp1 = new QuadraticProgram(c, R, A, b, 0); // Now we can call the Solve method to run the algorithm: Vector x = qp1.Solve();

This is how it looks in Visual Basic:

’ The linear term in the objective function: Dim c As Vector = Vector.CreateConstant(4, 0.0) ‘ The quaratic term in the objective function: Dim R As Matrix = Matrix.CreateSymmetric(4, _ New Double() _ { _ 0.08, -0.05, -0.05, -0.05, _ -0.05, 0.16, -0.02, -0.02, _ -0.05, -0.02, 0.35, 0.06, _ -0.05, -0.02, 0.06, 0.35 _ }, MatrixTriangle.Upper) ‘ The coefficients of the constraints: Dim A As Matrix = Matrix.Create(2, 4, New Double() _ { _ 1, 1, 1, 1, _ -0.05, 0.2, -0.15, -0.3 _ }, MatrixElementOrder.RowMajor) ‘ The right-hand sides of the constraints: Dim b As Vector = Vector.Create(10000, -1000) ‘ We’re now ready to call the constructor. ‘ The last parameter specifies the number of ‘ equality constraints. Dim qp1 As New QuadraticProgram(c, R, A, b, 0) ‘ Now we can call the Solve method to run the algorithm: Dim x As Vector = qp1.Solve()

And finally in F#:

// The linear term in the objective function: let c = Vector.CreateConstant(4, 0.0); // The quaratic term in the objective function: let R = Matrix.CreateSymmetric(4, [| 0.08;-0.05;-0.05;-0.05; -0.05; 0.16;-0.02;-0.02; -0.05;-0.02; 0.35; 0.06; -0.05;-0.02; 0.06; 0.35 |], MatrixTriangle.Upper) // The coefficients of the constraints: let A = Matrix.Create(2, 4, [| 1.0; 1.0; 1.0; 1.0; -0.05; 0.2; -0.15; -0.30 |], MatrixElementOrder.RowMajor) // The right-hand sides of the constraints: let b = Vector.Create(10000.0, -1000.0) // We’re now ready to call the constructor. // The last parameter specifies the number of // equality constraints. let qp1 = new QuadraticProgram(c, R, A, b, 0) // Now we can call the Solve method to run the algorithm: let x = qp1.Solve()

After we’ve run this code, the vector x will contain the optimal amounts for each asset. It gives us: $3,453, $0, $1,069, $2,223. Not surprisingly, the second asset, which has had a negative return on average, should not be part of our portfolio. However, it turns out that the asset with the lowest positive return should have the largest share.