portfolio-optimizer
Portfolio constraint feasibility checker with formal verification. Determines whether a set of portfolio constraints (cardinality, sector limits, position bounds, budget, CVaR risk) can be simultaneously satisfied — and if not, identifies exactly which constraints conflict and suggests fixes.
1,143 tests. Exhaustive brute-force verification, property-based fuzzing, adversarial edge cases, and formal solution certification on every result.
Install
pip install portfolio-optimizer
Quick Start
from portfolio_optimizer import PortfolioChecker
pc = PortfolioChecker(n_assets=500)
# Cardinality: select 15-20 assets
pc.add_cardinality(min_assets=15, max_assets=20)
# Sector weight limits
pc.add_weight_limit("tech", assets=[0,1,2,3,4], max_pct=0.30)
pc.add_weight_limit("energy", assets=[5,6,7], min_pct=0.10, max_pct=0.25)
# Position bounds and budget
pc.add_position_bounds(min_w=0.02, max_w=0.10)
pc.add_budget(total=1.0)
# Mutual exclusions
pc.add_exclusion(asset_a=0, asset_b=1) # Can't hold both
# CVaR risk constraint
import numpy as np
returns = np.random.normal(0.01, 0.05, (200, 500))
pc.add_cvar_limit(confidence=0.95, max_cvar=0.15, returns=returns)
# Check feasibility
result = pc.check_feasibility()
print(result.feasible) # True/False
print(result.method) # "quick", "sat", "lp", "mip", "cvar"
print(result.infeasible_constraints) # Which constraints conflict
print(result.suggestion) # How to fix it
Architecture: 5-Step Pipeline
Each step is more expensive than the previous. The pipeline stops at the first conclusive result.
| Step | Method | What it checks | When used |
|---|---|---|---|
| 1 | Quick checks | Arithmetic impossibilities | Always |
| 2 | SAT (torc-sat) | Binary constraints (cardinality, exclusions, sectors) | Binary only |
| 3 | LP (scipy.linprog/HiGHS) | Weight constraints (sectors, budget, bounds) | Weight only |
| 4 | MIP (scipy.milp/HiGHS) | Mixed binary + weight constraints | Mixed |
| 5 | CVaR (Rockafellar-Uryasev LP) | Risk constraints | When CVaR present |
Diagnostics: IIS Extraction
When constraints are infeasible, portfolio-optimizer identifies the Irreducible Infeasible Subsystem (IIS) — the minimal set of constraints that cannot be simultaneously satisfied. Analogous to MUS (Minimal Unsatisfiable Subset) in SAT solving.
result = pc.check_feasibility()
if not result.feasible:
print(result.infeasible_constraints)
# ['position_bounds(max_w=0.1)', 'budget(total=1.0)']
# → max 10 assets * 0.1 = 1.0, but cardinality says min 15
print(result.suggestion)
# "Relax position_bounds(max_w) or budget(total)"
Verification (1,143 Tests)
| Suite | Tests | What it verifies |
|---|---|---|
| Exhaustive | 87 | Brute-force all C(n,k) subsets for n<=7, compare with MIP |
| Fuzzing | 246 | Random constraints, verify LP>=MIP monotonicity, solution certification |
| Adversarial | 35 | Near-boundary, degenerate pivots, 1000 assets, overlapping sectors |
| Certification | 341 | Every feasible solution satisfies ALL constraints; every infeasible is brute-force confirmed |
| Parametrized | 320 | Systematic parameter sweeps across all constraint types |
| Unit | 114 | Individual module tests |
pytest tests/ -v # All 1,143 tests in ~7 seconds
Constraint Types
- CardinalityConstraint: min/max number of selected assets
- ExclusionConstraint: two assets cannot both be selected
- SectorMinConstraint: minimum assets from a sector
- DiversificationConstraint: at least 1 asset from each sector
- WeightLimitConstraint: sector weight min/max percentage
- BudgetConstraint: total weight must equal target (default 1.0)
- PositionBoundsConstraint: per-asset weight min/max when selected
- CVaRConstraint: Conditional Value at Risk limit (Rockafellar-Uryasev 2000)
Dependencies
numpyscipy >= 1.11.0(HiGHS MIP solver)torc-sat >= 0.1.1(topological SAT preprocessor)
License & Patent
All Rights Reserved. Carmen Esteban / IAFISCAL & PARTNERS.
This software implements methods protected by patent applications before the Spanish Patent and Trademark Office (OEPM). The topological SAT preprocessing method used in this package (via torc-sat) is the subject of a pending patent application.
- Free for academic research and education.
- Commercial use requires a written license from the author.
- Contact: caresment@gmail.com
Any use of this software or its methods in commercial products, SaaS platforms, or for-profit services without a license agreement constitutes patent infringement under Spanish and EU law.
Metadata
Release files for torc-portfolio 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| torc_portfolio-0.1.0.tar.gz | 45.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| torc_portfolio-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 62.3 kB
Release files / torc_portfolio-0.1.0.tar.gz
| Download URL | torc_portfolio-0.1.0.tar.gz |
|---|---|
| Size | 45.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
23d466ebbfe6f5614d06f369bb69ad36551203fb4a9210f3639aafaa70aaf6f3
|
|
BLAKE2b-256 checksum How to use checksums |
df684d4a443988c222d50ebb75944b94ac1b5f21f8ce738d2a90128aebeb4b8e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / torc_portfolio-0.1.0-py3-none-any.whl
| Download URL | torc_portfolio-0.1.0-py3-none-any.whl |
|---|---|
| Size | 16.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e08320023f96769c2db3631a4635f3b1481392fd18ff9615046cefd9b41f393e
|
|
BLAKE2b-256 checksum How to use checksums |
cb56097f5f449f0d564dd3de82ac78bedab5c1af9dd5153b07edfc0cd43804d8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|