Coverage for cvx/risk/bounds.py: 100%

27 statements  

« prev     ^ index     » next       coverage.py v7.6.8, created at 2025-01-09 10:59 +0000

1# Copyright 2023 Stanford University Convex Optimization Group 

2# 

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

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

5# You may obtain a copy of the License at 

6# 

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

8# 

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

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

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

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

13# limitations under the License. 

14"""Bounds""" 

15 

16from __future__ import annotations 

17 

18from dataclasses import dataclass 

19 

20import cvxpy as cp 

21import numpy as np 

22 

23from .model import Model 

24 

25 

26@dataclass 

27class Bounds(Model): 

28 m: int = 0 

29 """Maximal number of bounds""" 

30 

31 name: str = "" 

32 """Name for the bounds, e.g. assets or factors""" 

33 

34 def estimate(self, weights, **kwargs): 

35 """No estimation for bounds""" 

36 raise NotImplementedError("No estimation for bounds") 

37 

38 def _f(self, str): 

39 return f"{str}_{self.name}" 

40 

41 def __post_init__(self): 

42 self.parameter[self._f("lower")] = cp.Parameter( 

43 shape=self.m, 

44 name="lower bound", 

45 value=np.zeros(self.m), 

46 ) 

47 self.parameter[self._f("upper")] = cp.Parameter( 

48 shape=self.m, 

49 name="upper bound", 

50 value=np.ones(self.m), 

51 ) 

52 

53 def update(self, **kwargs): 

54 lower = kwargs[self._f("lower")] 

55 self.parameter[self._f("lower")].value = np.zeros(self.m) 

56 self.parameter[self._f("lower")].value[: len(lower)] = lower 

57 

58 upper = kwargs[self._f("upper")] 

59 self.parameter[self._f("upper")].value = np.zeros(self.m) 

60 self.parameter[self._f("upper")].value[: len(upper)] = upper 

61 

62 def constraints(self, weights, **kwargs): 

63 return [ 

64 weights >= self.parameter[self._f("lower")], 

65 weights <= self.parameter[self._f("upper")], 

66 ]