Package: cvxrisk
cvxriskWe provide an abstractModelclass.
The class is designed to be used in conjunction withcvxpy.
Using this class, we can formulate a function computing a standard minimum
risk portfolio asimportcvxpyascpfromcvx.riskimportModeldefminimum_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."""returncp.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 theestimatemethod.Note that factor risk models work with weights for the assets but also with
weights for the factors.
To stay flexible we are applying thiS**kwargspattern to the function above.A first exampleA first example is a risk model based on the sample covariance matrix.
We construct the risk model as followsimportnumpyasnpimportcvxpyascpfromcvx.risk.sampleimportSampleCovarianceriskmodel=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.Risk modelsSample covarianceWe offer aSampleCovarianceclass as seen above.Factor risk modelsFactor risk models use the projection of the weight vector into a lower
dimensional subspace, e.g. each asset is the linear combination of $k$ factors.r_i = \sum_{j=1}^k f_j \beta_{ji} + \epsilon_iThe factor time series are $f_1, \ldots, f_k$. The loadings are the coefficients
$\beta_{ji}$.
The residual returns $\epsilon_i$ are assumed to be uncorrelated with the f
actors.Any position $w$ in weight space projects to a position $y = \beta^T w$ in
factor space. The variance for a position $w$ is the sum of the variance of the
systematic returns explained by the factors and the variance of the
idiosyncratic returns.Var(r) = Var(\beta^T w) + Var(\epsilon w)We assume the residual returns are uncorrelated and henceVar(r) = y^T \Sigma_f y + \sum_i w_i^2 Var(\epsilon_i)where $\Sigma_f$ is the covariance matrix of the factors and $Var(\epsilon_i)$
is the variance of the idiosyncratic returns.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 $\Sigma_f$, the loadings $\beta$ and the volatilities of the
idiosyncratic returns $\epsilon_i$. Usually those quantities are provided by
external parties, e.g. Barra or Axioma.An alternative would be to start with the estimation of factor time series
$f_1, \ldots, f_k$.
Usually they are estimated via a principal component analysis (PCA) of the
asset returns.  It is then a simple linear regression to compute the loadings
$\beta$. The volatilities of the idiosyncratic returns $\epsilon_i$ are computed
as the standard deviation of the observed residuals.
The factor covariance matrix $\Sigma_f$ may even be diagonal in this case as the
factors are orthogonal.We expose a method to compute the first $k$ principal components.cvarWe currently also support the conditional value at risk (CVaR) as a risk
measure.PoetryWe assume you share already the love forPoetry.
Once you have installed poetry you can performmakeinstallto replicate the virtual environment we have defined in pyproject.toml.KernelWe installJupyterLabwithin your new virtual
environment. Executingmakekernelconstructs a dedicatedKernelfor the project.