skfolio 0.5.0__py3-none-any.whl → 0.5.2__py3-none-any.whl

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.
skfolio/datasets/_base.py CHANGED
@@ -11,6 +11,7 @@
11
11
  import gzip
12
12
  import os
13
13
  import shutil
14
+ import sys
14
15
  import urllib.request as ur
15
16
  from importlib import resources
16
17
  from pathlib import Path
@@ -140,7 +141,9 @@ def download_dataset(
140
141
  DataFrame with each row representing one observation and each column
141
142
  representing the asset price of a given observation.
142
143
  """
143
- url = (
144
+ # Use a CORS proxy when triggering requests from the browser
145
+ url_prefix = "https://corsproxy.io/?" if sys.platform == "emscripten" else ""
146
+ url = url_prefix + (
144
147
  f"https://github.com/skfolio/skfolio-datasets/raw/main/"
145
148
  f"datasets/{data_filename}.csv.gz"
146
149
  )
@@ -259,7 +259,7 @@ class ImpliedCovariance(BaseCovariance):
259
259
  if assets_names is not None:
260
260
  vol_assets_names = get_feature_names(implied_vol)
261
261
  if vol_assets_names is not None:
262
- missing_assets = assets_names[~np.in1d(assets_names, vol_assets_names)]
262
+ missing_assets = assets_names[~np.isin(assets_names, vol_assets_names)]
263
263
  if len(missing_assets) > 0:
264
264
  raise ValueError(
265
265
  f"The following assets are missing from "
@@ -622,7 +622,11 @@ class ConvexOptimization(BaseOptimization, ABC):
622
622
  self._cvx_cache = {}
623
623
 
624
624
  def _get_weight_constraints(
625
- self, n_assets: int, w: cp.Variable, factor: skt.Factor
625
+ self,
626
+ n_assets: int,
627
+ w: cp.Variable,
628
+ factor: skt.Factor,
629
+ allow_negative_weights: bool = True,
626
630
  ) -> list[cpc.Constraint]:
627
631
  """Compute weight constraints from input parameters.
628
632
 
@@ -651,6 +655,13 @@ class ConvexOptimization(BaseOptimization, ABC):
651
655
  fill_value=0,
652
656
  name="min_weights",
653
657
  )
658
+
659
+ if not allow_negative_weights and np.any(min_weights < 0):
660
+ raise ValueError(
661
+ f"{self.__class__.__name__} must have non negative `min_weights` "
662
+ f"constraint otherwise the problem becomes non-convex."
663
+ )
664
+
654
665
  constraints.append(
655
666
  w * self._scale_constraints
656
667
  >= min_weights * factor * self._scale_constraints
@@ -432,15 +432,6 @@ class RiskBudgeting(ConvexOptimization):
432
432
  self.min_return = min_return
433
433
  self.risk_budget = risk_budget
434
434
 
435
- def _validation(self) -> None:
436
- if not isinstance(self.risk_measure, RiskMeasure):
437
- raise TypeError("risk_measure must be of type `RiskMeasure`")
438
- if self.min_weights < 0:
439
- raise ValueError(
440
- "Risk Budgeting must have non negative `min_weights` constraint"
441
- " otherwise the problem becomes non-convex."
442
- )
443
-
444
435
  def fit(self, X: npt.ArrayLike, y=None, **fit_params) -> "RiskBudgeting":
445
436
  """Fit the Risk Budgeting Optimization estimator.
446
437
 
@@ -462,8 +453,10 @@ class RiskBudgeting(ConvexOptimization):
462
453
  routed_params = skm.process_routing(self, "fit", **fit_params)
463
454
 
464
455
  self._check_feature_names(X, reset=True)
465
- # Validate
466
- self._validation()
456
+
457
+ if not isinstance(self.risk_measure, RiskMeasure):
458
+ raise TypeError("risk_measure must be of type `RiskMeasure`")
459
+
467
460
  # Used to avoid adding multiple times similar constrains linked to identical
468
461
  # risk models
469
462
  self.prior_estimator_ = check_estimator(
@@ -518,7 +511,7 @@ class RiskBudgeting(ConvexOptimization):
518
511
 
519
512
  # weight constraints
520
513
  constraints += self._get_weight_constraints(
521
- n_assets=n_assets, w=w, factor=factor
514
+ n_assets=n_assets, w=w, factor=factor, allow_negative_weights=False
522
515
  )
523
516
 
524
517
  parameters_values = []
skfolio/utils/stats.py CHANGED
@@ -185,7 +185,7 @@ def is_cholesky_dec(x: np.ndarray) -> bool:
185
185
  try:
186
186
  np.linalg.cholesky(x)
187
187
  return True
188
- except np.linalg.linalg.LinAlgError:
188
+ except np.linalg.LinAlgError:
189
189
  return False
190
190
 
191
191
 
@@ -200,7 +200,7 @@ def is_positive_definite(x: np.ndarray) -> bool:
200
200
  Returns
201
201
  -------
202
202
  value : bool
203
- True if if the matrix is positive definite, False otherwise.
203
+ True if the matrix is positive definite, False otherwise.
204
204
  """
205
205
  return np.all(np.linalg.eigvals(x) > 0)
206
206
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: skfolio
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: Portfolio optimization built on top of scikit-learn
5
5
  Author-email: Hugo Delatte <delatte.hugo@gmail.com>
6
6
  Maintainer-email: Hugo Delatte <delatte.hugo@gmail.com>
@@ -69,7 +69,7 @@ Requires-Dist: sphinx-gallery ; extra == 'docs'
69
69
  Requires-Dist: sphinx-design ; extra == 'docs'
70
70
  Requires-Dist: pydata-sphinx-theme ==0.13.3 ; extra == 'docs'
71
71
  Requires-Dist: matplotlib ; extra == 'docs'
72
- Requires-Dist: kaleido ; extra == 'docs'
72
+ Requires-Dist: kaleido ==0.2.1 ; extra == 'docs'
73
73
  Requires-Dist: sphinx-copybutton ; extra == 'docs'
74
74
  Requires-Dist: numpydoc ; extra == 'docs'
75
75
  Requires-Dist: sphinx-togglebutton ; extra == 'docs'
@@ -77,6 +77,9 @@ Requires-Dist: sphinx-favicon ; extra == 'docs'
77
77
  Requires-Dist: sphinx-prompt ; extra == 'docs'
78
78
  Requires-Dist: sphinxext.opengraph ; extra == 'docs'
79
79
  Requires-Dist: sphinx-sitemap ; extra == 'docs'
80
+ Requires-Dist: jupyterlite-sphinx ; extra == 'docs'
81
+ Requires-Dist: jupyterlite-pyodide-kernel ; extra == 'docs'
82
+ Requires-Dist: nbformat ; extra == 'docs'
80
83
  Provides-Extra: tests
81
84
  Requires-Dist: pytest ; extra == 'tests'
82
85
  Requires-Dist: pytest-cov ; extra == 'tests'
@@ -84,7 +87,7 @@ Requires-Dist: ruff ; extra == 'tests'
84
87
 
85
88
  .. -*- mode: rst -*-
86
89
 
87
- |Licence| |Codecov| |Black| |PythonVersion| |PyPi| |CI/CD| |Downloads| |Ruff| |Contribution| |Website|
90
+ |Licence| |Codecov| |Black| |PythonVersion| |PyPi| |CI/CD| |Downloads| |Ruff| |Contribution| |Website| |JupyterLite|
88
91
 
89
92
  .. |Licence| image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
90
93
  :target: https://github.com/skfolio/skfolio/blob/main/LICENSE
@@ -116,14 +119,17 @@ Requires-Dist: ruff ; extra == 'tests'
116
119
  .. |Website| image:: https://img.shields.io/website.svg?down_color=red&down_message=down&up_color=53cc0d&up_message=up&url=https://skfolio.org
117
120
  :target: https://skfolio.org
118
121
 
122
+ .. |JupyterLite| image:: https://jupyterlite.rtfd.io/en/latest/_static/badge.svg
123
+ :target: https://skfolio.org/lite
124
+
119
125
  .. |PythonMinVersion| replace:: 3.10
120
126
  .. |NumpyMinVersion| replace:: 1.23.4
121
127
  .. |ScipyMinVersion| replace:: 1.8.0
122
128
  .. |PandasMinVersion| replace:: 1.4.1
123
129
  .. |CvxpyMinVersion| replace:: 1.4.1
124
- .. |SklearnMinVersion| replace:: 1.3.2
130
+ .. |SklearnMinVersion| replace:: 1.5.0
125
131
  .. |JoblibMinVersion| replace:: 1.3.2
126
- .. |PlotlyMinVersion| replace:: 5.15.0
132
+ .. |PlotlyMinVersion| replace:: 5.22.0
127
133
 
128
134
 
129
135
  ===============
@@ -4,7 +4,7 @@ skfolio/typing.py,sha256=yEZiCZ6UIyfYUqtfj9Kf2KA9mrjUbmxyzpH9uqVboJs,1378
4
4
  skfolio/cluster/__init__.py,sha256=4g-PFB_ld9BhiQ1ZPvvAorpFbRwd_p_DkeRlulDv2Hk,251
5
5
  skfolio/cluster/_hierarchical.py,sha256=16INBe5HB7ALODO3RNI8ZjOYALtMZa3U_7EP1aEIxp8,12819
6
6
  skfolio/datasets/__init__.py,sha256=TKzb3wucwuaBI7V8GSiEIun-oaV0W0Mhl_XJgMjlajU,481
7
- skfolio/datasets/_base.py,sha256=Al8YzVsiuas3NMMKSjMhE0C0XFkYE-qjONumgoXwFbo,15902
7
+ skfolio/datasets/_base.py,sha256=ECeHHlNOb2U5hEE3kaK8yQtegcVYiuGTjMLJ3Dop0Ks,16073
8
8
  skfolio/datasets/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  skfolio/datasets/data/factors_dataset.csv.gz,sha256=brCJlT25DJo40yg1gnUXAakNtvWZZYR_1ksFeN5JcWE,36146
10
10
  skfolio/datasets/data/sp500_dataset.csv.gz,sha256=7iHKwovvsdCnOanOsiGE-ZU5RyaqDP3pohlB0awErA0,426065
@@ -30,7 +30,7 @@ skfolio/moments/covariance/_empirical_covariance.py,sha256=_7T1x4p-vdATQvQzQjQBM
30
30
  skfolio/moments/covariance/_ew_covariance.py,sha256=jzLE4zSEfLCToNBTIG5CMy1n9EYWo1IHJPifcyLVe1g,3673
31
31
  skfolio/moments/covariance/_gerber_covariance.py,sha256=3wSwZtji2cEr2rzZ6pi2knmuOSzTFpyb_4XJl_S3Yj0,5856
32
32
  skfolio/moments/covariance/_graphical_lasso_cv.py,sha256=_6WQ1sjYJRG8XDq8zb5YIPtDhpb8CmLhLBlfewBvqjM,6539
33
- skfolio/moments/covariance/_implied_covariance.py,sha256=6DiPWo7WVRA8EFvjYxBLBIrYaeRJWpr8yH5I64Sbbd0,17732
33
+ skfolio/moments/covariance/_implied_covariance.py,sha256=L8odXiyNTfrnyroZUZSr8KkHv9_c3OCpdoqrtLqkonQ,17732
34
34
  skfolio/moments/covariance/_ledoit_wolf.py,sha256=iV92TpAopOAgQwa4zk7NF1rYdXkgm3uXn5ZZpbcMss0,4875
35
35
  skfolio/moments/covariance/_oas.py,sha256=ru8BNz7vQU75ARCuUbtJstmR2fy2fiD9OXLDlztUm5g,3684
36
36
  skfolio/moments/covariance/_shrunk_covariance.py,sha256=OOUahkiSdU3vFOb8i0iHtn8WU0AHl7o9pf8pFkG6Lv4,3095
@@ -49,11 +49,11 @@ skfolio/optimization/cluster/hierarchical/_base.py,sha256=l8rJHCH_79FOPdDL2I0dmA
49
49
  skfolio/optimization/cluster/hierarchical/_herc.py,sha256=LPtUrvyW9G60OZhMWlZH_GHZHdX8mJHksrYGB-WPRVg,20358
50
50
  skfolio/optimization/cluster/hierarchical/_hrp.py,sha256=dn6EKiTJ1wkoFhPdst6vlXnSQvXSYsMtB2zaGNVPpyA,18115
51
51
  skfolio/optimization/convex/__init__.py,sha256=F6BPFikTo0B-7JCKazqLGEwM3RkgTNbFm5GAGkaq9Uo,570
52
- skfolio/optimization/convex/_base.py,sha256=2at6Ll4qHkN_1wvYjl-yXWTbiRJj8fhNS-bfAT88YSw,76055
52
+ skfolio/optimization/convex/_base.py,sha256=P1rSw1oJAZR_BuOxJeXJrYHlkFD0AwCOaBl3mj54E8U,76413
53
53
  skfolio/optimization/convex/_distributionally_robust.py,sha256=tw_UNSDfAXP02khE10hpmcdlz3DQXQD7ttDqFDSHV1E,17811
54
54
  skfolio/optimization/convex/_maximum_diversification.py,sha256=IVKVbK7bh4KPkhpNWLLerl-qx9Qcmf2cIIRotP8r8nI,19500
55
55
  skfolio/optimization/convex/_mean_risk.py,sha256=H4Ik6vvIETdAZnNCA4Jhk_OTirHJg26KQZ5iLsXgaHo,44176
56
- skfolio/optimization/convex/_risk_budgeting.py,sha256=ntPK57Ws-_U4QAiZjXFvKUYUELv9EBoJIWqofxx-0rY,23779
56
+ skfolio/optimization/convex/_risk_budgeting.py,sha256=VXm6vUeB-BDEn6KhWxg1-9UmjqpFR1E04SM4NLcNuBY,23510
57
57
  skfolio/optimization/ensemble/__init__.py,sha256=8TXxcxH2_gG3C1xtgQj9OHHr0Le8lhdejtlURL6T3ZY,158
58
58
  skfolio/optimization/ensemble/_base.py,sha256=GaNDQu6ivosYuwMrb-b0PhToCsNrmhSYyXkxeM8W4rU,3399
59
59
  skfolio/optimization/ensemble/_stacking.py,sha256=ZoICUnc_MwoXDQAR2kewCg-KIezSOIUdDV1fuf7vMyA,14168
@@ -86,10 +86,10 @@ skfolio/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
86
  skfolio/utils/bootstrap.py,sha256=3zY2kO_GQURKEcQMCasJOSByde9Mt2IAi3KJH0_a4mk,3550
87
87
  skfolio/utils/equations.py,sha256=MQ1w3VSM2n_j9bTIKAQA716aWKYyUqtw5yM2bU-9t-M,13745
88
88
  skfolio/utils/sorting.py,sha256=lSjMvH2L-sSj-06B3MlwBrH1rtjCeGEe4hG894W7TE0,3504
89
- skfolio/utils/stats.py,sha256=bzKlF2U7BN2WonwtuwG_cL_16Z3cTAxCAw5pZgbib54,17005
89
+ skfolio/utils/stats.py,sha256=mWMpJ_XBy400kx7GlwBvR4Fwo8ValOZ9J3VDLODDaHQ,16995
90
90
  skfolio/utils/tools.py,sha256=4KrmBR9jOLiI6j0hb27gsPC--OHXo4Sp1xl-6i-k9Tg,20925
91
- skfolio-0.5.0.dist-info/LICENSE,sha256=F6Gi-ZJX5BlVzYK8R9NcvAkAsKa7KO29xB1OScbrH6Q,1526
92
- skfolio-0.5.0.dist-info/METADATA,sha256=yHEHbXE0miG8QngS1WprxyB9QrKnml44TPGScw8SqqM,19611
93
- skfolio-0.5.0.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
94
- skfolio-0.5.0.dist-info/top_level.txt,sha256=NXEaoS9Ms7t32gxkb867nV0OKlU0KmssL7IJBVo0fJs,8
95
- skfolio-0.5.0.dist-info/RECORD,,
91
+ skfolio-0.5.2.dist-info/LICENSE,sha256=F6Gi-ZJX5BlVzYK8R9NcvAkAsKa7KO29xB1OScbrH6Q,1526
92
+ skfolio-0.5.2.dist-info/METADATA,sha256=YCnMzyRfmhzQpJ6P6VySw-DJlYuHBdw4bkcfIrR_Gc8,19906
93
+ skfolio-0.5.2.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
94
+ skfolio-0.5.2.dist-info/top_level.txt,sha256=NXEaoS9Ms7t32gxkb867nV0OKlU0KmssL7IJBVo0fJs,8
95
+ skfolio-0.5.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.5.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5