cvxrisk: Convex Optimization for Portfolio Risk Management
cvxrisk is a Python library for portfolio risk management using convex optimization. It provides a flexible framework for implementing various risk models that can be used with CVXPY to solve portfolio optimization problems.
The library is built around an abstract Model class that standardizes
the interface for different risk models, making it easy to swap between
them in your optimization problems.
# Install from PyPI (without any convex solver)
pip install cvxrisk
# For development installation
git clone https://github.com/cvxgrp/cvxrisk.git
cd cvxrisk
make install
# For experimenting with the notebooks (after cloning)
make marimopip install cvxrisk[clarabel] or mosek
using pip install cvxrisk[mosek].
cvxrisk makes it easy to formulate and solve portfolio optimization problems:
import cvxpy as cp
import numpy as np
from cvxrisk.sample import SampleCovariance
from cvxrisk.portfolio import minrisk_problem
# Create a risk model
riskmodel = SampleCovariance(num=2)
# Update the model with data
riskmodel.update(
cov = np.array([[1.0, 0.5], [0.5, 2.0]]),
lower_assets = np.zeros(2),
upper_assets = np.ones(2)
)
# Define portfolio weights variable
weights = cp.Variable(2)
# Create and solve the optimization problem
problem = minrisk_problem(riskmodel, weights)
problem.solve(solver=cp.CLARABEL)
# Print the optimal weights with deterministic spacing
print(np.array2string(np.round(weights.value, 2), separator=" "))[0.75 0.25]
cvxrisk provides several risk models:
The simplest risk model based on the sample covariance matrix:
from cvxrisk.sample import SampleCovariance
import numpy as np
riskmodel = SampleCovariance(num=2)
riskmodel.update(
cov=np.array([[1.0, 0.5], [0.5, 2.0]]),
lower_assets=np.zeros(2),
upper_assets=np.ones(2),
)
# Reconstruct covariance from Cholesky factor and print
cov_est = riskmodel.parameter["chol"].value.T @ riskmodel.parameter["chol"].value
print(np.array2string(cov_est, precision=1))[[1. 0.5]
[0.5 2. ]]
Factor models reduce dimensionality by projecting asset returns onto a smaller set of factors:
import numpy as np
from cvxrisk.factor import FactorModel
from cvxrisk.linalg import pca
import pandas as pd
# Create some sample returns data
a = 100
m = 25
returns = pd.DataFrame(np.random.randn(a, m))
# Compute principal components (deterministic using a fixed seed for reproducibility)
np.random.seed(0)
factors = pca(returns, n_components=10)
# Create and update the factor model
model = FactorModel(assets=m, k=10)
model.update(
cov=factors.cov.values,
exposure=factors.exposure.values,
idiosyncratic_risk=factors.idiosyncratic.std().values,
lower_assets=np.zeros(m),
upper_assets=np.ones(m),
lower_factors=-0.1*np.ones(10),
upper_factors=0.1*np.ones(10),
)
# Verify the model has the correct dimensions
print(model.parameter["exposure"].value.shape)(10, 25)
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
CVaR measures the expected loss in the worst-case scenarios:
import numpy as np
from cvxrisk.cvar import CVar
# Create some sample historical returns (deterministic)
np.random.seed(0)
historical_returns = np.random.randn(50, 14)
# Create and update the CVaR model
model = CVar(alpha=0.95, n=50, m=14)
model.update(
returns=historical_returns,
lower_assets=np.zeros(14),
upper_assets=np.ones(14),
)
# Verify the model parameters
print(model.alpha)
print(model.parameter["R"].value.shape)0.95
(50, 14)
For more detailed documentation and examples, visit our documentation site.
cvxrisk uses modern Python development tools:
# Install development dependencies
make install
# Run tests
make test
# Format code
make fmt
# Start interactive notebooks
make marimocvxrisk is licensed under the Apache License 2.0. See LICENSE for details.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
For more information, see CONTRIBUTING.md.