Coverage for src/fast_minimum_variance/__init__.py: 100%

14 statements  

« prev     ^ index     » next       coverage.py v7.15.0, created at 2026-07-02 13:28 +0000

1"""fast_minimum_variance — fast solvers for the minimum-variance portfolio.""" 

2 

3import numpy as np 

4 

5from .minvar_problem import _MinVarProblem 

6from .problem import _Problem 

7 

8 

9def Problem( # noqa: N802 

10 X: np.ndarray, # noqa: N803 

11 target: np.ndarray | None = None, 

12 A: np.ndarray | None = None, # noqa: N803 

13 b: np.ndarray | None = None, 

14 C: np.ndarray | None = None, # noqa: N803 

15 d: np.ndarray | None = None, 

16 alpha: float = 0.0, 

17 rho: float = 0.0, 

18 mu: np.ndarray | None = None, 

19 target_lr: tuple[float, np.ndarray, np.ndarray] | None = None, 

20 pcg_lr: tuple[float, np.ndarray, np.ndarray] | None = None, 

21) -> _MinVarProblem | _Problem: 

22 """Create a portfolio optimisation problem. 

23 

24 Returns a :class:`_MinVarProblem` (shrinking active-set) when no custom 

25 constraints are supplied, or a :class:`_Problem` (growing active-set) when 

26 any of ``A``, ``b``, ``C``, ``d`` are provided. 

27 

28 Args: 

29 X: Returns matrix of shape ``(T, N)``. 

30 target: Optional ``(N, N)`` regularisation matrix; when supplied the 

31 shrinkage term ``alpha * ||target @ w||^2`` is added to the 

32 objective. ``None`` disables shrinkage entirely. 

33 A: Equality constraint matrix ``(N, m)``: ``A^T w = b``. 

34 b: Equality RHS ``(m,)``. 

35 C: Inequality constraint matrix ``(N, p)``: ``C^T w <= d``. 

36 d: Inequality RHS ``(p,)``. 

37 alpha: Shrinkage intensity; only active when ``target`` is provided. 

38 rho: Return tilt strength (Markowitz mean-variance). 

39 mu: Expected returns vector ``(N,)``; required when ``rho != 0``. 

40 target_lr: Low-rank factored target ``(bar_lam, U_k, delta_k)`` for 

41 RMT eigenvalue-cleaning; replaces ``target`` in the CG matvec. 

42 pcg_lr: RMT preconditioner ``(bar_lam, U_k, delta_k)`` for 

43 ``solve_pcg``; ignored unless PCG is invoked. 

44 

45 Returns: 

46 A solver instance with ``solve_kkt()``, ``solve_minres()``, 

47 ``solve_cg()``, and ``solve_cvxpy()`` methods, each returning 

48 ``(w, n_iters)``. 

49 

50 Examples: 

51 >>> import numpy as np 

52 >>> X = np.random.default_rng(42).standard_normal((500, 20)) 

53 >>> w, _ = Problem(X).solve_kkt() 

54 >>> float(round(w.sum(), 8)) 

55 1.0 

56 >>> bool((w >= 0).all()) 

57 True 

58 """ 

59 if A is None and b is None and C is None and d is None: 

60 return _MinVarProblem(X, target=target, alpha=alpha, rho=rho, mu=mu, target_lr=target_lr, pcg_lr=pcg_lr) 

61 

62 # number of assets 

63 n = X.shape[1] 

64 

65 A = A if A is not None else np.ones((n, 0)) # noqa: N806 

66 b = b if b is not None else np.ones(1) 

67 C = C if C is not None else -np.eye(n) # noqa: N806 

68 d = d if d is not None else np.zeros(n) 

69 

70 return _Problem(X, target=target, A=A, b=b, C=C, d=d, alpha=alpha, rho=rho, mu=mu) 

71 

72 

73from .data import simulate_equity_returns # noqa: E402 

74 

75__all__ = ["Problem", "simulate_equity_returns"]