SkillAgentSearch skills...

OptimalPortfolios

Implementation of optimisation analytics for constructing and backtesting optimal portfolios in Python

Install / Use

/learn @ArturSepp/OptimalPortfolios
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

🚀 Optimal Portfolios Construction and Backtesting: optimalportfolios

Production-grade multi-asset portfolio construction and backtesting in Python — from covariance estimation to rolling optimisation to factsheet reporting, in a single pipeline that handles real-world data


| 📊 Metric | 🔢 Value | |-----------|----------| | PyPI Version | PyPI | | Python Versions | Python | | License | License: MIT | | CI Status | CI |

📈 Package Statistics

| 📊 Metric | 🔢 Value | |-----------|----------| | Total Downloads | Total | | Monthly | Monthly | | Weekly | Weekly | | GitHub Stars | GitHub stars | | GitHub Forks | GitHub forks |

Why optimalportfolios <a name="analytics"></a>

Most Python portfolio optimisation packages (PyPortfolioOpt, Riskfolio-Lib, skfolio) solve single-period allocation problems: given a covariance matrix and expected returns, find the optimal weights. This is useful for textbook exercises but insufficient for running a real multi-asset portfolio.

optimalportfolios solves the production problem end-to-end: estimate covariance → compute alpha signals → optimise with constraints → rebalance on schedule → backtest with transaction costs — all in a single roll-forward pipeline that handles incomplete data, mixed-frequency assets, and illiquid positions.

Key differentiators

Production multi-asset portfolio construction. The package implements the full pipeline from the ROSAA framework: factor model covariance estimation (via factorlasso) → risk-budgeted SAA → alpha signal computation → TE-constrained TAA → rolling backtest. No other open-source package handles universes where equities rebalance monthly, alternatives rebalance quarterly, and private equity enters the allocation set only when sufficient return history is available. The constraint system (weight bounds, group allocation limits, tracking error budgets, turnover controls, rebalancing indicators for frozen positions) matches what real institutional PM teams need.

HCGL factor covariance estimation. The Hierarchical Clustering Group LASSO factor model (published in JPM, 2026) produces sparse, structured covariance matrices for heterogeneous multi-asset universes. The LASSO/Group LASSO/HCGL solver is implemented in the standalone factorlasso package — a general-purpose sparse factor model estimator with sign constraints, prior-centered regularisation, and scikit-learn compatible API. optimalportfolios builds on top of factorlasso with finance-specific functionality: FactorCovarEstimator handles multi-frequency asset returns, rolling estimation schedules, factor covariance assembly (Σ_y = β Σ_x β' + D), and integration with qis for performance attribution. The separation means the LASSO solver can be used independently for any multi-output regression problem (genomics, macro-econometrics), while the portfolio-specific rolling pipeline stays in optimalportfolios.

NaN-aware rolling backtesting. The three-layer architecture (solver / wrapper / rolling) automatically handles real-world data: assets with missing prices receive zero weight, assets entering the universe mid-sample are included when sufficient history is available, and the rebalancing indicator system freezes illiquid positions at their current weight while re-optimising the liquid portion. No data cleaning or pre-filtering required.

Research-backed methodology. The package is the reference implementation for the ROSAA framework published in The Journal of Portfolio Management (Sepp, Ossa, Kastenholz, 2026). The optimisation solvers, covariance estimators, and alpha signals are battle-tested on live multi-asset portfolios.

Quick-start: rolling backtest in 10 lines

import qis as qis
from optimalportfolios import (EwmaCovarEstimator, Constraints,
                               PortfolioObjective, compute_rolling_optimal_weights)

prices = ...  # pd.DataFrame of asset prices (may have NaNs, different start dates)
time_period = qis.TimePeriod('31Dec2004', '15Mar2026')

# estimate covariance → optimise → get rolling weights
estimator = EwmaCovarEstimator(returns_freq='W-WED', span=52, rebalancing_freq='QE')
covar_dict = estimator.fit_rolling_covars(prices=prices, time_period=time_period)
weights = compute_rolling_optimal_weights(prices=prices,
                                          portfolio_objective=PortfolioObjective.MAX_DIVERSIFICATION,
                                          constraints=Constraints(is_long_only=True),
                                          time_period=time_period,
                                          covar_dict=covar_dict)

# backtest with transaction costs
portfolio = qis.backtest_model_portfolio(prices=prices, weights=weights,
                                         rebalancing_costs=0.001, ticker='MaxDiv')

That's it — from prices to backtested portfolio in 10 lines, with automatic NaN handling, roll-forward estimation (no hindsight bias), and any optimisation objective. Try doing this with PyPortfolioOpt or skfolio — you'll need to write the rolling loop, covariance estimation, NaN filtering, and backtesting yourself.

Design scope

The optimisation solvers use quadratic and conic objective functions (variance, tracking error, Sharpe ratio, diversification ratio, CARA utility). The package does not implement non-quadratic risk measures (CVaR, MAD, drawdown constraints). For these, use Riskfolio-Lib or skfolio. The solver architecture (three-layer: mathematical / wrapper / rolling) makes it straightforward to add new solvers — each solver lives in its own module under optimization/ (grouped into general/, saa/, and taa/ submodules) and plugs into the rolling backtester via a single dispatch function.

Package overview <a name="overview"></a>

optimalportfolios/
├── alphas/                        # Alpha signal computation
│   ├── signals/
│   │   ├── momentum.py            # compute_momentum_alpha()
│   │   ├── low_beta.py            # compute_low_beta_alpha()
│   │   └── managers_alpha.py      # compute_managers_alpha()
│   ├── alpha_data.py              # AlphasData container
│   ├── backtest_alphas.py         # Signal backtesting tool
│   └── tests/
│       └── signals_test.py
├── covar_estimation/              # Covariance matrix estimation
│   ├── covar_estimator.py         # CovarEstimator ABC
│   ├── ewma_covar_estimator.py    # EwmaCovarEstimator
│   ├── factor_covar_estimator.py  # FactorCovarEstimator (uses factorlasso)
│   ├── factor_covar_data.py       # CurrentFactorCovarData, RollingFactorCovarData
│   └── covar_reporting.py         # Rolling covariance diagnostics
├── optimization/                  # Portfolio optimisation
│   ├── constraints.py             # Constraints, GroupLowerUpperConstraints
│   ├── config.py                  # OptimiserConfig dataclass
│   ├── wrapper_rolling_portfolios.py  # compute_rolling_optimal_weights()
│   ├── general/                   # Objective-driven solvers (no benchmark semantics)
│   │   ├── quadratic.py           # min variance, max quadratic utility
│   │   ├── max_sharpe.py          # maximum Sharpe ratio (Charnes-Cooper)
│   │   ├── max_diversification.py # maximum diversification ratio
│   │   ├── risk_budgeting.py      # constrained risk budgeting (pyrb)
│   │   └── carra_mixture.py       # CARA utility under Gaussian mixture
│   ├── saa/                       # Strategic solvers (CMA inputs, return/vol targets)
│   │   ├── min_variance_target_return.py
│   │   └── max_return_target_vol.py
│   ├── taa/                       # Tactical solvers (alphas, TE constraints, benchmarks)
│   │   ├── maximise_alpha_over_tre.py
│   │   └── maximise_alpha_with_target_yield.py
│   └── tests/                     # One test file per solver
├── utils/                         # Auxiliary analytics
│   ├── filter_nans.py             # NaN-aware covariance/vector filtering
│   ├── portfolio_funcs.py         # Risk contributions, diversification ratio
│   ├── gaussian_mixture.py        # Gaussian mixture fitting (pure numpy/scipy EM)
│   └── returns_unsmoother.py      # AR(1) return unsmoothing for PE/PD
├── reports/                       # Performance reporting
│   └── marginal_backtest.py       # Marginal asset contribution analysis
└── examples/                      # Worked examples and paper reproductions

# External dependency:
# factorlasso (pip install factorlasso)
#   └── LassoModel, solve_lasso_cvx_problem, solve_group_lasso_cvx_problem
#       Sign-constrained LASSO/Group LASSO/HCGL solver (domain-agnostic)
#       https://github.com/ArturSepp/factorlasso

Architecture: factorlasso vs optimalportfolios

factorlasso is the domain-agnostic LASSO solver — it estimates sparse factor loadings β in Y_t = α + β X_t + ε_t with sign constraints, prior-centered regularisation, and HCGL clustering. It provides LassoModel (scikit-learn compatible estimator), CurrentFactorCovarData (single-date covariance decomposition Σ_y = β Σ_x β' + D), and RollingFactorCovarData (time-indexed collection). It knows nothi

View on GitHub
GitHub Stars69
CategoryDevelopment
Updated2d ago
Forks28

Languages

Python

Security Score

100/100

Audited on Apr 3, 2026

No findings