Search code examples
pythonoptimizationportfoliocvxopt

portfolio optimization: how to maximize return while subject to target risk using cvxopt.solver.qp?


Trying to optimize a portfolio weight allocation here which maximize my return function by limit risk using cvxopt module. My codes are as below:

from cvxopt import matrix, solvers, spmatrix, sparse
from cvxopt.blas import dot
import numpy
import pandas as pd
import numpy as np
from datetime import datetime

solvers.options['show_progress'] = False
# solves the QP, where x is the allocation of the portfolio:
# minimize   x'Px + q'x
# subject to Gx <= h
#            Ax == b
#
# Input:  n       - # of assets
#         avg_ret - nx1 matrix of average returns
#         covs    - nxn matrix of return covariance
#         r_min   - the minimum expected return that you'd
#                   like to achieve
# Output: sol - cvxopt solution object

dates = pd.date_range('2000-01-01', periods=6)
industry = ['industry', 'industry', 'utility', 'utility', 'consumer']
symbols = ['A', 'B', 'C', 'D', 'E']
zipped = list(zip(industry, symbols))
index = pd.MultiIndex.from_tuples(zipped)

noa = len(symbols)

data = np.array([[10, 11, 12, 13, 14, 10],
                 [10, 11, 10, 13, 14, 9],
                 [10, 10, 12, 13, 9, 11],
                 [10, 11, 12, 13, 14, 8],
                 [10, 9, 12, 13, 14, 9]])

market_to_market_price = pd.DataFrame(data.T, index=dates, columns=index)
rets = market_to_market_price / market_to_market_price.shift(1) - 1.0
rets = rets.dropna(axis=0, how='all')

# covariance of asset returns
P    = matrix(rets.cov().values)


n = len(symbols)
q = matrix(np.zeros((n, 1)), tc='d')
G = matrix(-np.eye(n), tc='d')
h = matrix(-np.zeros((n, 1)), tc='d')
A = matrix(1.0, (1, n))
b = matrix(1.0)
sol = solvers.qp(P, q, G, h, A, b)

Should I use Monte Carlo simulation to get the target risk while maximize return? what's the best method for solving this problem? Thank you.


Solution

  • It is not as straightforward as one may think. The typical portfolio optimization problem is to minimize risk subject to a target return which is a linearly-constrained problem with a quadratic objective; ie, a quadratic program (QP).

    minimize        x^T.P.x
    subject to      sum(x_i) = 1
                    avg_ret^T.x >= r_min
                    x >= 0 (long-only)
    

    What you want here, to maximize return subject to a target risk, is a quadraticaly constrained quadratic program (QCQP), looking like:

    maximize        avg_ret^T.x
    subject to      sum(x_i) = 1
                    x^T.P.x <= risk_max
                    x >= 0 (long-only)
    

    With a convex quadratic constraint, optimization happens over a more complicated cone containing a second-order cone factor. If you want to proceed with cvxopt, you have to convert the QCQP to a second-order cone program (SOCP), as cvxopt does not have an explicit solver for QCQPs. SOCP with cvxopt has a different matrix syntax than the typical QP as you can see from the documentation. This blog post has a very nice walk-through on how to do this for this specific problem.