skfolio: scikit-learn's API Applied to Portfolio Construction
Python library for portfolio optimization built on top of scikit-learn
At a glance
- What is it?
- skfolio packages portfolio optimization, factor models and risk management behind the fit and predict interface scikit-learn users already know. It is a framework for comparing allocation methods under cross-validation, not a turnkey strategy engine.
- Who is it for?
- Adopt skfolio if your team already writes scikit-learn pipelines and wants allocation methods (mean-risk, risk budgeting, hierarchical clustering, stacking) to be cross-validated and stress-tested with the same tooling as your other models. Do not adopt it if you need live execution, order management or intraday rebalancing: the library returns weights, not trades.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem skfolio addresses: too many allocation methods, no common test harness
The README's Key Concepts section lays out the argument directly. Mean-variance optimization, in the Markowitz tradition, is described as sensitive to its inputs (expected returns and covariance), prone to weight concentration and high turnover, and weak out of sample. The same passage cites DeMiguel (2007) for the claim that naive allocation such as 1/N and inverse-volatility tends to beat MVO out of sample. The response from the literature has been a long list of fixes: shrinkage, extra constraints, regularization, uncertainty sets, higher moments, Bayesian methods, coherent risk measures, left-tail optimization, distributionally robust optimization, factor models, risk parity, hierarchical clustering, ensemble methods and pre-selection. Each of those is a separate paper with its own notation and its own backtest. skfolio's stated purpose is to put them in one framework so model selection, validation and parameter tuning can be done in a machine-learning style while limiting data leakage and overfitting. The intended user is therefore someone who already thinks in estimators and cross-validation: a quant researcher or data scientist who wants to compare six allocation rules on the same folds rather than read six papers and reimplement each one.
Estimators, not a solver wrapper: how the library is organised
The README groups the library into two model families. Portfolio optimization covers Naive (Equal-Weighted, Inverse-Volatility, Random Dirichlet), Convex (Mean-Risk, Risk Budgeting, Maximum Diversification, Distributionally Robust CVaR, Benchmark Tracker), Clustering (Hierarchical Risk Parity, Hierarchical Equal Risk Contribution, Schur Complementary Allocation, Nested Clusters Optimization) and Ensemble Methods (Stacking Optimization). Prior estimation is the second family: Empirical, a Characteristics-Based Cross-Sectional Factor Model with 46 descriptors across 17 families such as value, size, momentum and profitability, plus Time-Series Factor Model, Black-Litterman, Synthetic Data for stress tests and factor stress tests, and Entropy Pooling. The topics list confirms the underlying machinery: cvxpy and convex optimization, CVaR optimization, efficient frontier, risk parity, hierarchical clustering. The data flow implied by the layout is conventional for this API: a prior estimator supplies expected returns, covariance or factor exposures; an optimization estimator consumes those and produces weights; the meta-estimators from scikit-learn handle fitting, tuning and validation around both. That separation matters because it means you can swap a Black-Litterman prior under a Mean-Risk optimizer without rewriting the allocation code. It also means the library's correctness depends on two things you must check yourself: whether the prior is estimated on data the optimizer never sees, and whether the optimizer's constraints match your mandate.
Installation and the solver question
The README gives one command: pip install -U skfolio. It requires Python 3.10 or later, and the badge in the README lists 3.10, 3.11, 3.12 and 3.13. The README then points to the installation guide for the full dependency list, for conda-forge, and for the mixed-integer solvers. That last item is the one to read before you plan anything. Several of the convex models in this class of library (benchmark tracking with cardinality limits, certain risk-budgeting formulations) are not solvable as pure continuous convex programs; they need a mixed-integer solver, which is not part of a default pip install. The README does not enumerate which models require which solver, so the installation guide is the authoritative source. A second detail worth noting for teams with data-residency constraints: the documentation ships an llms.txt file, per-page Markdown at URLs such as factor_models.html.md, and a single-file llms-full.txt. That is a deliberate choice to make the docs consumable by coding assistants, and it is unusual enough to mention, but it is a documentation feature, not a runtime one.
Where skfolio stops: weights, not orders
Nothing in the supplied material describes order routing, broker connectivity, position keeping or execution algorithms. The library produces portfolio weights from historical inputs. That is the boundary. If your problem is deciding what to hold, skfolio is in scope. If your problem is getting from a target weight vector to filled positions across venues, it is not, and no amount of estimator quality changes that. There is a second boundary that is easy to miss. The README frames the library's value as mitigating data leakage and overfitting through cross-validation and stress testing. Those are procedures you run, not guarantees the library enforces. A walk-forward split that leaks one day of returns, or a hyperparameter search run over the full sample before the final fit, will produce a flattering efficient frontier regardless of which estimator you instantiate. The synthetic data generators (stress test and factor stress test) are the tool the library gives you for the tail scenarios; they do not choose the scenarios for you.
The alternative: PyPortfolioOpt and direct cvxpy
The most direct comparison is PyPortfolioOpt, which also targets mean-variance and related allocations in Python. The difference in approach is the interface contract. PyPortfolioOpt presents a more linear workflow around expected returns and a covariance matrix, with its own conventions for cleaning and adjusting those inputs. skfolio commits to the scikit-learn estimator API, so its objects are meant to be dropped into pipelines, scored with cross-validation splitters, and tuned with scikit-learn's search utilities. If your existing codebase is scikit-learn all the way down, that consistency is the whole point: the same train/test discipline you apply to a classifier applies to a risk-parity allocation. If you want a shorter script that solves one problem and stops, the scikit-learn ceremony is overhead. The other alternative is writing cvxpy models yourself. That gives you exact control over constraints and objective, at the cost of reimplementing priors, clustering methods and the validation scaffolding. skfolio's bet is that the shared interface is worth more than the marginal flexibility. That bet is reasonable for research and comparison work, and weaker for a single bespoke mandate that no estimator in the list expresses.
Maintenance, release cadence and licence
The repository is active, not archived. Recent releases are v1.0.4 on 2026-08-31, v1.0.5 on 2026-09-07 and v1.0.6 on 2026-09-08, and the last push to main is 2026-09-09. Patch releases landing a day apart suggest a maintenance window rather than a stable freeze, so pinning a version in production is sensible. The project is distributed under the 3-Clause BSD licence, which permits commercial use and modification subject to the licence terms; this is a statement of what the README says, not legal advice, and your counsel should review it. The README also states that skfolio is backed by Skfolio Labs, which provides enterprise support and SLAs for institutions. That is a support channel, not a licence change: the open-source package stays BSD-3-Clause. It does mean that if you need a contractual response time, the arrangement exists, and if you do not, you are relying on the public issue tracker and the contributing guide like any other user.
Who should adopt skfolio, and what to verify first
The fit is a research or asset-allocation team that already runs scikit-learn, wants to compare mean-risk, risk-budgeting and clustering allocations on identical folds, and is prepared to read the installation guide before assuming a model will solve. The mismatch is a team that needs execution, or one that wants a single allocation rule with no validation layer, since the framework's value is precisely the validation layer. Three things to verify before you commit. First, run the specific convex model you need and confirm it solves without a mixed-integer solver, or install one. Second, check the prior estimators you plan to use against your data: the cross-sectional factor model expects 46 descriptors across 17 families, and if you cannot supply them, the Empirical prior is the fallback. Third, read the user guide's pages on factor models and stress tests, which are published as Markdown at factor_models.html.md and linked from llms.txt, to see exactly how the ex-ante and ex-post attribution is computed. If those three checks pass, the library's unifying claim holds for your use case. If the first one fails, the model you wanted is out of reach regardless of how clean the interface is.
Editorial conclusion
Adopt skfolio if your team already writes scikit-learn pipelines and wants allocation methods (mean-risk, risk budgeting, hierarchical clustering, stacking) to be cross-validated and stress-tested with the same tooling as your other models. Do not adopt it if you need live execution, order management or intraday rebalancing: the library returns weights, not trades. Before committing, verify that the convex estimators you intend to use solve on your data without a mixed-integer solver, since the installation guide treats those solvers as an optional extra, and confirm the rebalancing and transaction-cost parameters against your own universe.
Community notes