Solve portfolio optimization (minimum variance) in Python
Portfolio optimization — choosing how to weight a set of assets to minimize risk (variance) for a target expected return — is the textbook Markowitz mean-variance problem, and it is a quadratic program (QP): a convex quadratic objective under linear constraints. With quicopt it is a few lines in Python.
The naive approach
A common tutorial move is Monte-Carlo: draw thousands of random weight vectors, compute each one's risk and return, and keep the best. It only approximates the efficient frontier, degrades fast as the number of assets grows, and never proves optimality. The problem is a convex QP — so solve it exactly.
Model it as a QP
A continuous weight per asset, fully invested (sum(w) == 1), long-only
(w >= 0), meeting a target return. The objective is the portfolio variance
wᵀΣw, where Σ is the covariance matrix:
from ortools.math_opt.python import mathopt
from quicopt import Client
# Minimum-variance portfolio (Markowitz): choose asset weights minimizing
# variance w'Σw, fully invested, meeting a target expected return.
Sigma = [[0.10, 0.02, 0.04, 0.00],
[0.02, 0.08, 0.01, 0.02],
[0.04, 0.01, 0.12, 0.03],
[0.00, 0.02, 0.03, 0.06]]
mu = [0.10, 0.08, 0.12, 0.07]
target = 0.09
N = len(mu)
model = mathopt.Model(name="portfolio")
w = [model.add_variable(lb=0.0, name=f"w_{i}") for i in range(N)]
model.add_linear_constraint(sum(w) == 1.0)
model.add_linear_constraint(sum(mu[i] * w[i] for i in range(N)) >= target)
model.minimize(sum(Sigma[i][j] * w[i] * w[j] for i in range(N) for j in range(N)))
client = Client("https://try.quicoptapi.pgi.fz-juelich.de")
print(client.solve(model).display)
├── status: optimal ├── feasible: true ├── objective: 0.03552848683416981 ├── x: w_0=0.2632, w_1=0.2362, w_2=0.1949, w_3=0.3058 (4 variables) └── solve_time: 0.0073 s
What you get
status: optimal means these weights are the proven minimum-variance
portfolio for the target return — variance 0.0355, fully invested, meeting the
9% return floor, in a few milliseconds. No sampling, no frontier scan.
The same model scales from four assets to hundreds — you change the covariance matrix and expected returns, not the method. (This is an illustrative optimization example, not financial advice.)
Next
- The problem class behind this: Quadratic programming (QP)
- Hold only a few assets: Cardinality-constrained portfolio (MINLP)
- A runnable model for every supported class: Examples
- Set up the client and solve your first model: Getting started
Reference: H. Markowitz, Portfolio Selection, The Journal of Finance, 1952.
A bigger portfolio — or a different problem?
Tell us what you're optimizing. We'll help you model it and point you at the right approach.
Frequently asked questions
Why not Monte-Carlo sample random weights and pick the best?
Random sampling only approximates the efficient frontier and needs enormous sample counts to get close in more than a few assets. The QP returns the provably minimum-variance portfolio directly.
Can I add a maximum weight per asset, sector limits, or no short-selling?
Yes — weight bounds, group limits and long-only (w >= 0) are linear constraints on the same QP.
What about a limit on the number of assets held?
A cardinality limit turns it into a mixed-integer QP (MINLP) with binary hold/skip variables — a related model quicopt also solves.
Is quicopt free to use?
Yes — pip install quicopt and your first call sets up a free key, no license.