Coverage for src/fast_minimum_variance/__init__.py: 100%
5 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-04 15:49 +0000
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-04 15:49 +0000
1"""fast_minimum_variance — fast solvers for the minimum-variance portfolio."""
3import numpy as np
5from .minvar_problem import _MinVarProblem
8def Problem( # noqa: N802
9 X: np.ndarray, # noqa: N803
10 target: np.ndarray | None = None,
11 B: np.ndarray | None = None, # noqa: N803
12 c: np.ndarray | None = None,
13 alpha: float = 0.0,
14 rho: float = 0.0,
15 mu: np.ndarray | None = None,
16 target_lr: tuple[float, np.ndarray, np.ndarray] | None = None,
17 pcg_lr: tuple[float, np.ndarray, np.ndarray] | None = None,
18) -> _MinVarProblem:
19 """Create a long-only minimum-variance portfolio optimisation problem.
21 Returns a :class:`_MinVarProblem` (shrinking active-set) for the long-only
22 minimum-variance problem, optionally with a balance system ``(B, c)`` in
23 place of the default budget constraint.
25 Args:
26 X: Returns matrix of shape ``(T, N)``.
27 target: Optional ``(N, N)`` regularisation matrix; when supplied the
28 shrinkage term ``alpha * ||target @ w||^2`` is added to the
29 objective. ``None`` disables shrinkage entirely.
30 B: Balance system ``(p, N)`` for the fast shrinking active-set
31 path: ``B w = c`` replaces the budget ``1^T w = 1``. ``B``
32 must have full row rank on every active set the loop visits.
33 c: Balance RHS ``(p,)``; required together with ``B``.
34 alpha: Shrinkage intensity; only active when ``target`` is provided.
35 rho: Return tilt strength (Markowitz mean-variance).
36 mu: Expected returns vector ``(N,)``; required when ``rho != 0``.
37 target_lr: Low-rank factored target ``(bar_lam, U_k, delta_k)`` for
38 RMT eigenvalue-cleaning; replaces ``target`` in the CG matvec.
39 pcg_lr: RMT preconditioner ``(bar_lam, U_k, delta_k)`` for
40 ``solve_pcg``; ignored unless PCG is invoked.
42 Returns:
43 A solver instance with ``solve_kkt()``, ``solve_minres()``,
44 ``solve_cg()``, and ``solve_cvxpy()`` methods, each returning
45 ``(w, n_iters)``.
47 Examples:
48 >>> import numpy as np
49 >>> X = np.random.default_rng(42).standard_normal((500, 20))
50 >>> w, _ = Problem(X).solve_kkt()
51 >>> float(round(w.sum(), 8))
52 1.0
53 >>> bool((w >= 0).all())
54 True
56 A two-sleeve balance system — each half of the universe holds half
57 of the budget:
59 >>> B = np.zeros((2, 20)); B[0, :10] = 1.0; B[1, 10:] = 1.0
60 >>> w, _ = Problem(X, B=B, c=np.array([0.5, 0.5])).solve_kkt()
61 >>> [float(round(s, 8)) for s in B @ w]
62 [0.5, 0.5]
63 >>> bool((w >= -1e-6).all())
64 True
65 """
66 return _MinVarProblem(X, target=target, alpha=alpha, rho=rho, mu=mu, target_lr=target_lr, pcg_lr=pcg_lr, B=B, c=c)
69__all__ = ["Problem"]