Coverage for cvxrisk/portfolio/min_risk.py: 100%

7 statements  

« prev     ^ index     » next       coverage.py v7.8.2, created at 2025-06-18 11:11 +0000

1"""Minimum risk portfolio optimization.""" 

2 

3# Copyright 2023 Stanford University Convex Optimization Group 

4# 

5# Licensed under the Apache License, Version 2.0 (the "License"); 

6# you may not use this file except in compliance with the License. 

7# You may obtain a copy of the License at 

8# 

9# http://www.apache.org/licenses/LICENSE-2.0 

10# 

11# Unless required by applicable law or agreed to in writing, software 

12# distributed under the License is distributed on an "AS IS" BASIS, 

13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

14# See the License for the specific language governing permissions and 

15# limitations under the License. 

16from __future__ import annotations 

17 

18import cvxpy as cp 

19 

20from .. import Model 

21 

22 

23def minrisk_problem( 

24 riskmodel: Model, 

25 weights: cp.Variable, 

26 base: cp.Expression | float = 0.0, 

27 constraints: list[cp.Constraint] | None = None, 

28 **kwargs, 

29) -> cp.Problem: 

30 """Create a minimum-risk portfolio optimization problem. 

31 

32 Args: 

33 riskmodel: A risk model implementing the `Model` interface, used to compute portfolio risk. 

34 

35 weights: CVXPY variable representing the portfolio weights. 

36 

37 base: Expression representing the base portfolio (e.g. for tracking error minimization). 

38 

39 constraints: List of CVXPY constraints applied to the optimization problem. 

40 

41 **kwargs: Additional keyword arguments passed to the risk model's risk expression. 

42 

43 Returns: 

44 A CVXPY problem that minimizes portfolio risk subject to the given constraints. 

45 

46 """ 

47 # if no constraints are specified 

48 constraints = constraints or [] 

49 

50 problem = cp.Problem( 

51 objective=cp.Minimize(riskmodel.estimate(weights - base, **kwargs)), 

52 constraints=[cp.sum(weights) == 1.0, weights >= 0] + riskmodel.constraints(weights, **kwargs) + constraints, 

53 ) 

54 

55 return problem