Name | skfolio JSON |
Version |
0.5.2
JSON |
| download |
home_page | None |
Summary | Portfolio optimization built on top of scikit-learn |
upload_time | 2024-11-17 21:58:00 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.10 |
license | BSD 3-Clause License Copyright (c) 2007-2023 The skfolio developers. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
keywords |
portfolio
optimization
optimisation
finance
asset
allocation
quantitative
quant
investment
strategy
machine-learning
scikit-learn
data-mining
data-science
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
.. -*- mode: rst -*-
|Licence| |Codecov| |Black| |PythonVersion| |PyPi| |CI/CD| |Downloads| |Ruff| |Contribution| |Website| |JupyterLite|
.. |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-blue.svg
:target: https://pypi.org/project/skfolio/
.. |PyPi| image:: https://img.shields.io/pypi/v/skfolio
:target: https://pypi.org/project/skfolio
.. |Black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
.. |CI/CD| image:: https://img.shields.io/github/actions/workflow/status/skfolio/skfolio/release.yml.svg?logo=github
:target: https://github.com/skfolio/skfolio/raw/main/LICENSE
.. |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
.. |PythonMinVersion| replace:: 3.10
.. |NumpyMinVersion| replace:: 1.23.4
.. |ScipyMinVersion| replace:: 1.8.0
.. |PandasMinVersion| replace:: 1.4.1
.. |CvxpyMinVersion| replace:: 1.4.1
.. |SklearnMinVersion| replace:: 1.5.0
.. |JoblibMinVersion| replace:: 1.3.2
.. |PlotlyMinVersion| replace:: 5.22.0
===============
|icon| skfolio
===============
.. |icon| image:: https://raw.githubusercontent.com/skfolio/skfolio/master/docs/_static/logo_animate.svg
:width: 100
:alt: skfolio documentation
:target: https://skfolio.org/
**skfolio** is a Python library for portfolio optimization built on top of scikit-learn.
It offers a unified interface and tools compatible with scikit-learn to build, fine-tune,
and cross-validate portfolio models.
It is distributed under the open source 3-Clause BSD license.
.. image:: https://raw.githubusercontent.com/skfolio/skfolio/master/docs/_static/expo.jpg
:target: https://skfolio.org/auto_examples/
:alt: examples
Important links
~~~~~~~~~~~~~~~
- Documentation: https://skfolio.org/
- Examples: https://skfolio.org/auto_examples/
- User Guide: https://skfolio.org/user_guide/
- GitHub Repo: https://github.com/skfolio/skfolio/
Installation
~~~~~~~~~~~~
`skfolio` is available on PyPI and can be installed with::
pip install -U skfolio
Dependencies
~~~~~~~~~~~~
`skfolio` requires:
- python (>= |PythonMinVersion|)
- numpy (>= |NumpyMinVersion|)
- scipy (>= |ScipyMinVersion|)
- pandas (>= |PandasMinVersion|)
- cvxpy (>= |CvxpyMinVersion|)
- scikit-learn (>= |SklearnMinVersion|)
- joblib (>= |JoblibMinVersion|)
- plotly (>= |PlotlyMinVersion|)
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.).
With this large number of methods, added to the fact that they can be composed together,
there is a need for a unified framework with a machine learning approach to perform
model selection, validation, and parameter tuning while reducing 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
* Clustering:
* Hierarchical Risk Parity
* Hierarchical Equal Risk Contribution
* Nested Clusters Optimization
* Ensemble Methods:
* Stacking Optimization
* Expected Returns Estimator:
* Empirical
* Exponentially Weighted
* Equilibrium
* Shrinkage
* Covariance Estimator:
* Empirical
* Gerber
* Denoising
* Detoning
* Exponentially Weighted
* Ledoit-Wolf
* Oracle Approximating Shrinkage
* Shrunk Covariance
* Graphical Lasso CV
* Implied Covariance
* Distance Estimator:
* Pearson Distance
* Kendall Distance
* Spearman Distance
* Covariance Distance (based on any of the above covariance estimators)
* Distance Correlation
* Variation of Information
* Prior Estimator:
* Empirical
* Black & Litterman
* Factor Model
* Uncertainty Set Estimator:
* On Expected Returns:
* Empirical
* Circular Bootstrap
* On Covariance:
* Empirical
* Circular bootstrap
* Pre-Selection Transformer:
* Non-Dominated Selection
* Select K Extremes (Best or Worst)
* Drop Highly Correlated Assets
* Cross-Validation and Model Selection:
* Compatible with all `sklearn` methods (KFold, etc.)
* Walk Forward
* Combinatorial Purged Cross-Validation
* Hyper-Parameter Tuning:
* Compatible with all `sklearn` methods (GridSearchCV, RandomizedSearchCV)
* 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
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
from skfolio.model_selection import (
CombinatorialPurgedCV,
WalkForward,
cross_val_predict,
)
from skfolio.moments import (
DenoiseCovariance,
DetoneCovariance,
EWMu,
GerberCovariance,
ShrunkMu,
)
from skfolio.optimization import (
MeanRisk,
NestedClustersOptimization,
ObjectiveFunction,
RiskBudgeting,
)
from skfolio.pre_selection import SelectKExtremes
from skfolio.preprocessing import prices_to_returns
from skfolio.prior import BlackLitterman, EmpiricalPrior, FactorModel
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.5 * Bond",
"US >= 0.1",
"Europe >= 0.5 * Fund",
"Japan <= 1",
],
)
model.fit(X_train)
Risk Parity on CVaR
-------------------
.. code-block:: python
model = RiskBudgeting(risk_measure=RiskMeasure.CVAR)
Risk Parity & Gerber Covariance
-------------------------------
.. code-block:: python
model = RiskBudgeting(
prior_estimator=EmpiricalPrior(covariance_estimator=GerberCovariance())
)
Nested Cluster Optimization with Cross-Validation and Parallelization
---------------------------------------------------------------------
.. code-block:: python
model = NestedClustersOptimization(
inner_estimator=MeanRisk(risk_measure=RiskMeasure.CVAR),
outer_estimator=RiskBudgeting(risk_measure=RiskMeasure.VARIANCE),
cv=KFold(),
n_jobs=-1,
)
Randomized Search of the L2 Norm
--------------------------------
.. code-block:: python
randomized_search = RandomizedSearchCV(
estimator=MeanRisk(),
cv=WalkForward(train_size=252, test_size=60),
param_distributions={
"l2_coef": loguniform(1e-3, 1e-1),
},
)
randomized_search.fit(X_train)
best_model = randomized_search.best_estimator_
print(best_model.weights_)
Grid Search on Embedded Parameters
----------------------------------
.. code-block:: python
model = MeanRisk(
objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
risk_measure=RiskMeasure.VARIANCE,
prior_estimator=EmpiricalPrior(mu_estimator=EWMu(alpha=0.2)),
)
print(model.get_params(deep=True))
gs = GridSearchCV(
estimator=model,
cv=KFold(n_splits=5, shuffle=False),
n_jobs=-1,
param_grid={
"risk_measure": [
RiskMeasure.VARIANCE,
RiskMeasure.CVAR,
RiskMeasure.VARIANCE.CDAR,
],
"prior_estimator__mu_estimator__alpha": [0.05, 0.1, 0.2, 0.5],
},
)
gs.fit(X)
best_model = gs.best_estimator_
print(best_model.weights_)
Black & Litterman Model
-----------------------
.. code-block:: python
views = ["AAPL - BBY == 0.03 ", "CVX - KO == 0.04", "MSFT == 0.06 "]
model = MeanRisk(
objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
prior_estimator=BlackLitterman(views=views),
)
Factor Model
------------
.. code-block:: python
factor_prices = load_factors_dataset()
X, y = prices_to_returns(prices, factor_prices)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, shuffle=False)
model = MeanRisk(prior_estimator=FactorModel())
model.fit(X_train, y_train)
print(model.weights_)
portfolio = model.predict(X_test)
print(portfolio.calmar_ratio)
print(portfolio.summary())
Factor Model & Covariance Detoning
----------------------------------
.. code-block:: python
model = MeanRisk(
prior_estimator=FactorModel(
factor_prior_estimator=EmpiricalPrior(covariance_estimator=DetoneCovariance())
)
)
Black & Litterman Factor Model
------------------------------
.. code-block:: python
factor_views = ["MTUM - QUAL == 0.03 ", "VLUE == 0.06"]
model = MeanRisk(
objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
prior_estimator=FactorModel(
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()
mmp = cross_val_predict(model, X_test, cv=KFold(n_splits=5))
# mmp is the predicted MultiPeriodPortfolio object composed of 5 Portfolios (1 per testing fold)
mmp.plot_cumulative_returns()
print(mmp.summary())
Combinatorial Purged Cross-Validation
-------------------------------------
.. code-block:: python
model = MeanRisk()
cv = CombinatorialPurgedCV(n_folds=10, n_test_folds=2)
print(cv.get_summary(X_train))
population = cross_val_predict(model, X_train, cv=cv)
population.plot_distribution(
measure_list=[RatioMeasure.SHARPE_RATIO, RatioMeasure.SORTINO_RATIO]
)
population.plot_cumulative_returns()
print(population.summary())
Recognition
~~~~~~~~~~~
We would like to thank all contributors behind our direct dependencies, such as
scikit-learn and cvxpy, but also the contributors of the following resources that were a
source of inspiration:
* PyPortfolioOpt
* Riskfolio-Lib
* scikit-portfolio
* microprediction
* statsmodels
* rsome
* gautier.marti.ai
Citation
~~~~~~~~
If you use `skfolio` in a scientific publication, we would appreciate citations:
Bibtex entry::
@misc{skfolio,
author = {Delatte, Hugo and Nicolini, Carlo},
title = {skfolio},
year = {2023},
url = {https://github.com/skfolio/skfolio}
}
Raw data
{
"_id": null,
"home_page": null,
"name": "skfolio",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": "Hugo Delatte <delatte.hugo@gmail.com>",
"keywords": "portfolio, optimization, optimisation, finance, asset, allocation, quantitative, quant, investment, strategy, machine-learning, scikit-learn, data-mining, data-science",
"author": null,
"author_email": "Hugo Delatte <delatte.hugo@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/44/b2/e2f28be8c6aaa9b641f3b578429563b9981943b93ee249e86ab0db17aafb/skfolio-0.5.2.tar.gz",
"platform": null,
"description": ".. -*- mode: rst -*-\n\n|Licence| |Codecov| |Black| |PythonVersion| |PyPi| |CI/CD| |Downloads| |Ruff| |Contribution| |Website| |JupyterLite|\n\n.. |Licence| image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg\n :target: https://github.com/skfolio/skfolio/blob/main/LICENSE\n\n.. |Codecov| image:: https://codecov.io/gh/skfolio/skfolio/graph/badge.svg?token=KJ0SE4LHPV\n :target: https://codecov.io/gh/skfolio/skfolio\n\n.. |PythonVersion| image:: https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue.svg\n :target: https://pypi.org/project/skfolio/\n\n.. |PyPi| image:: https://img.shields.io/pypi/v/skfolio\n :target: https://pypi.org/project/skfolio\n\n.. |Black| image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/psf/black\n\n.. |CI/CD| image:: https://img.shields.io/github/actions/workflow/status/skfolio/skfolio/release.yml.svg?logo=github\n :target: https://github.com/skfolio/skfolio/raw/main/LICENSE\n\n.. |Downloads| image:: https://static.pepy.tech/badge/skfolio\n :target: https://pepy.tech/project/skfolio\n\n.. |Ruff| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json\n :target: https://github.com/astral-sh/ruff\n\n.. |Contribution| image:: https://img.shields.io/badge/Contributions-Welcome-blue\n :target: https://github.com/skfolio/skfolio/blob/main/CONTRIBUTING.md\n\n.. |Website| image:: https://img.shields.io/website.svg?down_color=red&down_message=down&up_color=53cc0d&up_message=up&url=https://skfolio.org\n :target: https://skfolio.org\n\n.. |JupyterLite| image:: https://jupyterlite.rtfd.io/en/latest/_static/badge.svg\n :target: https://skfolio.org/lite\n\n.. |PythonMinVersion| replace:: 3.10\n.. |NumpyMinVersion| replace:: 1.23.4\n.. |ScipyMinVersion| replace:: 1.8.0\n.. |PandasMinVersion| replace:: 1.4.1\n.. |CvxpyMinVersion| replace:: 1.4.1\n.. |SklearnMinVersion| replace:: 1.5.0\n.. |JoblibMinVersion| replace:: 1.3.2\n.. |PlotlyMinVersion| replace:: 5.22.0\n\n\n===============\n|icon| skfolio\n===============\n.. |icon| image:: https://raw.githubusercontent.com/skfolio/skfolio/master/docs/_static/logo_animate.svg\n :width: 100\n :alt: skfolio documentation\n :target: https://skfolio.org/\n\n\n**skfolio** is a Python library for portfolio optimization built on top of scikit-learn.\nIt offers a unified interface and tools compatible with scikit-learn to build, fine-tune,\nand cross-validate portfolio models.\n\nIt is distributed under the open source 3-Clause BSD license.\n\n.. image:: https://raw.githubusercontent.com/skfolio/skfolio/master/docs/_static/expo.jpg\n :target: https://skfolio.org/auto_examples/\n :alt: examples\n\nImportant links\n~~~~~~~~~~~~~~~\n\n- Documentation: https://skfolio.org/\n- Examples: https://skfolio.org/auto_examples/\n- User Guide: https://skfolio.org/user_guide/\n- GitHub Repo: https://github.com/skfolio/skfolio/\n\nInstallation\n~~~~~~~~~~~~\n\n`skfolio` is available on PyPI and can be installed with::\n\n pip install -U skfolio\n\n\n\nDependencies\n~~~~~~~~~~~~\n\n`skfolio` requires:\n\n- python (>= |PythonMinVersion|)\n- numpy (>= |NumpyMinVersion|)\n- scipy (>= |ScipyMinVersion|)\n- pandas (>= |PandasMinVersion|)\n- cvxpy (>= |CvxpyMinVersion|)\n- scikit-learn (>= |SklearnMinVersion|)\n- joblib (>= |JoblibMinVersion|)\n- plotly (>= |PlotlyMinVersion|)\n\nKey Concepts\n~~~~~~~~~~~~\nSince the development of modern portfolio theory by Markowitz (1952), mean-variance\noptimization (MVO) has received considerable attention.\n\nUnfortunately, it faces a number of shortcomings, including high sensitivity to the\ninput parameters (expected returns and covariance), weight concentration, high turnover,\nand poor out-of-sample performance.\n\nIt is well known that naive allocation (1/N, inverse-vol, etc.) tends to outperform\nMVO out-of-sample (DeMiguel, 2007).\n\nNumerous approaches have been developed to alleviate these shortcomings (shrinkage,\nadditional constraints, regularization, uncertainty set, higher moments, Bayesian\napproaches, coherent risk measures, left-tail risk optimization, distributionally robust\noptimization, factor model, risk-parity, hierarchical clustering, ensemble methods,\npre-selection, etc.).\n\nWith this large number of methods, added to the fact that they can be composed together,\nthere is a need for a unified framework with a machine learning approach to perform\nmodel selection, validation, and parameter tuning while reducing the risk of data\nleakage and overfitting.\n\nThis framework is built on scikit-learn's API.\n\nAvailable models\n~~~~~~~~~~~~~~~~\n\n* Portfolio Optimization:\n * Naive:\n * Equal-Weighted\n * Inverse-Volatility\n * Random (Dirichlet)\n * Convex:\n * Mean-Risk\n * Risk Budgeting\n * Maximum Diversification\n * Distributionally Robust CVaR\n * Clustering:\n * Hierarchical Risk Parity\n * Hierarchical Equal Risk Contribution\n * Nested Clusters Optimization\n * Ensemble Methods:\n * Stacking Optimization\n\n* Expected Returns Estimator:\n * Empirical\n * Exponentially Weighted\n * Equilibrium\n * Shrinkage\n\n* Covariance Estimator:\n * Empirical\n * Gerber\n * Denoising\n * Detoning\n * Exponentially Weighted\n * Ledoit-Wolf\n * Oracle Approximating Shrinkage\n * Shrunk Covariance\n * Graphical Lasso CV\n * Implied Covariance\n\n* Distance Estimator:\n * Pearson Distance\n * Kendall Distance\n * Spearman Distance\n * Covariance Distance (based on any of the above covariance estimators)\n * Distance Correlation\n * Variation of Information\n\n* Prior Estimator:\n * Empirical\n * Black & Litterman\n * Factor Model\n\n* Uncertainty Set Estimator:\n * On Expected Returns:\n * Empirical\n * Circular Bootstrap\n * On Covariance:\n * Empirical\n * Circular bootstrap\n\n* Pre-Selection Transformer:\n * Non-Dominated Selection\n * Select K Extremes (Best or Worst)\n * Drop Highly Correlated Assets\n\n* Cross-Validation and Model Selection:\n * Compatible with all `sklearn` methods (KFold, etc.)\n * Walk Forward\n * Combinatorial Purged Cross-Validation\n\n* Hyper-Parameter Tuning:\n * Compatible with all `sklearn` methods (GridSearchCV, RandomizedSearchCV)\n\n* Risk Measures:\n * Variance\n * Semi-Variance\n * Mean Absolute Deviation\n * First Lower Partial Moment\n * CVaR (Conditional Value at Risk)\n * EVaR (Entropic Value at Risk)\n * Worst Realization\n * CDaR (Conditional Drawdown at Risk)\n * Maximum Drawdown\n * Average Drawdown\n * EDaR (Entropic Drawdown at Risk)\n * Ulcer Index\n * Gini Mean Difference\n * Value at Risk\n * Drawdown at Risk\n * Entropic Risk Measure\n * Fourth Central Moment\n * Fourth Lower Partial Moment\n * Skew\n * Kurtosis\n\n* Optimization Features:\n * Minimize Risk\n * Maximize Returns\n * Maximize Utility\n * Maximize Ratio\n * Transaction Costs\n * Management Fees\n * L1 and L2 Regularization\n * Weight Constraints\n * Group Constraints\n * Budget Constraints\n * Tracking Error Constraints\n * Turnover Constraints\n\nQuickstart\n~~~~~~~~~~\nThe code snippets below are designed to introduce the functionality of `skfolio` so you\ncan start using it quickly. It follows the same API as scikit-learn.\n\nImports\n-------\n.. code-block:: python\n\n from sklearn import set_config\n from sklearn.model_selection import (\n GridSearchCV,\n KFold,\n RandomizedSearchCV,\n train_test_split,\n )\n from sklearn.pipeline import Pipeline\n from scipy.stats import loguniform\n\n from skfolio import RatioMeasure, RiskMeasure\n from skfolio.datasets import load_factors_dataset, load_sp500_dataset\n from skfolio.model_selection import (\n CombinatorialPurgedCV,\n WalkForward,\n cross_val_predict,\n )\n from skfolio.moments import (\n DenoiseCovariance,\n DetoneCovariance,\n EWMu,\n GerberCovariance,\n ShrunkMu,\n )\n from skfolio.optimization import (\n MeanRisk,\n NestedClustersOptimization,\n ObjectiveFunction,\n RiskBudgeting,\n )\n from skfolio.pre_selection import SelectKExtremes\n from skfolio.preprocessing import prices_to_returns\n from skfolio.prior import BlackLitterman, EmpiricalPrior, FactorModel\n from skfolio.uncertainty_set import BootstrapMuUncertaintySet\n\nLoad Dataset\n------------\n.. code-block:: python\n\n prices = load_sp500_dataset()\n\nTrain/Test split\n----------------\n.. code-block:: python\n\n X = prices_to_returns(prices)\n X_train, X_test = train_test_split(X, test_size=0.33, shuffle=False)\n\n\nMinimum Variance\n----------------\n.. code-block:: python\n\n model = MeanRisk()\n\nFit on Training Set\n-------------------\n.. code-block:: python\n\n model.fit(X_train)\n\n print(model.weights_)\n\nPredict on Test Set\n-------------------\n.. code-block:: python\n\n portfolio = model.predict(X_test)\n\n print(portfolio.annualized_sharpe_ratio)\n print(portfolio.summary())\n\n\n\nMaximum Sortino Ratio\n---------------------\n.. code-block:: python\n\n model = MeanRisk(\n objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n risk_measure=RiskMeasure.SEMI_VARIANCE,\n )\n\n\nDenoised Covariance & Shrunk Expected Returns\n---------------------------------------------\n.. code-block:: python\n\n model = MeanRisk(\n objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n prior_estimator=EmpiricalPrior(\n mu_estimator=ShrunkMu(), covariance_estimator=DenoiseCovariance()\n ),\n )\n\nUncertainty Set on Expected Returns\n-----------------------------------\n.. code-block:: python\n\n model = MeanRisk(\n objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n mu_uncertainty_set_estimator=BootstrapMuUncertaintySet(),\n )\n\n\nWeight Constraints & Transaction Costs\n--------------------------------------\n.. code-block:: python\n\n model = MeanRisk(\n min_weights={\"AAPL\": 0.10, \"JPM\": 0.05},\n max_weights=0.8,\n transaction_costs={\"AAPL\": 0.0001, \"RRC\": 0.0002},\n groups=[\n [\"Equity\"] * 3 + [\"Fund\"] * 5 + [\"Bond\"] * 12,\n [\"US\"] * 2 + [\"Europe\"] * 8 + [\"Japan\"] * 10,\n ],\n linear_constraints=[\n \"Equity <= 0.5 * Bond\",\n \"US >= 0.1\",\n \"Europe >= 0.5 * Fund\",\n \"Japan <= 1\",\n ],\n )\n model.fit(X_train)\n\n\nRisk Parity on CVaR\n-------------------\n.. code-block:: python\n\n model = RiskBudgeting(risk_measure=RiskMeasure.CVAR)\n\nRisk Parity & Gerber Covariance\n-------------------------------\n.. code-block:: python\n\n model = RiskBudgeting(\n prior_estimator=EmpiricalPrior(covariance_estimator=GerberCovariance())\n )\n\nNested Cluster Optimization with Cross-Validation and Parallelization\n---------------------------------------------------------------------\n.. code-block:: python\n\n model = NestedClustersOptimization(\n inner_estimator=MeanRisk(risk_measure=RiskMeasure.CVAR),\n outer_estimator=RiskBudgeting(risk_measure=RiskMeasure.VARIANCE),\n cv=KFold(),\n n_jobs=-1,\n )\n\nRandomized Search of the L2 Norm\n--------------------------------\n.. code-block:: python\n\n randomized_search = RandomizedSearchCV(\n estimator=MeanRisk(),\n cv=WalkForward(train_size=252, test_size=60),\n param_distributions={\n \"l2_coef\": loguniform(1e-3, 1e-1),\n },\n )\n randomized_search.fit(X_train)\n\n best_model = randomized_search.best_estimator_\n\n print(best_model.weights_)\n\n\nGrid Search on Embedded Parameters\n----------------------------------\n.. code-block:: python\n\n model = MeanRisk(\n objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n risk_measure=RiskMeasure.VARIANCE,\n prior_estimator=EmpiricalPrior(mu_estimator=EWMu(alpha=0.2)),\n )\n\n print(model.get_params(deep=True))\n\n gs = GridSearchCV(\n estimator=model,\n cv=KFold(n_splits=5, shuffle=False),\n n_jobs=-1,\n param_grid={\n \"risk_measure\": [\n RiskMeasure.VARIANCE,\n RiskMeasure.CVAR,\n RiskMeasure.VARIANCE.CDAR,\n ],\n \"prior_estimator__mu_estimator__alpha\": [0.05, 0.1, 0.2, 0.5],\n },\n )\n gs.fit(X)\n\n best_model = gs.best_estimator_\n\n print(best_model.weights_)\n\n\nBlack & Litterman Model\n-----------------------\n.. code-block:: python\n\n views = [\"AAPL - BBY == 0.03 \", \"CVX - KO == 0.04\", \"MSFT == 0.06 \"]\n model = MeanRisk(\n objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n prior_estimator=BlackLitterman(views=views),\n )\n\nFactor Model\n------------\n.. code-block:: python\n\n factor_prices = load_factors_dataset()\n\n X, y = prices_to_returns(prices, factor_prices)\n X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, shuffle=False)\n\n model = MeanRisk(prior_estimator=FactorModel())\n model.fit(X_train, y_train)\n\n print(model.weights_)\n\n portfolio = model.predict(X_test)\n\n print(portfolio.calmar_ratio)\n print(portfolio.summary())\n\n\nFactor Model & Covariance Detoning\n----------------------------------\n.. code-block:: python\n\n model = MeanRisk(\n prior_estimator=FactorModel(\n factor_prior_estimator=EmpiricalPrior(covariance_estimator=DetoneCovariance())\n )\n )\n\nBlack & Litterman Factor Model\n------------------------------\n.. code-block:: python\n\n factor_views = [\"MTUM - QUAL == 0.03 \", \"VLUE == 0.06\"]\n model = MeanRisk(\n objective_function=ObjectiveFunction.MAXIMIZE_RATIO,\n prior_estimator=FactorModel(\n factor_prior_estimator=BlackLitterman(views=factor_views),\n ),\n )\n\nPre-Selection Pipeline\n----------------------\n.. code-block:: python\n\n set_config(transform_output=\"pandas\")\n model = Pipeline(\n [\n (\"pre_selection\", SelectKExtremes(k=10, highest=True)),\n (\"optimization\", MeanRisk()),\n ]\n )\n model.fit(X_train)\n\n portfolio = model.predict(X_test)\n\n\n\n\nK-fold Cross-Validation\n-----------------------\n.. code-block:: python\n\n model = MeanRisk()\n mmp = cross_val_predict(model, X_test, cv=KFold(n_splits=5))\n # mmp is the predicted MultiPeriodPortfolio object composed of 5 Portfolios (1 per testing fold)\n\n mmp.plot_cumulative_returns()\n print(mmp.summary())\n\n\nCombinatorial Purged Cross-Validation\n-------------------------------------\n.. code-block:: python\n\n model = MeanRisk()\n\n cv = CombinatorialPurgedCV(n_folds=10, n_test_folds=2)\n\n print(cv.get_summary(X_train))\n\n population = cross_val_predict(model, X_train, cv=cv)\n\n population.plot_distribution(\n measure_list=[RatioMeasure.SHARPE_RATIO, RatioMeasure.SORTINO_RATIO]\n )\n population.plot_cumulative_returns()\n print(population.summary())\n\n\nRecognition\n~~~~~~~~~~~\n\nWe would like to thank all contributors behind our direct dependencies, such as\nscikit-learn and cvxpy, but also the contributors of the following resources that were a\nsource of inspiration:\n\n * PyPortfolioOpt\n * Riskfolio-Lib\n * scikit-portfolio\n * microprediction\n * statsmodels\n * rsome\n * gautier.marti.ai\n\n\nCitation\n~~~~~~~~\n\nIf you use `skfolio` in a scientific publication, we would appreciate citations:\n\nBibtex entry::\n\n @misc{skfolio,\n author = {Delatte, Hugo and Nicolini, Carlo},\n title = {skfolio},\n year = {2023},\n url = {https://github.com/skfolio/skfolio}\n }\n\n",
"bugtrack_url": null,
"license": "BSD 3-Clause License Copyright (c) 2007-2023 The skfolio developers. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
"summary": "Portfolio optimization built on top of scikit-learn",
"version": "0.5.2",
"project_urls": {
"API Reference": "https://www.skfolio.org/api_reference.html",
"Documentation": "https://www.skfolio.org",
"Repository": "https://github.com/skfolio/skfolio",
"Tutorials": "https://www.skfolio.org"
},
"split_keywords": [
"portfolio",
" optimization",
" optimisation",
" finance",
" asset",
" allocation",
" quantitative",
" quant",
" investment",
" strategy",
" machine-learning",
" scikit-learn",
" data-mining",
" data-science"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "ee66aab631ff89a79f3d6f0709135a984835b2ba9c058afefa8e65072e139c78",
"md5": "6c696b2ce46ccc4de23ffc051e583b4a",
"sha256": "1643b47f35229244160bbf0ae1228ccfe9ebaffac673ff405d183ce6e14ea5dc"
},
"downloads": -1,
"filename": "skfolio-0.5.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "6c696b2ce46ccc4de23ffc051e583b4a",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 730215,
"upload_time": "2024-11-17T21:57:58",
"upload_time_iso_8601": "2024-11-17T21:57:58.911576Z",
"url": "https://files.pythonhosted.org/packages/ee/66/aab631ff89a79f3d6f0709135a984835b2ba9c058afefa8e65072e139c78/skfolio-0.5.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "44b2e2f28be8c6aaa9b641f3b578429563b9981943b93ee249e86ab0db17aafb",
"md5": "fa543c68a7b4021fc111f9517abee754",
"sha256": "c098edcc2d35c075c9827bd8900e751ec5cb1164ad1e5177b8b90dfed1fca66d"
},
"downloads": -1,
"filename": "skfolio-0.5.2.tar.gz",
"has_sig": false,
"md5_digest": "fa543c68a7b4021fc111f9517abee754",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 667296,
"upload_time": "2024-11-17T21:58:00",
"upload_time_iso_8601": "2024-11-17T21:58:00.940270Z",
"url": "https://files.pythonhosted.org/packages/44/b2/e2f28be8c6aaa9b641f3b578429563b9981943b93ee249e86ab0db17aafb/skfolio-0.5.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-17 21:58:00",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "skfolio",
"github_project": "skfolio",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "skfolio"
}