Skip to main content

Risk parity portfolio optimization with weight constraints.

Project description

Risk Parity Portfolio Optimization with Weight Constraints

Python package for long-only risk parity portfolio construction with two solvers:

  • CCDSolver for the unconstrained baseline problem
  • SCASolver for risk parity with per-asset upper bounds

The project is designed as a compact, testable implementation for numerical finance coursework and lightweight experimentation.

Features

  • Unconstrained risk parity via cyclical coordinate descent (CCD)
  • Constrained risk parity via successive convex approximation (SCA)
  • Utility functions for absolute and relative risk contributions
  • NumPy-only core dependency
  • Pytest test suite and GitHub Actions CI

Installation

Install from PyPI:

pip install risk-parity-constrained

Or install locally from source:

git clone https://github.com/mercuryyujia/MATH5030_group_project.git
cd MATH5030_group_project
pip install -e .

Install test dependencies:

pip install -e .[test]

Install notebook/demo dependencies:

pip install -e .[demo]

Quick Start

import numpy as np
from riskparity import (
    CCDSolver,
    SCASolver,
    relative_risk_contributions,
    risk_contribution_gap,
)

Sigma = np.array([
    [0.04, 0.01, 0.00],
    [0.01, 0.09, 0.02],
    [0.00, 0.02, 0.16],
])

w_ccd = CCDSolver(Sigma).solve()
print("CCD weights:", w_ccd)
print("CCD relative RC:", relative_risk_contributions(Sigma, w_ccd))
print("CCD gap:", risk_contribution_gap(Sigma, w_ccd))

w_sca = SCASolver(Sigma, w_max=0.5).solve()
print("SCA weights:", w_sca)
print("SCA relative RC:", relative_risk_contributions(Sigma, w_sca))
print("SCA gap:", risk_contribution_gap(Sigma, w_sca))

What the Solvers Do

Risk parity aims to allocate weights so that each asset contributes equally to total portfolio risk. In practice, portfolio construction often requires additional constraints such as:

  • long-only weights
  • weights summing to one
  • per-asset caps like w_i <= 10%

This package provides:

  • CCDSolver: an unconstrained long-only baseline solver
  • SCASolver: a constrained solver with box constraints of the form 0 <= w_i <= w_max

Public API

Solvers

CCDSolver(Sigma, tol=1e-8, max_iter=1000)

Computes an unconstrained long-only risk parity solution and normalizes weights to sum to 1.

Parameter Type Description
Sigma np.ndarray Symmetric covariance matrix of shape (n, n)
tol float Convergence tolerance
max_iter int Maximum CCD iterations

Key attributes after .solve():

  • n_iter_
  • converged_
  • objective_
  • risk_contribution_gap_

SCASolver(Sigma, w_max=1.0, tol=1e-6, max_iter=200)

Computes a constrained risk parity portfolio under:

  • sum(w) = 1
  • 0 <= w_i <= w_max
Parameter Type Description
Sigma np.ndarray Symmetric covariance matrix of shape (n, n)
w_max float Per-asset upper bound in (0, 1]
tol float Convergence tolerance
max_iter int Maximum outer SCA iterations

Key attributes after .solve():

  • n_iter_
  • converged_
  • objective_
  • risk_contribution_gap_

Utility Functions

risk_contributions(Sigma, w)

Returns per-asset risk contributions:

w * (Sigma @ w)

relative_risk_contributions(Sigma, w)

Normalizes risk contributions to sum to 1.

risk_contribution_gap(Sigma, w)

Returns the maximum absolute deviation from equal risk contributions.

Testing

The test suite is organized around correctness, validation, and robustness:

  • Correct implementation and validation: covariance input validation, CCD solver checks, diagonal covariance closed-form cases, two-asset sanity checks, long-only weights that sum to one, and equal risk contribution checks.
  • Robustness testing: constrained solver feasibility, infeasible w_max errors, randomized covariance matrices, stability across different portfolio sizes, and boundary parameter cases.

Run the test suite with:

pytest

CI currently tests Python 3.10, 3.11, and 3.12.

Demo Notebook

The repository includes a demonstration notebook in notebooks/demo.ipynb.

Open In Colab

Project Structure

.
├── .github/workflows/
│   ├── ci.yml
│   └── publish.yml
├── notebooks/
│   ├── demo.html
│   ├── demo.ipynb
│   └── demo.pdf
├── riskparity/
│   ├── __init__.py
│   └── _core.py
├── tests/
│   └── test_riskparity.py
├── LICENSE
├── pyproject.toml
└── README.md

License

MIT License. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

risk_parity_constrained-0.1.0.tar.gz (10.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

risk_parity_constrained-0.1.0-py3-none-any.whl (7.2 kB view details)

Uploaded Python 3

File details

Details for the file risk_parity_constrained-0.1.0.tar.gz.

File metadata

  • Download URL: risk_parity_constrained-0.1.0.tar.gz
  • Upload date:
  • Size: 10.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for risk_parity_constrained-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7fcf0c9fd499979fcc08f31d3251a6e6d35ac45a71892f36b45c90a01787af41
MD5 97e9816997aa10dea79948fccf24067e
BLAKE2b-256 4a7e16d6fd0bb1c0924f4934981788688970dd0b48e53d806093237b73e5abb0

See more details on using hashes here.

Provenance

The following attestation bundles were made for risk_parity_constrained-0.1.0.tar.gz:

Publisher: publish.yml on mercuryyujia/MATH5030_group_project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file risk_parity_constrained-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for risk_parity_constrained-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5ff06d378d872adb37bb76117a9a7fd6c658b1fa87f5464ff5ced00b5166e469
MD5 928e097c23d996206485e9f3652670b2
BLAKE2b-256 cd1eaa4cb41ace043a821bed96f12686ef1d8bd8cbbe6c7a967a1623cf0a9904

See more details on using hashes here.

Provenance

The following attestation bundles were made for risk_parity_constrained-0.1.0-py3-none-any.whl:

Publisher: publish.yml on mercuryyujia/MATH5030_group_project

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page