skfolio is a free, open source compliance & risk management project written in Python and released under BSD-3-Clause. It has 2,535 GitHub stars, 285 forks and 30 open issues, and was last pushed 17 hours ago. On this registry it ranks #29 of 55 tracked projects in Compliance & Risk Management, with 5 head-to-head comparisons available.

What is skfolio?

skfolio is an open-source Python library, released under the BSD-3-Clause licence, that gives quantitative developers, researchers and portfolio managers a scikit-learn-compatible toolkit for portfolio optimization, factor model construction and risk management.

What it is

skfolio lives in the Python data-science ecosystem and is built directly on top of scikit-learn. It exposes a unified interface and a set of tools that follow the conventions of that library, so that portfolio models can be built, fine-tuned, cross-validated and stress-tested using the same estimator patterns practitioners already apply to predictive models. The library is distributed under the 3-Clause BSD licence, supports Python 3.10 through 3.14, and is backed by Skfolio Labs, which provides enterprise support and SLAs for institutions.

The concrete problem it addresses is the gap between portfolio construction and the rest of a machine-learning workflow. Allocation, factor modelling and risk analysis have traditionally been handled by separate, hand-written optimization code that sits outside the estimator API, which makes systematic cross-validation and stress testing awkward to express and hard to reproduce. skfolio supplies that missing layer: rather than replacing a named commercial product, it replaces the fragmented bespoke scripting that would otherwise surround a scikit-learn pipeline, folding portfolio construction, backtesting and risk measurement into the same interface. The project's topics reflect that scope directly — asset-allocation, portfolio-construction, portfolio-management, factor-investing, factor-models, backtesting and investment-analysis.

Key capabilities

  • A unified, scikit-learn-compatible interface for building, fine-tuning, cross-validating and stress-testing portfolio models, as stated in the project's own introduction.
  • Portfolio optimization and portfolio construction estimators, covering asset allocation workflows.
  • Factor model construction and factor investing tools, documented in a dedicated factor models section of the user guide.
  • Backtesting facilities for evaluating allocation strategies, reflected in the backtesting topic and the examples gallery.
  • Risk management and investment analysis components, aligning the library with the Compliance & Risk Management category.
  • Support for mixed-integer solvers, documented separately in the installation guide alongside conda-forge instructions.
  • LLM-friendly documentation published under the llms.txt convention, with token-efficient Markdown pages available by appending .md to an HTML URL, plus a consolidated llms-full.txt and an interactive JupyterLite build at skfolio.org/lite.

Who uses it and how

  • Quantitative developers and researchers who already work in Python 3.10 to 3.14 and want portfolio models expressed as scikit-learn estimators rather than standalone scripts.
  • Teams running scikit-learn pipelines who need to cross-validate and stress-test allocation models with the same tooling they use for other estimators.
  • Risk and compliance functions that need repeatable portfolio analysis and backtesting rather than one-off spreadsheet or notebook calculations.
  • Institutions requiring contractual support, which Skfolio Labs supplies through enterprise support and SLAs.
  • Educators and students, who can run the examples directly in the browser through the JupyterLite build, and readers of Daniel P. Palomar's Portfolio Optimization: Theory and Application, which includes Python examples using skfolio.

Getting started

Install the library from PyPI with pip install -U skfolio; the installation guide on skfolio.org covers the full dependency list, conda-forge availability and the additional mixed-integer solvers.

How it compares

The facts provided do not name any comparable portfolio optimization libraries, so skfolio stands alone in this registry on that axis. Its distinguishing characteristics, as documented, are the scikit-learn compatibility of its interface, its BSD-3-Clause licence, and the availability of a commercial support path through Skfolio Labs while the code itself remains open source.

When to use it — and when not

Choose skfolio if the team already works in Python and scikit-learn and wants portfolio construction, factor modelling and backtesting to share one estimator interface; be prepared to manage the Python environment yourself, including the separate installation of mixed-integer solvers if those optimizations are needed. It is not a hosted platform or a point-and-click application, so anyone without Python skills should look elsewhere. Note also that the README is largely badge and link scaffolding — the substantive content lives on the documentation site, the user guide and the API reference, so evaluate those before committing.

project readme (upstream, from github) — read inline

.. -- mode: rst --

.. The regions delimited by the skfolio-shared-*-start and skfolio-shared-*-end comments are included verbatim in docs/index.rst. Do not rename or remove them. Content placed outside those regions stays in the README only.

|Licence| |Codecov| |PythonVersion| |PyPi| |CI/CD| |Downloads| |Ruff| |Contribution| |Website| |JupyterLite| |Discord| |DOI|

.. |Licence| image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg :target: https://github.com/skfolio/skfolio/blob/main/LICENSE

.. |Codecov| image:: https://codecov.io/gh/skfolio/skfolio/graph/badge.svg?token=KJ0SE4LHPV :target: https://codecov.io/gh/skfolio/skfolio

.. |PythonVersion| image:: https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue.svg :target: https://pypi.org/project/skfolio/

.. |PyPi| image:: https://img.shields.io/pypi/v/skfolio :target: https://pypi.org/project/skfolio

.. |CI/CD| image:: https://img.shields.io/github/actions/workflow/status/skfolio/skfolio/release.yml.svg?logo=github :target: https://github.com/skfolio/skfolio/actions

.. |Downloads| image:: https://static.pepy.tech/badge/skfolio :target: https://pepy.tech/project/skfolio

.. |Ruff| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json :target: https://github.com/astral-sh/ruff

.. |Contribution| image:: https://img.shields.io/badge/Contributions-Welcome-blue :target: https://github.com/skfolio/skfolio/blob/main/CONTRIBUTING.md

.. |Website| image:: https://img.shields.io/website.svg?down_color=red&down_message=down&up_color=53cc0d&up_message=up&url=https://skfolio.org :target: https://skfolio.org

.. |JupyterLite| image:: https://jupyterlite.rtfd.io/en/latest/_static/badge.svg :target: https://skfolio.org/lite

.. |Discord| image:: https://img.shields.io/badge/Discord-Join%20Chat-5865F2?logo=discord&logoColor=white :target: https://discord.gg/Bu7EtNYugS

.. |DOI| image:: https://zenodo.org/badge/731792488.svg :target: https://doi.org/10.5281/zenodo.16148630

=============== |icon| skfolio

.. |icon| image:: https://raw.githubusercontent.com/skfolio/skfolio/main/docs/_static/logo_animate.svg :width: 100 :alt: skfolio documentation

.. skfolio-shared-introduction-start

skfolio is a Python library for portfolio optimization, factor model construction, and risk management built on top of scikit-learn. It offers a unified interface and tools compatible with scikit-learn to build, fine-tune, cross-validate, and stress-test portfolio models.

It is distributed under the open-source 3-Clause BSD license.

skfolio is backed by Skfolio Labs _, which provides enterprise support and SLAs for institutions.

.. skfolio-shared-introduction-end

.. image:: https://raw.githubusercontent.com/skfolio/skfolio/main/docs/_static/expo.jpg :target: https://skfolio.org/auto_examples/index.html :alt: examples

.. skfolio-shared-body-start

Important links


- `Examples `_
- `User Guide `_
- `API Reference `_
- `GitHub Repo `_
- `Enterprise Support `_

Featured in
~~~~~~~~~~~

* `Portfolio Optimization: Theory and Application `_ by Daniel P. Palomar, includes Python code examples using skfolio.

Installation
~~~~~~~~~~~~

.. |PythonMinVersion| replace:: 3.10

`skfolio` requires Python |PythonMinVersion| or later and can be installed with:

.. code:: bash

    pip install -U skfolio

See the `installation guide `_ for the full
dependency list, for conda-forge and for the mixed-integer solvers.

LLM-friendly documentation

The documentation follows the llms.txt convention _ and provides token-efficient Markdown alongside the HTML site:

  • Start with llms.txt _ to find relevant pages.
  • Read only the Markdown pages needed by appending .md to their HTML URLs, for example factor_models.html.md _.
  • Use llms-full.txt _ only when the complete documentation is required in a single file.

Contribution


We welcome contributions of all kinds. Whether it's reporting a bug, suggesting an
improvement, or submitting code, your input helps make `skfolio` better. See the
`contributing guide `_
to get started.

Key Concepts

Since the development of modern portfolio theory by Markowitz (1952), mean-variance optimization (MVO) has received considerable attention.

Unfortunately, it faces a number of shortcomings, including high sensitivity to the input parameters (expected returns and covariance), weight concentration, high turnover, and poor out-of-sample performance.

It is well-known that naive allocation (1/N, inverse-vol, etc.) tends to outperform MVO out-of-sample (DeMiguel, 2007).

Numerous approaches have been developed to alleviate these shortcomings (shrinkage, additional constraints, regularization, uncertainty set, higher moments, Bayesian approaches, coherent risk measures, left-tail risk optimization, distributionally robust optimization, factor model, risk-parity, hierarchical clustering, ensemble methods, pre-selection, etc.).

Given the large number of methods, and the fact that they can be combined, there is a need for a unified framework with a machine-learning approach to perform model selection, validation, and parameter tuning while mitigating the risk of data leakage and overfitting.

This framework is built on scikit-learn's API.

Available models


* Portfolio Optimization:
    * 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
    * Ensemble Methods:
        * Stacking Optimization

* Prior Estimator:
    * Empirical
    * Characteristics-Based Cross-Sectional Factor Model:
        * 46 descriptors across 17 families (e.g. value, size, momentum, profitability)
        * Factor Exposures
        * Cross-Sectional Regression
        * Alpha Estimators
        * Forecast Evaluation
        * Ex-post and Ex-ante Attribution
    * Time-Series Factor Model
    * Black & Litterman
    * Synthetic Data (Stress Test, Factor Stress Test)
    * Entropy Pooling
    * Opinion Pooling

* Expected Returns Estimator:
    * Empirical
    * Exponentially Weighted
    * Equilibrium
    * Shrinkage

* Covariance Estimator:
    * Empirical
    * Gerber
    * Denoising
    * Detoning
    * Exponentially Weighted
    * Regime-Adjusted Exponentially Weighted
    * Ledoit-Wolf
    * Oracle Approximating Shrinkage
    * Shrunk Covariance
    * Geodesic Shrinkage Covariance
    * Graphical Lasso CV
    * Implied Covariance

* Variance Estimator:
    * Empirical
    * Exponentially Weighted
    * Regime-Adjusted Exponentially Weighted

* Distance Estimator:
    * Pearson Distance
    * Kendall Distance
    * Spearman Distance
    * Covariance Distance (based on any of the above covariance estimators)
    * Distance Correlation
    * Variation of Information

* Seriation Estimator:
    * Hierarchical Seriation
    * Spectral Seriation

* Distribution Estimator:
    * Univariate:
        * Gaussian
        * Student's t
        * Johnson Su
        * Normal Inverse Gaussian
    * Bivariate Copula
        * Gaussian Copula
        * Student's t Copula
        * Clayton Copula
        * Gumbel Copula
        * Joe Copula
        * Independent Copula
    * Multivariate
        * Vine Copula (Regular, Centered, Clustered, Conditional Sampling)

* Uncertainty Set Estimator:
    * On Expected Returns:
        * Empirical
        * Circular Bootstrap
    * On Covariance:
        * Empirical
        * Circular Bootstrap

* Pre-Selection Transformers:
    * Non-Dominated Selection
    * Select K Extremes (Best or Worst)
    * Drop Highly Correlated Assets
    * Select Non-Expiring Assets
    * Select Complete Assets (handle late inception, delisting, etc.)
    * Drop Zero Variance

* Cross-Sectional Transformers:
    * Standard Scaler (z-score)
    * Percentile Rank Scaler
    * Gaussian Rank Scaler (rank gaussianization)
    * Winsorizer (percentile clipping)
    * Tanh Shrinker (smooth outlier shrinkage)

* Cross-Validation and Model Selection:
    * Compatible with all `sklearn` methods (KFold, etc.)
    * Walk Forward
    * Combinatorial Purged Cross-Validation
    * Multiple Randomized Cross-Validation
    * Covariance Forecast Evaluation
    * Online Predict and Online Score

* Hyper-Parameter Tuning:
    * Compatible with all `sklearn` methods (GridSearchCV, RandomizedSearchCV)
    * Online Grid Search and Online Randomized Search

* Risk Measures:
    * Variance
    * Semi-Variance
    * Mean Absolute Deviation
    * First Lower Partial Moment
    * CVaR (Conditional Value at Risk)
    * EVaR (Entropic Value at Risk)
    * Worst Realization
    * CDaR (Conditional Drawdown at Risk)
    * Maximum Drawdown
    * Average Drawdown
    * EDaR (Entropic Drawdown at Risk)
    * Ulcer Index
    * Gini Mean Difference
    * Value at Risk
    * Drawdown at Risk
    * Entropic Risk Measure
    * Fourth Central Moment
    * Fourth Lower Partial Moment
    * Skew
    * Kurtosis

* Optimization Features:
    * Minimize Risk
    * Maximize Returns
    * Maximize Utility
    * Maximize Ratio
    * Transaction Costs
    * Management Fees
    * L1 and L2 Regularization
    * Weight Constraints
    * Group Constraints
    * Budget Constraints
    * Tracking Error Constraints
    * Turnover Constraints
    * Cardinality and Group Cardinality Constraints
    * Threshold (Long and Short) Constraints

Quickstart
~~~~~~~~~~
The code snippets below are designed to introduce the functionality of `skfolio` so you
can start using it quickly. It follows the same API as scikit-learn.

Imports
-------
.. code-block:: python

    from sklearn import set_config
    from sklearn.model_selection import (
        GridSearchCV,
        KFold,
        RandomizedSearchCV,
        train_test_split,
    )
    from sklearn.pipeline import Pipeline
    from scipy.stats import loguniform

    from skfolio import RatioMeasure, RiskMeasure
    from skfolio.datasets import (
        load_factors_dataset,
        load_sp500_dataset,
        make_synthetic_characteristics,
    )
    from skfolio.descriptor import (
        BookToPrice,
        CashFlowToPrice,
        EWMarketBeta,
        EWMomentum,
        EWResidualVolatility,
        EWVolatility,
        LogMarketCap,
        SalesToPrice,
    )
    from skfolio.distribution import VineCopula
    from skfolio.factor_exposure import (
        DerivedFactor,
        FixedWeightedFactor,
        GlobalFactor,
        OneHotCategoricalFactors,
    )
    from skfolio.model_selection import (
        CombinatorialPurgedCV,
        WalkForward,
        cross_val_predict,
    )
    from skfolio.moments import (
        DenoiseCovariance,
        DetoneCovariance,
        EWMu,
        GerberCovariance,
        ShrunkMu,
    )
    from skfolio.optimization import (
        MeanRisk,
        HierarchicalRiskParity,
        NestedClustersOptimization,
        ObjectiveFunction,
        RiskBudgeting,
    )
    from skfolio.pre_selection import SelectKExtremes
    from skfolio.preprocessing import prices_to_returns
    from skfolio.prior import (
        BlackLitterman,
        CharacteristicsFactorModel,
        EmpiricalPrior,
        EntropyPooling,
        TimeSeriesFactorModel,
        OpinionPooling,
        SyntheticData,
    )
    from skfolio.uncertainty_set import BootstrapMuUncertaintySet

Load Dataset
------------
.. code-block:: python

    prices = load_sp500_dataset()

Train/Test split
----------------
.. code-block:: python

    X = prices_to_returns(prices)
    X_train, X_test = train_test_split(X, test_size=0.33, shuffle=False)


Minimum Variance
----------------
.. code-block:: python

    model = MeanRisk()

Fit on Training Set
-------------------
.. code-block:: python

    model.fit(X_train)

    print(model.weights_)

Predict on Test Set
-------------------
.. code-block:: python

    portfolio = model.predict(X_test)

    print(portfolio.annualized_sharpe_ratio)
    print(portfolio.summary())



Maximum Sortino Ratio
---------------------
.. code-block:: python

    model = MeanRisk(
        objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
        risk_measure=RiskMeasure.SEMI_VARIANCE,
    )


Denoised Covariance & Shrunk Expected Returns
---------------------------------------------
.. code-block:: python

    model = MeanRisk(
        objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
        prior_estimator=EmpiricalPrior(
            mu_estimator=ShrunkMu(), covariance_estimator=DenoiseCovariance()
        ),
    )

Uncertainty Set on Expected Returns
-----------------------------------
.. code-block:: python

    model = MeanRisk(
        objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
        mu_uncertainty_set_estimator=BootstrapMuUncertaintySet(),
    )


Weight Constraints & Transaction Costs
--------------------------------------
.. code-block:: python

    model = MeanRisk(
        min_weights={"AAPL": 0.10, "JPM": 0.05},
        max_weights=0.8,
        transaction_costs={"AAPL": 0.0001, "RRC": 0.0002},
        groups=[
            ["Equity"] * 3 + ["Fund"] * 5 + ["Bond"] * 12,
            ["US"] * 2 + ["Europe"] * 8 + ["Japan"] * 10,
        ],
        linear_constraints=[
            "Equity = 0.1",
            "Europe >= 0.5 * Fund",
            "Japan `_ and the `Factor Models tutorials
`_.

Time-Series Factor Model
------------------------
.. code-block:: python

    factor_prices = load_factors_dataset()

    X, factors = prices_to_returns(prices, factor_prices)
    X_train, X_test, factors_train, factors_test = train_test_split(
        X, factors, test_size=0.33, shuffle=False
    )

    model = MeanRisk(prior_estimator=TimeSeriesFactorModel())
    model.fit(X_train, factors=factors_train)

    print(model.weights_)

    portfolio = model.predict(X_test)

    print(portfolio.calmar_ratio)
    print(portfolio.summary())

Time-Series Factor Model & Covariance Detoning
----------------------------------------------
.. code-block:: python

    model = MeanRisk(
        prior_estimator=TimeSeriesFactorModel(
            factor_prior_estimator=EmpiricalPrior(covariance_estimator=DetoneCovariance())
        )
    )

Black & Litterman Time-Series Factor Model
------------------------------------------
.. code-block:: python

    factor_views = ["MTUM - QUAL == 0.03 ", "VLUE == 0.06"]
    model = MeanRisk(
        objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
        prior_estimator=TimeSeriesFactorModel(
            factor_prior_estimator=BlackLitterman(views=factor_views),
        ),
    )

Pre-Selection Pipeline
----------------------
.. code-block:: python

    set_config(transform_output="pandas")
    model = Pipeline(
        [
            ("pre_selection", SelectKExtremes(k=10, highest=True)),
            ("optimization", MeanRisk()),
        ]
    )
    model.fit(X_train)

    portfolio = model.predict(X_test)




K-fold Cross-Validation
-----------------------
.. code-block:: python

    model = MeanRisk()
    mpp = cross_val_predict(model, X_test, cv=KFold(n_splits=5))
    # mpp is the predicted MultiPeriodPortfolio object composed of 5 Portfolios (1 per testing fold)

    mpp.plot_cumulative_returns()
    print(mpp.summary())


Combinatorial Purged Cross-Validation
-------------------------------------
.. code-block:: python

    model = MeanRisk()

    cv = CombinatorialPurgedCV(n_folds=10, n_test_folds=2)

    print(cv.summary(X_test))

    population = cross_val_predict(model, X_test, cv=cv)

    population.plot_distribution(
        measure_list=[RatioMeasure.SHARPE_RATIO, RatioMeasure.SORTINO_RATIO]
    )
    population.plot_cumulative_returns()
    print(population.summary())


Minimum CVaR Optimization on Synthetic Returns
----------------------------------------------
.. code-block:: python

    vine = VineCopula(log_transform=True, n_jobs=-1)
    prior = SyntheticData(distribution_estimator=vine, n_samples=2000)
    model = MeanRisk(risk_measure=RiskMeasure.CVAR, prior_estimator=prior)
    model.fit(X)
    print(model.weights_)


Stress Test
-----------
.. code-block:: python

    vine = VineCopula(log_transform=True, central_assets=["BAC"], n_jobs=-1)
    vine.fit(X)
    X_stressed = vine.sample(n_samples=10_000, conditioning = {"BAC": -0.2})
    ptf_stressed = model.predict(X_stressed)


Minimum CVaR Optimization on Synthetic Factors
----------------------------------------------
.. code-block:: python

    vine = VineCopula(central_assets=["QUAL"], log_transform=True, n_jobs=-1)
    factor_prior = SyntheticData(
        distribution_estimator=vine,
        n_samples=10_000,
        sample_args=dict(conditioning={"QUAL": -0.2}),
    )
    factor_model = TimeSeriesFactorModel(factor_prior_estimator=factor_prior)
    model = MeanRisk(risk_measure=RiskMeasure.CVAR, prior_estimator=factor_model)
    model.fit(X, factors=factors)
    print(model.weights_)


Factor Stress Test
------------------
.. code-block:: python

    factor_model.set_params(factor_prior_estimator__sample_args=dict(
        conditioning={"QUAL": -0.5}
    ))
    factor_model.fit(X, factors=factors)
    stressed_dist = factor_model.return_distribution_
    stressed_ptf = model.predict(stressed_dist)

Entropy Pooling
---------------
.. code-block:: python

    entropy_pooling = EntropyPooling(
        mean_views=[
            "JPM == -0.002",
            "PG >= LLY",
            "BAC >= prior(BAC) * 1.2",
        ],
        cvar_views=[
            "GE == 0.08",
        ],
    )
    entropy_pooling.fit(X)
    print(entropy_pooling.relative_entropy_)
    print(entropy_pooling.effective_number_of_scenarios_)
    print(entropy_pooling.return_distribution_.sample_weight)

CVaR Hierarchical Risk Parity optimization on Entropy Pooling
-------------------------------------------------------------
.. code-block:: python

    entropy_pooling = EntropyPooling(cvar_views=["GE == 0.08"])
    model = HierarchicalRiskParity(
        risk_measure=RiskMeasure.CVAR,
        prior_estimator=entropy_pooling
    )
    model.fit(X)
    print(model.weights_)

Stress Test with Entropy Pooling on Factor Synthetic Data
---------------------------------------------------------
.. code-block:: python

    # Regular Vine Copula and sampling of 100,000 synthetic factor returns
    factor_synth = SyntheticData(
        n_samples=100_000,
        distribution_estimator=VineCopula(log_transform=True, n_jobs=-1, random_state=0)
    )

    # Entropy Pooling by imposing a CVaR-95% of 10% on the Quality factor
    factor_entropy_pooling = EntropyPooling(
        prior_estimator=factor_synth,
        cvar_views=["QUAL == 0.10"],
    )

    factor_model = TimeSeriesFactorModel(factor_prior_estimator=factor_entropy_pooling)
    factor_model.fit(X, factors=factors)

    # We retrieve the stressed distribution:
    stressed_dist = factor_model.return_distribution_

    # We stress-test our portfolio:
    stressed_ptf = model.predict(stressed_dist)

Opinion Pooling
---------------
.. code-block:: python

    # We consider two expert opinions, each generated via Entropy Pooling with
    # user-defined views.
    # We assign probabilities of 40% to Expert 1, 50% to Expert 2, and by default
    # the remaining 10% is allocated to the prior distribution:
    opinion_1 = EntropyPooling(cvar_views=["AMD == 0.10"])
    opinion_2 = EntropyPooling(
        mean_views=["AMD >= BAC", "JPM `_ and `cvxpy `_, as well as the contributors of the following resources:

    * PyPortfolioOpt
    * Riskfolio-Lib
    * scikit-portfolio
    * statsmodels
    * rsome
    * `Microprediction `_ (Peter Cotton)
    * `Portfolio Optimization Book `_ (Daniel P. Palomar)
    * *The Elements of Quantitative Investing* (Giuseppe Paleologo)
    * `quantresearch.org `_ (Marcos López de Prado)
    * gautier.marti.ai (Gautier Marti)


Citation
~~~~~~~~

If you use `skfolio` in a scientific publication, we would appreciate citations:

**The library:**

.. code-block:: bibtex

        @software{skfolio,
          title     = {skfolio},
          author    = {Delatte, Hugo and Nicolini, Carlo and Manzi, Matteo},
          year      = {2026},
          doi       = {10.5281/zenodo.16148630},
          url       = {https://doi.org/10.5281/zenodo.16148630}
        }

The citation above refers to skfolio across all versions. Its concept DOI resolves
to the latest version archived on Zenodo.

For reproducible research, we recommend citing the specific release you used. Visit
the `Zenodo project page `_, select that
release, and use its citation so that the DOI, version, and publication date
correspond to the same release.

**The paper:**

.. code-block:: bibtex

        @article{nicolini2025skfolio,
          title         = {skfolio: Portfolio Optimization in Python},
          author        = {Nicolini, Carlo and Manzi, Matteo and Delatte, Hugo},
          journal       = {arXiv preprint arXiv:2507.04176},
          year          = {2025},
          eprint        = {2507.04176},
          archivePrefix = {arXiv},
          url           = {https://arxiv.org/abs/2507.04176}
        }

.. skfolio-shared-body-end

Repository mirror

The project is also mirrored on AtomGit . GitHub remains the primary repository for development and contributions.

Frequently asked questions

Is skfolio free to use?

skfolio is open source under the BSD-3-Clause licence. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does skfolio do?

Python library for portfolio optimization, factor model construction, and risk management built on scikit-learn

What is skfolio written in?

skfolio is primarily written in Python. Its source is publicly available at https://github.com/skfolio/skfolio, and it has 2,535 GitHub stars.