skfolio 0.0.1__tar.gz → 0.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. {skfolio-0.0.1/src/skfolio.egg-info → skfolio-0.0.3}/PKG-INFO +580 -568
  2. {skfolio-0.0.1 → skfolio-0.0.3}/README.rst +19 -19
  3. {skfolio-0.0.1 → skfolio-0.0.3}/pyproject.toml +42 -13
  4. {skfolio-0.0.1 → skfolio-0.0.3}/setup.cfg +4 -4
  5. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/cluster/_hierarchical.py +1 -0
  6. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/datasets/_base.py +1 -1
  7. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/model_selection/_combinatorial.py +12 -14
  8. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/model_selection/_validation.py +6 -8
  9. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/moments/covariance/_covariance.py +0 -1
  10. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/moments/expected_returns/_expected_returns.py +1 -0
  11. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/_base.py +9 -11
  12. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/cluster/hierarchical/_base.py +0 -2
  13. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/convex/__init__.py +1 -1
  14. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/convex/_base.py +43 -26
  15. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/convex/_distributionally_robust.py +22 -10
  16. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/convex/_maximum_diversification.py +17 -7
  17. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/convex/_mean_risk.py +25 -13
  18. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/convex/_risk_budgeting.py +22 -10
  19. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/ensemble/_stacking.py +4 -6
  20. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/population/_population.py +18 -25
  21. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/portfolio/_portfolio.py +11 -13
  22. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/pre_selection/_pre_selection.py +6 -6
  23. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/preprocessing/_returns.py +1 -1
  24. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/prior/_base.py +1 -0
  25. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/prior/_empirical.py +1 -1
  26. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/prior/_factor_model.py +4 -6
  27. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/uncertainty_set/_base.py +1 -0
  28. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/uncertainty_set/_bootstrap.py +1 -0
  29. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/uncertainty_set/_empirical.py +2 -0
  30. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/utils/stats.py +1 -1
  31. {skfolio-0.0.1 → skfolio-0.0.3/src/skfolio.egg-info}/PKG-INFO +580 -568
  32. skfolio-0.0.3/src/skfolio.egg-info/requires.txt +27 -0
  33. skfolio-0.0.1/src/skfolio.egg-info/requires.txt +0 -14
  34. {skfolio-0.0.1 → skfolio-0.0.3}/LICENSE +0 -0
  35. {skfolio-0.0.1 → skfolio-0.0.3}/MANIFEST.in +0 -0
  36. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/__init__.py +0 -0
  37. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/cluster/__init__.py +0 -0
  38. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/datasets/__init__.py +0 -0
  39. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/datasets/data/__init__.py +0 -0
  40. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/datasets/data/factors_dataset.csv.gz +0 -0
  41. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/datasets/data/sp500_dataset.csv.gz +0 -0
  42. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/datasets/data/sp500_index.csv.gz +0 -0
  43. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/distance/__init__.py +0 -0
  44. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/distance/_base.py +0 -0
  45. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/distance/_distance.py +0 -0
  46. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/exceptions.py +0 -0
  47. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/measures/__init__.py +1 -1
  48. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/measures/_enums.py +0 -0
  49. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/measures/_measures.py +0 -0
  50. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/metrics/__init__.py +0 -0
  51. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/metrics/_scorer.py +0 -0
  52. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/model_selection/__init__.py +0 -0
  53. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/model_selection/_walk_forward.py +0 -0
  54. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/moments/__init__.py +0 -0
  55. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/moments/covariance/__init__.py +0 -0
  56. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/moments/covariance/_base.py +0 -0
  57. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/moments/expected_returns/__init__.py +0 -0
  58. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/moments/expected_returns/_base.py +0 -0
  59. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/__init__.py +0 -0
  60. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/cluster/__init__.py +0 -0
  61. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/cluster/_nco.py +0 -0
  62. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/cluster/hierarchical/__init__.py +0 -0
  63. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/cluster/hierarchical/_herc.py +0 -0
  64. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/cluster/hierarchical/_hrp.py +0 -0
  65. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/ensemble/__init__.py +0 -0
  66. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/ensemble/_base.py +0 -0
  67. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/naive/__init__.py +0 -0
  68. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/optimization/naive/_naive.py +0 -0
  69. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/population/__init__.py +0 -0
  70. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/portfolio/__init__.py +0 -0
  71. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/portfolio/_base.py +0 -0
  72. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/portfolio/_multi_period_portfolio.py +0 -0
  73. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/pre_selection/__init__.py +0 -0
  74. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/preprocessing/__init__.py +0 -0
  75. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/prior/__init__.py +1 -1
  76. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/prior/_black_litterman.py +0 -0
  77. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/typing.py +0 -0
  78. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/uncertainty_set/__init__.py +0 -0
  79. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/utils/__init__.py +0 -0
  80. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/utils/bootstrap.py +0 -0
  81. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/utils/equations.py +0 -0
  82. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/utils/sorting.py +0 -0
  83. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio/utils/tools.py +0 -0
  84. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio.egg-info/SOURCES.txt +0 -0
  85. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio.egg-info/dependency_links.txt +0 -0
  86. {skfolio-0.0.1 → skfolio-0.0.3}/src/skfolio.egg-info/top_level.txt +0 -0
@@ -1,568 +1,580 @@
1
- Metadata-Version: 2.1
2
- Name: skfolio
3
- Version: 0.0.1
4
- Summary: Portfolio optimization built on scikit-learn's API
5
- Author-email: Hugo Delatte <delatte.hugo@gmail.com>
6
- Maintainer-email: Hugo Delatte <delatte.hugo@gmail.com>
7
- License: BSD 3-Clause License
8
-
9
- Copyright (c) 2007-2023 The skfolio developers.
10
- All rights reserved.
11
-
12
- Redistribution and use in source and binary forms, with or without
13
- modification, are permitted provided that the following conditions are met:
14
-
15
- * Redistributions of source code must retain the above copyright notice, this
16
- list of conditions and the following disclaimer.
17
-
18
- * Redistributions in binary form must reproduce the above copyright notice,
19
- this list of conditions and the following disclaimer in the documentation
20
- and/or other materials provided with the distribution.
21
-
22
- * Neither the name of the copyright holder nor the names of its
23
- contributors may be used to endorse or promote products derived from
24
- this software without specific prior written permission.
25
-
26
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
- Project-URL: API Reference, https://www.skfolio.org/api_reference.html
37
- Project-URL: Documentation, https://www.skfolio.org
38
- Project-URL: Tutorials, https://www.skfolio.org
39
- Project-URL: Repository, https://github.com/skfolio/skfolio
40
- Keywords: portfolio,optimization,optimisation,finance,asset,allocation,quantitative,quant,investment,startegy,machine-learning,scikit-learn,data-mining,data-science
41
- Classifier: Intended Audience :: Developers
42
- Classifier: Intended Audience :: Science/Research
43
- Classifier: Intended Audience :: Financial and Insurance Industry
44
- Classifier: License :: OSI Approved :: BSD License
45
- Classifier: Operating System :: Unix
46
- Classifier: Operating System :: Microsoft :: Windows
47
- Classifier: Operating System :: MacOS
48
- Classifier: Programming Language :: Python
49
- Classifier: Programming Language :: Python :: 3
50
- Classifier: Programming Language :: Python :: 3.10
51
- Classifier: Programming Language :: Python :: 3.11
52
- Classifier: Programming Language :: Python :: 3.12
53
- Classifier: Topic :: Scientific/Engineering :: Mathematics
54
- Classifier: Topic :: Office/Business :: Financial :: Investment
55
- Classifier: Topic :: Software Development
56
- Requires-Python: >=3.10
57
- Description-Content-Type: text/x-rst
58
- License-File: LICENSE
59
- Requires-Dist: numpy>=1.26.2
60
- Requires-Dist: scipy>=1.11.4
61
- Requires-Dist: pandas>=2.1.4
62
- Requires-Dist: cvxpy>=1.4.1
63
- Requires-Dist: joblib>=1.3.2
64
- Requires-Dist: scikit-learn>=1.3.2
65
- Requires-Dist: plotly>=5.18.0
66
- Provides-Extra: dev
67
- Requires-Dist: pytest; extra == "dev"
68
- Requires-Dist: pytest-cov; extra == "dev"
69
- Requires-Dist: pydata-sphinx-theme; extra == "dev"
70
- Requires-Dist: Sphinx>=7.2.6; extra == "dev"
71
- Requires-Dist: sphinx-gallery; extra == "dev"
72
-
73
- .. -*- mode: rst -*-
74
-
75
- |Licence|_ |Codecov|_ |Black|_ |PythonVersion|_ |PyPi|_ |CI/CD|_
76
-
77
- .. |Licence| image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
78
- .. _Licence: https://github.com/skfolio/skfolio/blob/main/LICENSE
79
-
80
- .. |Codecov| image:: https://codecov.io/gh/scikit-learn/scikit-learn/branch/main/graph/badge.svg?token=Pk8G9gg3y9
81
- .. _Codecov: https://codecov.io/gh/scikit-learn/scikit-learn
82
-
83
- .. |PythonVersion| image:: https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10-blue
84
- .. _PythonVersion: https://pypi.org/project/scikit-learn/
85
-
86
- .. |PyPi| image:: https://img.shields.io/pypi/v/scikit-learn
87
- .. _PyPi: https://pypi.org/project/scikit-learn
88
-
89
- .. |Black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
90
- .. _Black: https://github.com/psf/black
91
-
92
- .. |CI/CD| image:: https://img.shields.io/github/actions/workflow/status/sktime/sktime/wheels.yml?logo=github
93
- .. _CI/CD: https://github.com/skfolio/skfolio/blob/main/LICENSE
94
-
95
-
96
- .. |PythonMinVersion| replace:: 3.10
97
- .. |NumpyMinVersion| replace:: 1.26
98
- .. |ScipyMinVersion| replace:: 1.11
99
- .. |PandasMinVersion| replace:: 2.1
100
- .. |NumbaMinVersion| replace:: 0.58
101
- .. |CvxpyMinVersion| replace:: 1.4
102
- .. |SklearnMinVersion| replace:: 1.3
103
- .. |JoblibMinVersion| replace:: 1.3
104
- .. |PlotlyMinVersion| replace:: 5.18
105
-
106
-
107
- ===============
108
- |icon| skfolio
109
- ===============
110
- .. |icon| image:: https://raw.githubusercontent.com/skfolio/skfolio/master/docs/_static/logo.ico
111
- :width: 100
112
- :target: https://skfolio.org/
113
-
114
-
115
- **skfolio** is a Python library for portfolio optimization built on top of scikit-learn.
116
- It provides a unified interface and `sklearn` compatible tools to build, tune and
117
- cross-validate portfolio models. It is distributed under the 3-Clause BSD license.
118
-
119
- .. image:: https://raw.githubusercontent.com/skfolio/skfolio/master/docs/_static/expo.jpg
120
-
121
- Important links
122
- ~~~~~~~~~~~~~~~
123
-
124
- - Documentation: https://skfolio.org
125
- - Tutorials: https://skfolio.org
126
- - Repository: https://github.com/skfolio/skfolio
127
-
128
- Installation
129
- ~~~~~~~~~~~~
130
-
131
- The easiest way to install skfolio is using ``pip``::
132
-
133
- pip install -U skfolio
134
-
135
- or ``conda``::
136
-
137
- conda install -c conda-forge skfolio
138
-
139
-
140
- Dependencies
141
- ~~~~~~~~~~~~
142
-
143
- sklearn requires:
144
-
145
- - python (>= |PythonMinVersion|)
146
- - numpy (>= |NumpyMinVersion|)
147
- - scipy (>= |ScipyMinVersion|)
148
- - pandas (>= |PandasMinVersion|)
149
- - cvxpy (>= |CvxpyMinVersion|)
150
- - scikit-learn (>= |SklearnMinVersion|)
151
- - joblib (>= |JoblibMinVersion|)
152
- - plotly (>= |PlotlyMinVersion|)
153
-
154
- Key Concepts
155
- ~~~~~~~~~~~~
156
- Since the development of modern portfolio theory by Markowitz (1952), mean-variance optimization (MVO)
157
- has received considerable attention. Unfortunately it faces a number of shortcomings including high sensitivity to the
158
- input parameters (expected returns and covariance), weight concentration, high turnover and poor out-of-sample
159
- performance.
160
- It is well known that naive allocation (1/N, inverse-vol, ...) tend to outperform MVO out-of-sample (DeMiguel, 2007).
161
-
162
- Numerous approaches have been developed to alleviate these shortcomings (shrinkage, bayesian approaches,
163
- additional constraints, regularization, uncertainty set, higher moments, coherent risk measures,
164
- left-tail risk optimization, distributionally robust optimization, factor model, risk-parity, hierarchical clustering,
165
- ensemble methods...)
166
-
167
- With this large number of methods, added to the fact that they can be composed together there is the need for an
168
- unified framework to perform model selection, validation and parameter tuning while reducing the risk of data leakage
169
- and overfitting. This framework is build on scikit-learn's API.
170
-
171
- Available models
172
- ~~~~~~~~~~~~~~~~
173
- The current release contains:
174
-
175
- * Optimization estimators:
176
- * Naive:
177
- * Equal-Weighted
178
- * Inverse-Volatility
179
- * Random (dirichlet)
180
- * Convex:
181
- * Mean-Risk
182
- * Risk Budgeting
183
- * Maximum Diversification
184
- * Distributionally Robust CVaR
185
- * Clustering:
186
- * Hierarchical Risk Parity
187
- * Hierarchical Equal Risk Contribution
188
- * Nested Clusters Optimization
189
- * Ensemble methods:
190
- * Stacking Optimization
191
-
192
- * Moment estimators:
193
- * Expected Returns:
194
- * Empirical
195
- * Exponentially Weighted
196
- * Equilibrium
197
- * Shrinkage (James-Stein, Bayes-Stein, ...)
198
- * Covariance:
199
- * Empirical
200
- * Gerber
201
- * Denoising
202
- * Denoting
203
- * Exponentially Weighted
204
- * Ledoit-Wolf
205
- * Oracle Approximating Shrinkage
206
- * Shrunk Covariance
207
- * Graphical lasso CV
208
-
209
- * Distance estimator:
210
- * Pearson Distance
211
- * Kendall Distance
212
- * Spearman Distance
213
- * Covariance Distance (based on any of the above covariance estimators)
214
- * Distance Correlation
215
- * Variation of Information
216
-
217
- * Prior estimators:
218
- * Empirical
219
- * Black & Litterman
220
- * Factor Model
221
-
222
- * Uncertainty Set estimators:
223
- * On Expected Returns:
224
- * Empirical
225
- * Circular Bootstrap
226
- * On Covariance:
227
- * Empirical
228
- * Circular bootstrap
229
-
230
- * Pre-Selection transformers:
231
- * Non-Dominated Selection
232
- * Select K Extremes (Best or Worst)
233
- * Drop Highly Correlated Assets
234
-
235
- * Cross-Validation and Model Selection:
236
- * Compatible with all `sklearn` methods (KFold, ...)
237
- * Walk Forward
238
- * Combinatorial Purged Cross-validation
239
-
240
- * Hyper-Parameter Tuning:
241
- * Compatible with all `sklearn` methods (GridSearchCV, RandomizedSearchCV, ...)
242
-
243
- * Risk Measures:
244
- * Variance
245
- * Semi-Variance
246
- * Mean Absolute Deviation
247
- * First Lower Partial Moment
248
- * CVaR (Conditional Value at Risk)
249
- * EVaR (Entropic Value at Risk)
250
- * Worst Realization
251
- * CDaR (Conditional Drawdown at Risk)
252
- * Maximum Drawdown
253
- * Average Drawdown
254
- * EDaR (Entropic Drawdown at Risk)
255
- * Ulcer Index
256
- * Gini Mean Difference
257
- * Value at Risk
258
- * Drawdown at Risk
259
- * Entropic Risk Measure
260
- * Fourth Central Moment
261
- * Fourth Lower Partial Moment
262
- * Skew
263
- * Kurtosis
264
-
265
- Quickstart
266
- ~~~~~~~~~~
267
- The code snippets below are designed to introduce ``skfolio``'s functionality so you can start using it quickly.
268
-
269
- Preparing the data
270
- ------------------
271
- .. code-block:: python
272
-
273
- from sklearn import set_config
274
- from sklearn.model_selection import (
275
- GridSearchCV,
276
- KFold,
277
- RandomizedSearchCV,
278
- train_test_split,
279
- )
280
- from sklearn.pipeline import Pipeline
281
- from scipy.stats import loguniform
282
-
283
- from skfolio import RatioMeasure, RiskMeasure
284
- from skfolio.datasets import load_factors_dataset, load_sp500_dataset
285
- from skfolio.model_selection import (
286
- CombinatorialPurgedCV,
287
- WalkForward,
288
- cross_val_predict,
289
- )
290
- from skfolio.moments import (
291
- DenoiseCovariance,
292
- DenoteCovariance,
293
- EWMu,
294
- GerberCovariance,
295
- ShrunkMu,
296
- )
297
- from skfolio.optimization import (
298
- MeanRisk,
299
- NestedClustersOptimization,
300
- ObjectiveFunction,
301
- RiskBudgeting,
302
- )
303
- from skfolio.pre_selection import SelectKExtremes
304
- from skfolio.preprocessing import prices_to_returns
305
- from skfolio.prior import BlackLitterman, EmpiricalPrior, FactorModel
306
- from skfolio.uncertainty_set import BootstrapMuUncertaintySet
307
-
308
- prices = load_sp500_dataset()
309
-
310
- X = prices_to_returns(prices)
311
- X_train, X_test = train_test_split(X, test_size=0.33, shuffle=False)
312
-
313
-
314
- Minimum Variance
315
- ----------------
316
- .. code-block:: python
317
-
318
- model = MeanRisk()
319
-
320
- Fit on training set
321
- -------------------
322
- .. code-block:: python
323
-
324
- model.fit(X_train)
325
- print(model.weights_)
326
-
327
- Predict on test set
328
- -------------------
329
- .. code-block:: python
330
-
331
- portfolio = model.predict(X_test)
332
- print(portfolio.annualized_sharpe_ratio)
333
- print(portfolio.summary())
334
-
335
-
336
-
337
- Maximum Sortino Ratio
338
- ---------------------
339
- .. code-block:: python
340
-
341
- model = MeanRisk(
342
- objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
343
- risk_measure=RiskMeasure.SEMI_VARIANCE,
344
- )
345
-
346
-
347
- Denoised Covariance & Shrunk Expected Returns
348
- ---------------------------------------------
349
- .. code-block:: python
350
-
351
- model = MeanRisk(
352
- objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
353
- prior_estimator=EmpiricalPrior(
354
- mu_estimator=ShrunkMu(), covariance_estimator=DenoiseCovariance()
355
- ),
356
- )
357
-
358
- Uncertainty Set on Expected Returns
359
- -----------------------------------
360
- .. code-block:: python
361
-
362
- model = MeanRisk(
363
- objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
364
- mu_uncertainty_set_estimator=BootstrapMuUncertaintySet(),
365
- )
366
-
367
-
368
- Weight Constraints & Transaction Costs
369
- --------------------------------------
370
- .. code-block:: python
371
-
372
- model = MeanRisk(
373
- min_weights={"AAPL": 0.10, "JPM": 0.05},
374
- max_weights=0.8,
375
- transaction_costs={"AAPL": 0.0001, "RRC": 0.0002},
376
- groups=[
377
- ["Equity"] * 3 + ["Fund"] * 5 + ["Bond"] * 12,
378
- ["US"] * 2 + ["Europe"] * 8 + ["Japan"] * 10,
379
- ],
380
- linear_constraints=[
381
- "Equity <= 0.5 * Bond",
382
- "US >= 0.1",
383
- "Europe >= 0.5 * Fund",
384
- "Japan <= 1",
385
- ],
386
- )
387
- model.fit(X_train)
388
-
389
-
390
- Risk Parity on CVaR
391
- -------------------
392
- .. code-block:: python
393
-
394
- model = RiskBudgeting(risk_measure=RiskMeasure.CVAR)
395
-
396
- Risk Parity & Gerber Covariance
397
- -------------------------------
398
- .. code-block:: python
399
-
400
- model = RiskBudgeting(
401
- prior_estimator=EmpiricalPrior(covariance_estimator=GerberCovariance())
402
- )
403
-
404
- Nested Cluster Optimization with cross-validation and parallelization
405
- ---------------------------------------------------------------------
406
- .. code-block:: python
407
-
408
- model = NestedClustersOptimization(
409
- inner_estimator=MeanRisk(risk_measure=RiskMeasure.CVAR),
410
- outer_estimator=RiskBudgeting(risk_measure=RiskMeasure.VARIANCE),
411
- cv=KFold(),
412
- n_jobs=-1,
413
- )
414
-
415
- Randomized Search of the L2 Norm
416
- --------------------------------
417
- .. code-block:: python
418
-
419
- randomized_search = RandomizedSearchCV(
420
- estimator=MeanRisk(),
421
- cv=WalkForward(train_size=255, test_size=60),
422
- param_distributions={
423
- "l2_coef": loguniform(1e-3, 1e-1),
424
- },
425
- )
426
- randomized_search.fit(X_train)
427
- best_model = randomized_search.best_estimator_
428
- print(best_model.weights_)
429
-
430
-
431
- Grid Search on embedded parameters
432
- ----------------------------------
433
- .. code-block:: python
434
-
435
- model = MeanRisk(
436
- objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
437
- risk_measure=RiskMeasure.VARIANCE,
438
- prior_estimator=EmpiricalPrior(mu_estimator=EWMu(alpha=0.2)),
439
- )
440
-
441
- print(model.get_params(deep=True))
442
-
443
- gs = GridSearchCV(
444
- estimator=model,
445
- cv=KFold(n_splits=5, shuffle=False),
446
- n_jobs=-1,
447
- param_grid={
448
- "risk_measure": [
449
- RiskMeasure.VARIANCE,
450
- RiskMeasure.CVAR,
451
- RiskMeasure.VARIANCE.CDAR,
452
- ],
453
- "prior_estimator__mu_estimator__alpha": [0.05, 0.1, 0.2, 0.5],
454
- },
455
- )
456
- gs.fit(X)
457
- best_model = gs.best_estimator_
458
- print(best_model.weights_)
459
-
460
-
461
- Black & Litterman Model
462
- -----------------------
463
- .. code-block:: python
464
-
465
- views = ["AAPL - BBY == 0.03 ", "CVX - KO == 0.04", "MSFT == 0.06 "]
466
- model = MeanRisk(
467
- objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
468
- prior_estimator=BlackLitterman(views=views),
469
- )
470
-
471
- Factor Model
472
- ------------
473
- .. code-block:: python
474
-
475
- factor_prices = load_factors_dataset()
476
-
477
- X, y = prices_to_returns(prices, factor_prices)
478
- X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, shuffle=False)
479
-
480
- model = MeanRisk(prior_estimator=FactorModel())
481
- model.fit(X_train, y_train)
482
-
483
- print(model.weights_)
484
- portfolio = model.predict(X_test)
485
- print(portfolio.calmar_ratio)
486
- print(portfolio.summary())
487
-
488
-
489
- Factor Model & Covariance Detoning
490
- ----------------------------------
491
- .. code-block:: python
492
-
493
- model = MeanRisk(
494
- prior_estimator=FactorModel(
495
- factor_prior_estimator=EmpiricalPrior(covariance_estimator=DenoteCovariance())
496
- )
497
- )
498
-
499
- Black & Litterman Factor Model
500
- ------------------------------
501
- .. code-block:: python
502
-
503
- factor_views = ["MTUM - QUAL == 0.03 ", "SIZE - TLT == 0.04", "VLUE == 0.06"]
504
- model = MeanRisk(
505
- objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
506
- prior_estimator=FactorModel(
507
- factor_prior_estimator=BlackLitterman(views=factor_views),
508
- ),
509
- )
510
-
511
- Pre-Selection Pipeline
512
- ----------------------
513
- .. code-block:: python
514
-
515
- set_config(transform_output="pandas")
516
- model = Pipeline(
517
- [
518
- ("pre_selection", SelectKExtremes(k=10, highest=True)),
519
- ("optimization", MeanRisk()),
520
- ]
521
- )
522
- model.fit(X_train)
523
- portfolio = model.predict(X_test)
524
-
525
-
526
-
527
-
528
- K-fold Cross-Validation
529
- -----------------------
530
- .. code-block:: python
531
-
532
- model = MeanRisk()
533
- mmp = cross_val_predict(model, X_test, cv=KFold(n_splits=5))
534
- # mmp is the predicted MultiPeriodPortfolio object composed of 5 Portfolios (1 per testing fold)
535
- mmp.plot_cumulative_returns()
536
- print(mmp.summary()
537
-
538
-
539
- Combinatorial Purged Cross-Validation
540
- -------------------------------------
541
- .. code-block:: python
542
-
543
- model = MeanRisk()
544
- cv = CombinatorialPurgedCV(n_folds=10, n_test_folds=2)
545
- print(cv.get_summary(X_train))
546
- population = cross_val_predict(model, X_train, cv=cv)
547
- population.plot_distribution(
548
- measure_list=[RatioMeasure.SHARPE_RATIO, RatioMeasure.SORTINO_RATIO]
549
- )
550
- population.plot_cumulative_returns()
551
- print(population.summary())
552
-
553
-
554
-
555
- Citation
556
- ~~~~~~~~
557
-
558
- If you use scikit-learn in a scientific publication, we would appreciate citations:
559
-
560
- Bibtex entry::
561
-
562
- @misc{riskfolio,
563
- author = {Hugo Delatte},
564
- title = {skfolio},
565
- year = {2023},
566
- url = {https://github.com/skfolio/skfolio}
567
-
568
-
1
+ Metadata-Version: 2.1
2
+ Name: skfolio
3
+ Version: 0.0.3
4
+ Summary: Portfolio optimization built on top of scikit-learn
5
+ Author-email: Hugo Delatte <delatte.hugo@gmail.com>
6
+ Maintainer-email: Hugo Delatte <delatte.hugo@gmail.com>
7
+ License: BSD 3-Clause License
8
+
9
+ Copyright (c) 2007-2023 The skfolio developers.
10
+ All rights reserved.
11
+
12
+ Redistribution and use in source and binary forms, with or without
13
+ modification, are permitted provided that the following conditions are met:
14
+
15
+ * Redistributions of source code must retain the above copyright notice, this
16
+ list of conditions and the following disclaimer.
17
+
18
+ * Redistributions in binary form must reproduce the above copyright notice,
19
+ this list of conditions and the following disclaimer in the documentation
20
+ and/or other materials provided with the distribution.
21
+
22
+ * Neither the name of the copyright holder nor the names of its
23
+ contributors may be used to endorse or promote products derived from
24
+ this software without specific prior written permission.
25
+
26
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
30
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ Project-URL: API Reference, https://www.skfolio.org/api_reference.html
37
+ Project-URL: Documentation, https://www.skfolio.org
38
+ Project-URL: Tutorials, https://www.skfolio.org
39
+ Project-URL: Repository, https://github.com/skfolio/skfolio
40
+ Keywords: portfolio,optimization,optimisation,finance,asset,allocation,quantitative,quant,investment,startegy,machine-learning,scikit-learn,data-mining,data-science
41
+ Classifier: Intended Audience :: Developers
42
+ Classifier: Intended Audience :: Science/Research
43
+ Classifier: Intended Audience :: Financial and Insurance Industry
44
+ Classifier: License :: OSI Approved :: BSD License
45
+ Classifier: Operating System :: Unix
46
+ Classifier: Operating System :: Microsoft :: Windows
47
+ Classifier: Operating System :: MacOS
48
+ Classifier: Programming Language :: Python
49
+ Classifier: Programming Language :: Python :: 3
50
+ Classifier: Programming Language :: Python :: 3.10
51
+ Classifier: Programming Language :: Python :: 3.11
52
+ Classifier: Programming Language :: Python :: 3.12
53
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
54
+ Classifier: Topic :: Office/Business :: Financial :: Investment
55
+ Classifier: Topic :: Software Development
56
+ Requires-Python: >=3.10
57
+ Description-Content-Type: text/x-rst
58
+ License-File: LICENSE
59
+ Requires-Dist: numpy>=1.23.4
60
+ Requires-Dist: scipy>=1.8.0
61
+ Requires-Dist: pandas>=1.4.1
62
+ Requires-Dist: cvxpy>=1.4.1
63
+ Requires-Dist: scikit-learn>=1.3.2
64
+ Requires-Dist: joblib>=1.3.2
65
+ Requires-Dist: plotly>=5.15.0
66
+ Provides-Extra: tests
67
+ Requires-Dist: pytest; extra == "tests"
68
+ Requires-Dist: pytest-cov; extra == "tests"
69
+ Requires-Dist: black; extra == "tests"
70
+ Requires-Dist: ruff; extra == "tests"
71
+ Provides-Extra: docs
72
+ Requires-Dist: Sphinx; extra == "docs"
73
+ Requires-Dist: sphinx-gallery; extra == "docs"
74
+ Requires-Dist: sphinx-design; extra == "docs"
75
+ Requires-Dist: pydata-sphinx-theme; extra == "docs"
76
+ Requires-Dist: matplotlib; extra == "docs"
77
+ Requires-Dist: kaleido; extra == "docs"
78
+ Requires-Dist: sphinx-copybutton; extra == "docs"
79
+ Requires-Dist: numpydoc; extra == "docs"
80
+ Requires-Dist: sphinx-togglebutton; extra == "docs"
81
+ Requires-Dist: jupyterlite-sphinx; extra == "docs"
82
+ Requires-Dist: sphinx-favicon; extra == "docs"
83
+ Requires-Dist: sphinx-prompt; extra == "docs"
84
+
85
+ .. -*- mode: rst -*-
86
+
87
+ |Licence|_ |Codecov|_ |Black|_ |PythonVersion|_ |PyPi|_ |CI/CD|_
88
+
89
+ .. |Licence| image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
90
+ .. _Licence: https://github.com/skfolio/skfolio/blob/main/LICENSE
91
+
92
+ .. |Codecov| image:: https://codecov.io/gh/skfolio/skfolio/branch/main/graph/badge.svg
93
+ .. _Codecov: https://codecov.io/gh/skfolio/skfolio
94
+
95
+ .. |PythonVersion| image:: https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue
96
+ .. _PythonVersion: https://pypi.org/project/skfolio/
97
+
98
+ .. |PyPi| image:: https://img.shields.io/pypi/v/skfolio
99
+ .. _PyPi: https://pypi.org/project/skfolio
100
+
101
+ .. |Black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
102
+ .. _Black: https://github.com/psf/black
103
+
104
+ .. |CI/CD| image:: https://img.shields.io/github/actions/workflow/status/sktime/sktime/wheels.yml?logo=github
105
+ .. _CI/CD: https://github.com/skfolio/skfolio/raw/main/LICENSE
106
+
107
+
108
+ .. |PythonMinVersion| replace:: 3.10
109
+ .. |NumpyMinVersion| replace:: 1.23.4
110
+ .. |ScipyMinVersion| replace:: 1.8.0
111
+ .. |PandasMinVersion| replace:: 1.4.1
112
+ .. |CvxpyMinVersion| replace:: 1.4.1
113
+ .. |SklearnMinVersion| replace:: 1.3.2
114
+ .. |JoblibMinVersion| replace:: 1.3.2
115
+ .. |PlotlyMinVersion| replace:: 5.15.0
116
+
117
+
118
+ ===============
119
+ |icon| skfolio
120
+ ===============
121
+ .. |icon| image:: https://raw.githubusercontent.com/skfolio/skfolio/master/docs/_static/logo.ico
122
+ :width: 100
123
+ :target: https://skfolio.github.io/skfolio/
124
+
125
+
126
+ **skfolio** is a Python library for portfolio optimization built on top of scikit-learn.
127
+ It provides a unified interface and `sklearn` compatible tools to build, tune and
128
+ cross-validate portfolio models. It is distributed under the 3-Clause BSD license.
129
+
130
+ .. image:: https://raw.githubusercontent.com/skfolio/skfolio/master/docs/_static/expo.jpg
131
+ :target: https://skfolio.github.io/skfolio/auto_examples/index.html
132
+
133
+ Important links
134
+ ~~~~~~~~~~~~~~~
135
+
136
+ - Documentation: https://skfolio.github.io/skfolio/
137
+ - Tutorials: https://skfolio.github.io/skfolio/auto_examples/index.html
138
+ - GitHub Repo: https://github.com/skfolio/skfolio
139
+
140
+ Installation
141
+ ~~~~~~~~~~~~
142
+
143
+ The easiest way to install skfolio is using ``pip``::
144
+
145
+ pip install -U skfolio
146
+
147
+ or ``conda``::
148
+
149
+ conda install -c conda-forge skfolio
150
+
151
+
152
+ Dependencies
153
+ ~~~~~~~~~~~~
154
+
155
+ sklearn requires:
156
+
157
+ - python (>= |PythonMinVersion|)
158
+ - numpy (>= |NumpyMinVersion|)
159
+ - scipy (>= |ScipyMinVersion|)
160
+ - pandas (>= |PandasMinVersion|)
161
+ - cvxpy (>= |CvxpyMinVersion|)
162
+ - scikit-learn (>= |SklearnMinVersion|)
163
+ - joblib (>= |JoblibMinVersion|)
164
+ - plotly (>= |PlotlyMinVersion|)
165
+
166
+ Key Concepts
167
+ ~~~~~~~~~~~~
168
+ Since the development of modern portfolio theory by Markowitz (1952), mean-variance optimization (MVO)
169
+ has received considerable attention. Unfortunately it faces a number of shortcomings including high sensitivity to the
170
+ input parameters (expected returns and covariance), weight concentration, high turnover and poor out-of-sample
171
+ performance.
172
+ It is well known that naive allocation (1/N, inverse-vol, ...) tend to outperform MVO out-of-sample (DeMiguel, 2007).
173
+
174
+ Numerous approaches have been developed to alleviate these shortcomings (shrinkage, bayesian approaches,
175
+ additional constraints, regularization, uncertainty set, higher moments, coherent risk measures,
176
+ left-tail risk optimization, distributionally robust optimization, factor model, risk-parity, hierarchical clustering,
177
+ ensemble methods...)
178
+
179
+ With this large number of methods, added to the fact that they can be composed together there is the need for an
180
+ unified framework to perform model selection, validation and parameter tuning while reducing the risk of data leakage
181
+ and overfitting. This framework is build on scikit-learn's API.
182
+
183
+ Available models
184
+ ~~~~~~~~~~~~~~~~
185
+ The current release contains:
186
+
187
+ * Optimization estimators:
188
+ * Naive:
189
+ * Equal-Weighted
190
+ * Inverse-Volatility
191
+ * Random (dirichlet)
192
+ * Convex:
193
+ * Mean-Risk
194
+ * Risk Budgeting
195
+ * Maximum Diversification
196
+ * Distributionally Robust CVaR
197
+ * Clustering:
198
+ * Hierarchical Risk Parity
199
+ * Hierarchical Equal Risk Contribution
200
+ * Nested Clusters Optimization
201
+ * Ensemble methods:
202
+ * Stacking Optimization
203
+
204
+ * Moment estimators:
205
+ * Expected Returns:
206
+ * Empirical
207
+ * Exponentially Weighted
208
+ * Equilibrium
209
+ * Shrinkage (James-Stein, Bayes-Stein, ...)
210
+ * Covariance:
211
+ * Empirical
212
+ * Gerber
213
+ * Denoising
214
+ * Denoting
215
+ * Exponentially Weighted
216
+ * Ledoit-Wolf
217
+ * Oracle Approximating Shrinkage
218
+ * Shrunk Covariance
219
+ * Graphical lasso CV
220
+
221
+ * Distance estimator:
222
+ * Pearson Distance
223
+ * Kendall Distance
224
+ * Spearman Distance
225
+ * Covariance Distance (based on any of the above covariance estimators)
226
+ * Distance Correlation
227
+ * Variation of Information
228
+
229
+ * Prior estimators:
230
+ * Empirical
231
+ * Black & Litterman
232
+ * Factor Model
233
+
234
+ * Uncertainty Set estimators:
235
+ * On Expected Returns:
236
+ * Empirical
237
+ * Circular Bootstrap
238
+ * On Covariance:
239
+ * Empirical
240
+ * Circular bootstrap
241
+
242
+ * Pre-Selection transformers:
243
+ * Non-Dominated Selection
244
+ * Select K Extremes (Best or Worst)
245
+ * Drop Highly Correlated Assets
246
+
247
+ * Cross-Validation and Model Selection:
248
+ * Compatible with all `sklearn` methods (KFold, ...)
249
+ * Walk Forward
250
+ * Combinatorial Purged Cross-validation
251
+
252
+ * Hyper-Parameter Tuning:
253
+ * Compatible with all `sklearn` methods (GridSearchCV, RandomizedSearchCV, ...)
254
+
255
+ * Risk Measures:
256
+ * Variance
257
+ * Semi-Variance
258
+ * Mean Absolute Deviation
259
+ * First Lower Partial Moment
260
+ * CVaR (Conditional Value at Risk)
261
+ * EVaR (Entropic Value at Risk)
262
+ * Worst Realization
263
+ * CDaR (Conditional Drawdown at Risk)
264
+ * Maximum Drawdown
265
+ * Average Drawdown
266
+ * EDaR (Entropic Drawdown at Risk)
267
+ * Ulcer Index
268
+ * Gini Mean Difference
269
+ * Value at Risk
270
+ * Drawdown at Risk
271
+ * Entropic Risk Measure
272
+ * Fourth Central Moment
273
+ * Fourth Lower Partial Moment
274
+ * Skew
275
+ * Kurtosis
276
+
277
+ Quickstart
278
+ ~~~~~~~~~~
279
+ The code snippets below are designed to introduce ``skfolio``'s functionality so you can start using it quickly.
280
+
281
+ Preparing the data
282
+ ------------------
283
+ .. code-block:: python
284
+
285
+ from sklearn import set_config
286
+ from sklearn.model_selection import (
287
+ GridSearchCV,
288
+ KFold,
289
+ RandomizedSearchCV,
290
+ train_test_split,
291
+ )
292
+ from sklearn.pipeline import Pipeline
293
+ from scipy.stats import loguniform
294
+
295
+ from skfolio import RatioMeasure, RiskMeasure
296
+ from skfolio.datasets import load_factors_dataset, load_sp500_dataset
297
+ from skfolio.model_selection import (
298
+ CombinatorialPurgedCV,
299
+ WalkForward,
300
+ cross_val_predict,
301
+ )
302
+ from skfolio.moments import (
303
+ DenoiseCovariance,
304
+ DenoteCovariance,
305
+ EWMu,
306
+ GerberCovariance,
307
+ ShrunkMu,
308
+ )
309
+ from skfolio.optimization import (
310
+ MeanRisk,
311
+ NestedClustersOptimization,
312
+ ObjectiveFunction,
313
+ RiskBudgeting,
314
+ )
315
+ from skfolio.pre_selection import SelectKExtremes
316
+ from skfolio.preprocessing import prices_to_returns
317
+ from skfolio.prior import BlackLitterman, EmpiricalPrior, FactorModel
318
+ from skfolio.uncertainty_set import BootstrapMuUncertaintySet
319
+
320
+ prices = load_sp500_dataset()
321
+
322
+ X = prices_to_returns(prices)
323
+ X_train, X_test = train_test_split(X, test_size=0.33, shuffle=False)
324
+
325
+
326
+ Minimum Variance
327
+ ----------------
328
+ .. code-block:: python
329
+
330
+ model = MeanRisk()
331
+
332
+ Fit on training set
333
+ -------------------
334
+ .. code-block:: python
335
+
336
+ model.fit(X_train)
337
+ print(model.weights_)
338
+
339
+ Predict on test set
340
+ -------------------
341
+ .. code-block:: python
342
+
343
+ portfolio = model.predict(X_test)
344
+ print(portfolio.annualized_sharpe_ratio)
345
+ print(portfolio.summary())
346
+
347
+
348
+
349
+ Maximum Sortino Ratio
350
+ ---------------------
351
+ .. code-block:: python
352
+
353
+ model = MeanRisk(
354
+ objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
355
+ risk_measure=RiskMeasure.SEMI_VARIANCE,
356
+ )
357
+
358
+
359
+ Denoised Covariance & Shrunk Expected Returns
360
+ ---------------------------------------------
361
+ .. code-block:: python
362
+
363
+ model = MeanRisk(
364
+ objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
365
+ prior_estimator=EmpiricalPrior(
366
+ mu_estimator=ShrunkMu(), covariance_estimator=DenoiseCovariance()
367
+ ),
368
+ )
369
+
370
+ Uncertainty Set on Expected Returns
371
+ -----------------------------------
372
+ .. code-block:: python
373
+
374
+ model = MeanRisk(
375
+ objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
376
+ mu_uncertainty_set_estimator=BootstrapMuUncertaintySet(),
377
+ )
378
+
379
+
380
+ Weight Constraints & Transaction Costs
381
+ --------------------------------------
382
+ .. code-block:: python
383
+
384
+ model = MeanRisk(
385
+ min_weights={"AAPL": 0.10, "JPM": 0.05},
386
+ max_weights=0.8,
387
+ transaction_costs={"AAPL": 0.0001, "RRC": 0.0002},
388
+ groups=[
389
+ ["Equity"] * 3 + ["Fund"] * 5 + ["Bond"] * 12,
390
+ ["US"] * 2 + ["Europe"] * 8 + ["Japan"] * 10,
391
+ ],
392
+ linear_constraints=[
393
+ "Equity <= 0.5 * Bond",
394
+ "US >= 0.1",
395
+ "Europe >= 0.5 * Fund",
396
+ "Japan <= 1",
397
+ ],
398
+ )
399
+ model.fit(X_train)
400
+
401
+
402
+ Risk Parity on CVaR
403
+ -------------------
404
+ .. code-block:: python
405
+
406
+ model = RiskBudgeting(risk_measure=RiskMeasure.CVAR)
407
+
408
+ Risk Parity & Gerber Covariance
409
+ -------------------------------
410
+ .. code-block:: python
411
+
412
+ model = RiskBudgeting(
413
+ prior_estimator=EmpiricalPrior(covariance_estimator=GerberCovariance())
414
+ )
415
+
416
+ Nested Cluster Optimization with cross-validation and parallelization
417
+ ---------------------------------------------------------------------
418
+ .. code-block:: python
419
+
420
+ model = NestedClustersOptimization(
421
+ inner_estimator=MeanRisk(risk_measure=RiskMeasure.CVAR),
422
+ outer_estimator=RiskBudgeting(risk_measure=RiskMeasure.VARIANCE),
423
+ cv=KFold(),
424
+ n_jobs=-1,
425
+ )
426
+
427
+ Randomized Search of the L2 Norm
428
+ --------------------------------
429
+ .. code-block:: python
430
+
431
+ randomized_search = RandomizedSearchCV(
432
+ estimator=MeanRisk(),
433
+ cv=WalkForward(train_size=255, test_size=60),
434
+ param_distributions={
435
+ "l2_coef": loguniform(1e-3, 1e-1),
436
+ },
437
+ )
438
+ randomized_search.fit(X_train)
439
+ best_model = randomized_search.best_estimator_
440
+ print(best_model.weights_)
441
+
442
+
443
+ Grid Search on embedded parameters
444
+ ----------------------------------
445
+ .. code-block:: python
446
+
447
+ model = MeanRisk(
448
+ objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
449
+ risk_measure=RiskMeasure.VARIANCE,
450
+ prior_estimator=EmpiricalPrior(mu_estimator=EWMu(alpha=0.2)),
451
+ )
452
+
453
+ print(model.get_params(deep=True))
454
+
455
+ gs = GridSearchCV(
456
+ estimator=model,
457
+ cv=KFold(n_splits=5, shuffle=False),
458
+ n_jobs=-1,
459
+ param_grid={
460
+ "risk_measure": [
461
+ RiskMeasure.VARIANCE,
462
+ RiskMeasure.CVAR,
463
+ RiskMeasure.VARIANCE.CDAR,
464
+ ],
465
+ "prior_estimator__mu_estimator__alpha": [0.05, 0.1, 0.2, 0.5],
466
+ },
467
+ )
468
+ gs.fit(X)
469
+ best_model = gs.best_estimator_
470
+ print(best_model.weights_)
471
+
472
+
473
+ Black & Litterman Model
474
+ -----------------------
475
+ .. code-block:: python
476
+
477
+ views = ["AAPL - BBY == 0.03 ", "CVX - KO == 0.04", "MSFT == 0.06 "]
478
+ model = MeanRisk(
479
+ objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
480
+ prior_estimator=BlackLitterman(views=views),
481
+ )
482
+
483
+ Factor Model
484
+ ------------
485
+ .. code-block:: python
486
+
487
+ factor_prices = load_factors_dataset()
488
+
489
+ X, y = prices_to_returns(prices, factor_prices)
490
+ X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, shuffle=False)
491
+
492
+ model = MeanRisk(prior_estimator=FactorModel())
493
+ model.fit(X_train, y_train)
494
+
495
+ print(model.weights_)
496
+ portfolio = model.predict(X_test)
497
+ print(portfolio.calmar_ratio)
498
+ print(portfolio.summary())
499
+
500
+
501
+ Factor Model & Covariance Detoning
502
+ ----------------------------------
503
+ .. code-block:: python
504
+
505
+ model = MeanRisk(
506
+ prior_estimator=FactorModel(
507
+ factor_prior_estimator=EmpiricalPrior(covariance_estimator=DenoteCovariance())
508
+ )
509
+ )
510
+
511
+ Black & Litterman Factor Model
512
+ ------------------------------
513
+ .. code-block:: python
514
+
515
+ factor_views = ["MTUM - QUAL == 0.03 ", "SIZE - TLT == 0.04", "VLUE == 0.06"]
516
+ model = MeanRisk(
517
+ objective_function=ObjectiveFunction.MAXIMIZE_RATIO,
518
+ prior_estimator=FactorModel(
519
+ factor_prior_estimator=BlackLitterman(views=factor_views),
520
+ ),
521
+ )
522
+
523
+ Pre-Selection Pipeline
524
+ ----------------------
525
+ .. code-block:: python
526
+
527
+ set_config(transform_output="pandas")
528
+ model = Pipeline(
529
+ [
530
+ ("pre_selection", SelectKExtremes(k=10, highest=True)),
531
+ ("optimization", MeanRisk()),
532
+ ]
533
+ )
534
+ model.fit(X_train)
535
+ portfolio = model.predict(X_test)
536
+
537
+
538
+
539
+
540
+ K-fold Cross-Validation
541
+ -----------------------
542
+ .. code-block:: python
543
+
544
+ model = MeanRisk()
545
+ mmp = cross_val_predict(model, X_test, cv=KFold(n_splits=5))
546
+ # mmp is the predicted MultiPeriodPortfolio object composed of 5 Portfolios (1 per testing fold)
547
+ mmp.plot_cumulative_returns()
548
+ print(mmp.summary()
549
+
550
+
551
+ Combinatorial Purged Cross-Validation
552
+ -------------------------------------
553
+ .. code-block:: python
554
+
555
+ model = MeanRisk()
556
+ cv = CombinatorialPurgedCV(n_folds=10, n_test_folds=2)
557
+ print(cv.get_summary(X_train))
558
+ population = cross_val_predict(model, X_train, cv=cv)
559
+ population.plot_distribution(
560
+ measure_list=[RatioMeasure.SHARPE_RATIO, RatioMeasure.SORTINO_RATIO]
561
+ )
562
+ population.plot_cumulative_returns()
563
+ print(population.summary())
564
+
565
+
566
+
567
+ Citation
568
+ ~~~~~~~~
569
+
570
+ If you use scikit-learn in a scientific publication, we would appreciate citations:
571
+
572
+ Bibtex entry::
573
+
574
+ @misc{riskfolio,
575
+ author = {Hugo Delatte},
576
+ title = {skfolio},
577
+ year = {2023},
578
+ url = {https://github.com/skfolio/skfolio}
579
+
580
+