We provide an abstract Model
class.
The class is designed to be used in conjunction with cvxpy.
Using this class, we can formulate a function computing a standard minimum
risk portfolio as
import cvxpy as cp
from cvx.risk import Model
def minimum_risk(w: cp.Variable, risk_model: Model, **kwargs) -> cp.Problem:
"""Constructs a minimum variance portfolio.
Args:
w: cp.Variable representing the portfolio weights.
risk_model: A risk model.
Returns:
A convex optimization problem.
"""
return cp.Problem(
cp.Minimize(risk_model.estimate(w, **kwargs)),
[cp.sum(w) == 1, w >= 0] + risk_model.constraints(w, **kwargs)
)
The risk model is injected into the function.
The function is not aware of the precise risk model used.
All risk models are required to implement the estimate
method.
Note that factor risk models work with weights for the assets but also with
weights for the factors.
To stay flexible we are applying the **kwargs
pattern to the function above.
A first example is a risk model based on the sample covariance matrix. We construct the risk model as follows
import numpy as np
import cvxpy as cp
from cvx.risk.sample import SampleCovariance
riskmodel = SampleCovariance(num=2)
w = cp.Variable(2)
problem = minimum_risk(w, riskmodel)
riskmodel.update(cov=np.array([[1.0, 0.5], [0.5, 2.0]]))
problem.solve()
print(w.value)
The risk model and the actual optimization problem are decoupled. This is good practice and keeps the code clean and maintainable.
In a backtest we don't have to reconstruct the problem in every iteration. We can simply update the risk model with the new data and solve the problem again. The implementation of the risk models is flexible enough to deal with changing dimensions of the underlying weight space.
We offer a SampleCovariance
class as seen above.
Factor risk models use the projection of the weight vector into a lower
dimensional subspace, e.g. each asset is the linear combination of
The factor time series are
Any position
We assume the residual returns are uncorrelated and hence
where
Factor risk models are widely used in practice. Usually two scenarios are
distinguished. A first route is to rely on estimates for the factor covariance
matrix
An alternative would be to start with the estimation of factor time series
We expose a method to compute the first
We currently also support the conditional value at risk (CVaR) as a risk measure.
Starting with
make install
will install uv and create the virtual environment defined in pyproject.toml and locked in uv.lock.
We install marimo on the fly within the aforementioned virtual environment. Executing
make marimo
will install and start marimo.