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
« 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"""
16from __future__ import annotations
18from dataclasses import dataclass
20import cvxpy as cp
21import numpy as np
23from .model import Model
26@dataclass
27class Bounds(Model):
28 m: int = 0
29 """Maximal number of bounds"""
31 name: str = ""
32 """Name for the bounds, e.g. assets or factors"""
34 def estimate(self, weights, **kwargs):
35 """No estimation for bounds"""
36 raise NotImplementedError("No estimation for bounds")
38 def _f(self, str):
39 return f"{str}_{self.name}"
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 )
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
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
62 def constraints(self, weights, **kwargs):
63 return [
64 weights >= self.parameter[self._f("lower")],
65 weights <= self.parameter[self._f("upper")],
66 ]