markowitz.optimizer.mean_variance¶
markowitz.optimizer.mean_variance
¶
High-level mean-variance optimizer.
:class:MeanVariance is the public entry point for the numerical layer.
It hides the bookkeeping around
- validating / canonicalising inputs (numpy arrays, pandas Series / DataFrames),
- building a fresh :class:
cvxpy.Problemper objective call, - turning the user's declarative constraint list into CVXPY constraints,
- dispatching the Cornuejols--Tutuncu reformulation for max-Sharpe, and
- mapping solver failures to the typed exception hierarchy.
The class is deliberately stateless across solves -- the only mutable state
is the constraint list and the most recent solution (kept for convenience
in :pyattr:last_weights).
MeanVariance(mu: pd.Series | np.ndarray, sigma: pd.DataFrame | np.ndarray, weight_bounds: tuple[float | None, float | None] = (0.0, 1.0), *, solver: str = 'CLARABEL', solver_options: dict[str, Any] | None = None, regularize: float = _REGULARIZE_DEFAULT)
¶
Convex mean-variance optimizer over a single horizon.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mu
|
Series | ndarray
|
Expected returns; either a |
required |
sigma
|
DataFrame | ndarray
|
Covariance matrix; either a |
required |
weight_bounds
|
tuple[float | None, float | None]
|
Default |
(0.0, 1.0)
|
solver
|
str
|
CVXPY solver name forwarded to :func: |
'CLARABEL'
|
solver_options
|
dict[str, Any] | None
|
Extra keyword arguments forwarded to the solver backend. |
None
|
regularize
|
float
|
Ridge term added to |
_REGULARIZE_DEFAULT
|
Source code in src/markowitz/optimizer/mean_variance.py
add_constraint(constraint: Constraint) -> MeanVariance
¶
clear_constraints() -> MeanVariance
¶
efficient_return(target_return: float) -> pd.Series
¶
Minimise variance subject to mu^T w >= target_return.
Source code in src/markowitz/optimizer/mean_variance.py
efficient_risk(target_volatility: float) -> pd.Series
¶
Maximise mu^T w subject to sqrt(w^T Sigma w) <= target_vol.
Source code in src/markowitz/optimizer/mean_variance.py
max_quadratic_utility(risk_aversion: float = 1.0) -> pd.Series
¶
Maximise mu^T w - (lambda/2) w^T Sigma w.
With risk_aversion = lambda. lambda > 0 is required.
Source code in src/markowitz/optimizer/mean_variance.py
max_sharpe(risk_free_rate: float = 0.0) -> pd.Series
¶
Maximise the Sharpe ratio via the Cornuejols--Tutuncu reformulation.
Source code in src/markowitz/optimizer/mean_variance.py
min_volatility() -> pd.Series
¶
Minimise w^T Sigma w subject to sum(w) = 1 and constraints.
Source code in src/markowitz/optimizer/mean_variance.py
portfolio_performance(weights: pd.Series | np.ndarray | None = None, *, risk_free_rate: float = 0.0) -> tuple[float, float, float]
¶
Return (expected_return, volatility, sharpe_ratio).
If weights is None the most-recently-computed weights are
used; an error is raised when no solve has happened yet.