The brief
A portfolio manager has $50 million to place across ten funds, and wants the book with the least risk. Every dollar must be invested, so the budget is a constraint. Risk is the variance of the book's value over a year.
The desk wants the answer from a formula and from a numerical optimiser. The optimiser is what it will use once more constraints arrive, such as the fund's rule against short sales.
Your task
- Derive the positions on paper. Minimise subject to , with the Lagrangian . Here holds the positions in $ millions, is the covariance matrix and the budget.
- Write
min_variance(cov, budget): the pair(x, lam), with the positions as a NumPy array and the multiplier . RaiseValueErrorunlesscovis square, symmetric and positive definite, andbudgetis positive. - Write
min_variance_numeric(cov, budget, long_only=False): the same positions, found withscipy.optimize.minimize. Withlong_only=Trueno position may be negative. RaiseValueErrorfor the same bad inputs, andRuntimeErrorif the optimiser reports a failure.
The desk checks every answer to within $1,000 in each fund, which is 0.001 in these units.
The data
VOLS and CORR hold the ten funds' annual volatilities and correlations, and COV is the covariance matrix built from them. BUDGET is 50, in $ millions.
Hint: Where to start
Case study 4.5.5 found the minimum-variance weights for a budget of 1. Follow the same steps from Lagrange's condition (lesson 4.5.1), here , and let the budget fix .
Hint: What the multiplier measures
Lesson 4.5.1 reads as a rate: the change in the least variance for each extra unit of budget. Check yours by solving for two budgets either side of 50.
Hint: The optimiser and short sales
Lesson 4.5.2 solves with SciPy's SLSQP method, whose ftol sets how precisely it stops; the default stops too early here. Case study 4.5.5 adds bounds for a long-only book, and its KKT conditions tell you whether the answer is right.