skfolio 0.6.0__py3-none-any.whl → 0.8.0__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.
Files changed (118) hide show
  1. skfolio/__init__.py +7 -7
  2. skfolio/cluster/__init__.py +2 -2
  3. skfolio/cluster/_hierarchical.py +2 -2
  4. skfolio/datasets/__init__.py +3 -3
  5. skfolio/datasets/_base.py +2 -2
  6. skfolio/datasets/data/__init__.py +1 -0
  7. skfolio/distance/__init__.py +4 -4
  8. skfolio/distance/_base.py +2 -2
  9. skfolio/distance/_distance.py +11 -10
  10. skfolio/distribution/__init__.py +56 -0
  11. skfolio/distribution/_base.py +203 -0
  12. skfolio/distribution/copula/__init__.py +35 -0
  13. skfolio/distribution/copula/_base.py +456 -0
  14. skfolio/distribution/copula/_clayton.py +539 -0
  15. skfolio/distribution/copula/_gaussian.py +407 -0
  16. skfolio/distribution/copula/_gumbel.py +560 -0
  17. skfolio/distribution/copula/_independent.py +196 -0
  18. skfolio/distribution/copula/_joe.py +609 -0
  19. skfolio/distribution/copula/_selection.py +111 -0
  20. skfolio/distribution/copula/_student_t.py +486 -0
  21. skfolio/distribution/copula/_utils.py +509 -0
  22. skfolio/distribution/multivariate/__init__.py +11 -0
  23. skfolio/distribution/multivariate/_base.py +241 -0
  24. skfolio/distribution/multivariate/_utils.py +632 -0
  25. skfolio/distribution/multivariate/_vine_copula.py +1254 -0
  26. skfolio/distribution/univariate/__init__.py +19 -0
  27. skfolio/distribution/univariate/_base.py +308 -0
  28. skfolio/distribution/univariate/_gaussian.py +136 -0
  29. skfolio/distribution/univariate/_johnson_su.py +152 -0
  30. skfolio/distribution/univariate/_normal_inverse_gaussian.py +153 -0
  31. skfolio/distribution/univariate/_selection.py +85 -0
  32. skfolio/distribution/univariate/_student_t.py +144 -0
  33. skfolio/exceptions.py +8 -8
  34. skfolio/measures/__init__.py +24 -24
  35. skfolio/measures/_enums.py +7 -7
  36. skfolio/measures/_measures.py +4 -7
  37. skfolio/metrics/__init__.py +2 -0
  38. skfolio/metrics/_scorer.py +4 -4
  39. skfolio/model_selection/__init__.py +4 -4
  40. skfolio/model_selection/_combinatorial.py +15 -12
  41. skfolio/model_selection/_validation.py +2 -2
  42. skfolio/model_selection/_walk_forward.py +3 -3
  43. skfolio/moments/__init__.py +11 -11
  44. skfolio/moments/covariance/__init__.py +6 -6
  45. skfolio/moments/covariance/_base.py +1 -1
  46. skfolio/moments/covariance/_denoise_covariance.py +3 -2
  47. skfolio/moments/covariance/_detone_covariance.py +3 -2
  48. skfolio/moments/covariance/_empirical_covariance.py +3 -2
  49. skfolio/moments/covariance/_ew_covariance.py +3 -2
  50. skfolio/moments/covariance/_gerber_covariance.py +3 -2
  51. skfolio/moments/covariance/_graphical_lasso_cv.py +1 -1
  52. skfolio/moments/covariance/_implied_covariance.py +3 -8
  53. skfolio/moments/covariance/_ledoit_wolf.py +1 -1
  54. skfolio/moments/covariance/_oas.py +1 -1
  55. skfolio/moments/covariance/_shrunk_covariance.py +1 -1
  56. skfolio/moments/expected_returns/__init__.py +2 -2
  57. skfolio/moments/expected_returns/_base.py +1 -1
  58. skfolio/moments/expected_returns/_empirical_mu.py +3 -2
  59. skfolio/moments/expected_returns/_equilibrium_mu.py +3 -2
  60. skfolio/moments/expected_returns/_ew_mu.py +3 -2
  61. skfolio/moments/expected_returns/_shrunk_mu.py +4 -3
  62. skfolio/optimization/__init__.py +12 -10
  63. skfolio/optimization/_base.py +2 -2
  64. skfolio/optimization/cluster/__init__.py +3 -1
  65. skfolio/optimization/cluster/_nco.py +10 -9
  66. skfolio/optimization/cluster/hierarchical/__init__.py +3 -1
  67. skfolio/optimization/cluster/hierarchical/_base.py +1 -2
  68. skfolio/optimization/cluster/hierarchical/_herc.py +4 -3
  69. skfolio/optimization/cluster/hierarchical/_hrp.py +4 -3
  70. skfolio/optimization/convex/__init__.py +5 -3
  71. skfolio/optimization/convex/_base.py +10 -9
  72. skfolio/optimization/convex/_distributionally_robust.py +8 -5
  73. skfolio/optimization/convex/_maximum_diversification.py +8 -6
  74. skfolio/optimization/convex/_mean_risk.py +10 -8
  75. skfolio/optimization/convex/_risk_budgeting.py +6 -4
  76. skfolio/optimization/ensemble/__init__.py +2 -0
  77. skfolio/optimization/ensemble/_base.py +2 -2
  78. skfolio/optimization/ensemble/_stacking.py +3 -3
  79. skfolio/optimization/naive/__init__.py +3 -1
  80. skfolio/optimization/naive/_naive.py +4 -3
  81. skfolio/population/__init__.py +2 -0
  82. skfolio/population/_population.py +34 -7
  83. skfolio/portfolio/__init__.py +1 -1
  84. skfolio/portfolio/_base.py +43 -8
  85. skfolio/portfolio/_multi_period_portfolio.py +3 -2
  86. skfolio/portfolio/_portfolio.py +5 -4
  87. skfolio/pre_selection/__init__.py +3 -1
  88. skfolio/pre_selection/_drop_correlated.py +3 -3
  89. skfolio/pre_selection/_select_complete.py +31 -30
  90. skfolio/pre_selection/_select_k_extremes.py +3 -3
  91. skfolio/pre_selection/_select_non_dominated.py +3 -3
  92. skfolio/pre_selection/_select_non_expiring.py +8 -6
  93. skfolio/preprocessing/__init__.py +2 -0
  94. skfolio/preprocessing/_returns.py +2 -2
  95. skfolio/prior/__init__.py +7 -3
  96. skfolio/prior/_base.py +2 -2
  97. skfolio/prior/_black_litterman.py +7 -4
  98. skfolio/prior/_empirical.py +5 -2
  99. skfolio/prior/_factor_model.py +10 -5
  100. skfolio/prior/_synthetic_data.py +239 -0
  101. skfolio/synthetic_returns/__init__.py +1 -0
  102. skfolio/typing.py +7 -7
  103. skfolio/uncertainty_set/__init__.py +7 -5
  104. skfolio/uncertainty_set/_base.py +5 -4
  105. skfolio/uncertainty_set/_bootstrap.py +1 -1
  106. skfolio/uncertainty_set/_empirical.py +1 -1
  107. skfolio/utils/__init__.py +1 -0
  108. skfolio/utils/bootstrap.py +2 -2
  109. skfolio/utils/equations.py +13 -10
  110. skfolio/utils/sorting.py +2 -2
  111. skfolio/utils/stats.py +15 -15
  112. skfolio/utils/tools.py +86 -22
  113. {skfolio-0.6.0.dist-info → skfolio-0.8.0.dist-info}/METADATA +122 -46
  114. skfolio-0.8.0.dist-info/RECORD +120 -0
  115. {skfolio-0.6.0.dist-info → skfolio-0.8.0.dist-info}/WHEEL +1 -1
  116. skfolio-0.6.0.dist-info/RECORD +0 -95
  117. {skfolio-0.6.0.dist-info → skfolio-0.8.0.dist-info/licenses}/LICENSE +0 -0
  118. {skfolio-0.6.0.dist-info → skfolio-0.8.0.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,8 @@
1
- """Combinatorial module"""
1
+ """Combinatorial module."""
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-portfolio, Copyright (c) 2022, Carlo Nicolini, Licensed under MIT Licence.
8
8
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
@@ -36,7 +36,7 @@ class BaseCombinatorialCV(ABC):
36
36
 
37
37
  @abstractmethod
38
38
  def get_path_ids(self) -> np.ndarray:
39
- """Return the path id of each test sets in each split"""
39
+ """Return the path id of each test sets in each split."""
40
40
  pass
41
41
 
42
42
  __repr__ = sks.BaseCrossValidator.__repr__
@@ -196,18 +196,19 @@ class CombinatorialPurgedCV(BaseCombinatorialCV):
196
196
 
197
197
  @property
198
198
  def n_splits(self) -> int:
199
- """Number of splits"""
199
+ """Number of splits."""
200
200
  return _n_splits(n_folds=self.n_folds, n_test_folds=self.n_test_folds)
201
201
 
202
202
  @property
203
203
  def n_test_paths(self) -> int:
204
204
  """Number of test paths that can be reconstructed from the train/test
205
- combinations"""
205
+ combinations.
206
+ """
206
207
  return _n_test_paths(n_folds=self.n_folds, n_test_folds=self.n_test_folds)
207
208
 
208
209
  @property
209
210
  def test_set_index(self) -> np.ndarray:
210
- """Location of each test set"""
211
+ """Location of each test set."""
211
212
  return np.array(
212
213
  list(itertools.combinations(np.arange(self.n_folds), self.n_test_folds))
213
214
  ).reshape(-1, self.n_test_folds)
@@ -215,7 +216,8 @@ class CombinatorialPurgedCV(BaseCombinatorialCV):
215
216
  @property
216
217
  def binary_train_test_sets(self) -> np.ndarray:
217
218
  """Identify training and test folds for each combinations by assigning `0` to
218
- training folds and `1` to test folds"""
219
+ training folds and `1` to test folds.
220
+ """
219
221
  folds_train_test = np.zeros((self.n_folds, self.n_splits))
220
222
  folds_train_test[
221
223
  self.test_set_index, np.arange(self.n_splits)[:, np.newaxis]
@@ -230,7 +232,7 @@ class CombinatorialPurgedCV(BaseCombinatorialCV):
230
232
  )
231
233
 
232
234
  def get_path_ids(self) -> np.ndarray:
233
- """Return the path id of each test sets in each split"""
235
+ """Return the path id of each test sets in each split."""
234
236
  recombine_paths = self.recombined_paths
235
237
  path_ids = np.zeros((self.n_splits, self.n_test_folds), dtype=int)
236
238
  for i in range(self.n_splits):
@@ -334,7 +336,7 @@ class CombinatorialPurgedCV(BaseCombinatorialCV):
334
336
  )
335
337
 
336
338
  def plot_train_test_folds(self) -> skt.Figure:
337
- """Plot the train/test fold locations"""
339
+ """Plot the train/test fold locations."""
338
340
  values = self.binary_train_test_sets
339
341
  fill_color = np.where(values == 0, "blue", "red")
340
342
  fill_color = fill_color.astype(object)
@@ -367,7 +369,8 @@ class CombinatorialPurgedCV(BaseCombinatorialCV):
367
369
 
368
370
  def plot_train_test_index(self, X) -> skt.Figure:
369
371
  """Plot the training and test indices for each combinations by assigning `0` to
370
- training, `1` to test and `-1` to both purge and embargo indices."""
372
+ training, `1` to test and `-1` to both purge and embargo indices.
373
+ """
371
374
  next(self.split(X))
372
375
  n_samples = X.shape[0]
373
376
  cond = [
@@ -425,12 +428,12 @@ def _n_splits(n_folds: int, n_test_folds: int) -> int:
425
428
  n_splits : int
426
429
  Number of splits
427
430
  """
428
- return int(math.comb(n_folds, n_test_folds))
431
+ return math.comb(n_folds, n_test_folds)
429
432
 
430
433
 
431
434
  def _n_test_paths(n_folds: int, n_test_folds: int) -> int:
432
435
  """Number of test paths that can be reconstructed from the train/test
433
- combinations
436
+ combinations.
434
437
 
435
438
  Parameters
436
439
  ----------
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-portfolio, Copyright (c) 2022, Carlo Nicolini, Licensed under MIT Licence.
8
8
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
@@ -26,7 +26,7 @@ from skfolio.utils.tools import fit_and_predict, safe_split
26
26
 
27
27
  def _routing_enabled():
28
28
  """Return whether metadata routing is enabled.
29
- Returns
29
+ Returns.
30
30
  -------
31
31
  enabled : bool
32
32
  Whether metadata routing is enabled. If the config is not set, it
@@ -1,8 +1,8 @@
1
- """Walk Forward cross-validator"""
1
+ """Walk Forward cross-validator."""
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-portfolio, Copyright (c) 2022, Carlo Nicolini, Licensed under MIT Licence.
8
8
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
@@ -273,7 +273,7 @@ class WalkForward(sks.BaseCrossValidator):
273
273
  )
274
274
 
275
275
  def get_n_splits(self, X=None, y=None, groups=None) -> int:
276
- """Returns the number of splitting iterations in the cross-validator
276
+ """Return the number of splitting iterations in the cross-validator.
277
277
 
278
278
  Parameters
279
279
  ----------
@@ -23,21 +23,21 @@ from skfolio.moments.expected_returns import (
23
23
  )
24
24
 
25
25
  __all__ = [
26
+ "OAS",
27
+ "BaseCovariance",
26
28
  "BaseMu",
27
- "EmpiricalMu",
29
+ "DenoiseCovariance",
30
+ "DetoneCovariance",
31
+ "EWCovariance",
28
32
  "EWMu",
29
- "ShrunkMu",
30
- "EquilibriumMu",
31
- "ShrunkMuMethods",
32
- "BaseCovariance",
33
33
  "EmpiricalCovariance",
34
- "EWCovariance",
34
+ "EmpiricalMu",
35
+ "EquilibriumMu",
35
36
  "GerberCovariance",
36
- "DenoiseCovariance",
37
- "DetoneCovariance",
38
- "LedoitWolf",
39
- "OAS",
40
- "ShrunkCovariance",
41
37
  "GraphicalLassoCV",
42
38
  "ImpliedCovariance",
39
+ "LedoitWolf",
40
+ "ShrunkCovariance",
41
+ "ShrunkMu",
42
+ "ShrunkMuMethods",
43
43
  ]
@@ -15,15 +15,15 @@ from skfolio.moments.covariance._oas import OAS
15
15
  from skfolio.moments.covariance._shrunk_covariance import ShrunkCovariance
16
16
 
17
17
  __all__ = [
18
+ "OAS",
18
19
  "BaseCovariance",
19
- "EmpiricalCovariance",
20
- "EWCovariance",
21
- "GerberCovariance",
22
20
  "DenoiseCovariance",
23
21
  "DetoneCovariance",
24
- "LedoitWolf",
25
- "OAS",
26
- "ShrunkCovariance",
22
+ "EWCovariance",
23
+ "EmpiricalCovariance",
24
+ "GerberCovariance",
27
25
  "GraphicalLassoCV",
28
26
  "ImpliedCovariance",
27
+ "LedoitWolf",
28
+ "ShrunkCovariance",
29
29
  ]
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
@@ -12,6 +12,7 @@ import numpy.typing as npt
12
12
  import scipy.optimize as sco
13
13
  import sklearn.neighbors as skn
14
14
  import sklearn.utils.metadata_routing as skm
15
+ import sklearn.utils.validation as skv
15
16
 
16
17
  from skfolio.moments.covariance._base import BaseCovariance
17
18
  from skfolio.moments.covariance._empirical_covariance import EmpiricalCovariance
@@ -139,7 +140,7 @@ class DenoiseCovariance(BaseCovariance):
139
140
 
140
141
  # we validate and convert to numpy after all models have been fitted to keep
141
142
  # features names information.
142
- X = self._validate_data(X)
143
+ X = skv.validate_data(self, X)
143
144
  n_observations, n_assets = X.shape
144
145
  q = n_observations / n_assets
145
146
  corr, std = cov_to_corr(self.covariance_estimator_.covariance_)
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
@@ -10,6 +10,7 @@
10
10
  import numpy as np
11
11
  import numpy.typing as npt
12
12
  import sklearn.utils.metadata_routing as skm
13
+ import sklearn.utils.validation as skv
13
14
 
14
15
  from skfolio.moments.covariance._base import BaseCovariance
15
16
  from skfolio.moments.covariance._empirical_covariance import EmpiricalCovariance
@@ -141,7 +142,7 @@ class DetoneCovariance(BaseCovariance):
141
142
 
142
143
  # we validate and convert to numpy after all models have been fitted to keep
143
144
  # features names information.
144
- _ = self._validate_data(X)
145
+ _ = skv.validate_data(self, X)
145
146
  corr, std = cov_to_corr(self.covariance_estimator_.covariance_)
146
147
  e_val, e_vec = np.linalg.eigh(corr)
147
148
  indices = e_val.argsort()[::-1]
@@ -2,13 +2,14 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
9
9
 
10
10
  import numpy as np
11
11
  import numpy.typing as npt
12
+ import sklearn.utils.validation as skv
12
13
 
13
14
  from skfolio.moments.covariance._base import BaseCovariance
14
15
 
@@ -92,7 +93,7 @@ class EmpiricalCovariance(BaseCovariance):
92
93
  self : EmpiricalCovariance
93
94
  Fitted estimator.
94
95
  """
95
- X = self._validate_data(X)
96
+ X = skv.validate_data(self, X)
96
97
  if self.window_size is not None:
97
98
  X = X[-int(self.window_size) :]
98
99
  covariance = np.cov(X.T, ddof=self.ddof)
@@ -2,13 +2,14 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
9
9
 
10
10
  import numpy.typing as npt
11
11
  import pandas as pd
12
+ import sklearn.utils.validation as skv
12
13
 
13
14
  from skfolio.moments.covariance._base import BaseCovariance
14
15
 
@@ -94,7 +95,7 @@ class EWCovariance(BaseCovariance):
94
95
  self : EWCovariance
95
96
  Fitted estimator.
96
97
  """
97
- X = self._validate_data(X)
98
+ X = skv.validate_data(self, X)
98
99
  if self.window_size is not None:
99
100
  X = X[-int(self.window_size) :]
100
101
  n_observations = X.shape[0]
@@ -2,13 +2,14 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
9
9
 
10
10
  import numpy as np
11
11
  import numpy.typing as npt
12
+ import sklearn.utils.validation as skv
12
13
 
13
14
  from skfolio.moments.covariance._base import BaseCovariance
14
15
  from skfolio.utils.stats import corr_to_cov
@@ -131,7 +132,7 @@ class GerberCovariance(BaseCovariance):
131
132
  self : GerberCovariance
132
133
  Fitted estimator.
133
134
  """
134
- X = self._validate_data(X)
135
+ X = skv.validate_data(self, X)
135
136
  if self.window_size is not None:
136
137
  X = X[-self.window_size :]
137
138
  if not (1 > self.threshold > 0):
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
@@ -272,7 +272,7 @@ class ImpliedCovariance(BaseCovariance):
272
272
  # and re-order to follow returns ordering.
273
273
  implied_vol = safe_indexing(implied_vol, indices=indices, axis=1)
274
274
 
275
- X = self._validate_data(X)
275
+ X = skv.validate_data(self, X)
276
276
  _, n_assets = X.shape
277
277
  implied_vol = check_implied_vol(implied_vol=implied_vol, X=X)
278
278
  implied_vol /= np.sqrt(self.annualized_factor)
@@ -286,11 +286,7 @@ class ImpliedCovariance(BaseCovariance):
286
286
  n_assets=n_assets,
287
287
  fill_value=np.nan,
288
288
  dim=1,
289
- assets_names=(
290
- self.feature_names_in_
291
- if hasattr(self, "feature_names_in_")
292
- else None
293
- ),
289
+ assets_names=getattr(self, "feature_names_in_", None),
294
290
  name="volatility_risk_premium_adj",
295
291
  )
296
292
 
@@ -417,7 +413,6 @@ def _compute_implied_vol(implied_vol: np.ndarray, window_size: int) -> np.ndarra
417
413
  def check_implied_vol(implied_vol: npt.ArrayLike, X: npt.ArrayLike) -> np.ndarray:
418
414
  """Validate implied volatilities.
419
415
 
420
-
421
416
  Parameters
422
417
  ----------
423
418
  implied_vol : array-like of shape (n_observations, n_assets)
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
@@ -10,9 +10,9 @@ from skfolio.moments.expected_returns._shrunk_mu import ShrunkMu, ShrunkMuMethod
10
10
 
11
11
  __all__ = [
12
12
  "BaseMu",
13
- "EmpiricalMu",
14
13
  "EWMu",
15
- "ShrunkMu",
14
+ "EmpiricalMu",
16
15
  "EquilibriumMu",
16
+ "ShrunkMu",
17
17
  "ShrunkMuMethods",
18
18
  ]
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
@@ -2,13 +2,14 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
9
9
 
10
10
  import numpy as np
11
11
  import numpy.typing as npt
12
+ import sklearn.utils.validation as skv
12
13
 
13
14
  from skfolio.moments.expected_returns._base import BaseMu
14
15
 
@@ -56,7 +57,7 @@ class EmpiricalMu(BaseMu):
56
57
  self : EmpiricalMu
57
58
  Fitted estimator.
58
59
  """
59
- X = self._validate_data(X)
60
+ X = skv.validate_data(self, X)
60
61
  if self.window_size is not None:
61
62
  X = X[-self.window_size :]
62
63
  self.mu_ = np.mean(X, axis=0)
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
@@ -10,6 +10,7 @@
10
10
  import numpy as np
11
11
  import numpy.typing as npt
12
12
  import sklearn.utils.metadata_routing as skm
13
+ import sklearn.utils.validation as skv
13
14
 
14
15
  from skfolio.moments.covariance import BaseCovariance, EmpiricalCovariance
15
16
  from skfolio.moments.expected_returns._base import BaseMu
@@ -114,7 +115,7 @@ class EquilibriumMu(BaseMu):
114
115
 
115
116
  # we validate and convert to numpy after all models have been fitted to keep
116
117
  # features names information.
117
- X = self._validate_data(X)
118
+ X = skv.validate_data(self, X)
118
119
  n_assets = X.shape[1]
119
120
  if self.weights is None:
120
121
  weights = np.ones(n_assets) / n_assets
@@ -2,13 +2,14 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
8
  # Grisel Licensed under BSD 3 clause.
9
9
 
10
10
  import numpy.typing as npt
11
11
  import pandas as pd
12
+ import sklearn.utils.validation as skv
12
13
 
13
14
  from skfolio.moments.expected_returns._base import BaseMu
14
15
 
@@ -62,7 +63,7 @@ class EWMu(BaseMu):
62
63
  self : EWMu
63
64
  Fitted estimator.
64
65
  """
65
- X = self._validate_data(X)
66
+ X = skv.validate_data(self, X)
66
67
  if self.window_size is not None:
67
68
  X = X[-self.window_size :]
68
69
  self.mu_ = pd.DataFrame(X).ewm(alpha=self.alpha).mean().iloc[-1, :].to_numpy()
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Copyright (c) 2023
4
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
- # License: BSD 3 clause
5
+ # SPDX-License-Identifier: BSD-3-Clause
6
6
  # Implementation derived from:
7
7
  # Riskfolio-Lib, Copyright (c) 2020-2023, Dany Cajas, Licensed under BSD 3 clause.
8
8
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
@@ -13,6 +13,7 @@ from enum import auto
13
13
  import numpy as np
14
14
  import numpy.typing as npt
15
15
  import sklearn.utils.metadata_routing as skm
16
+ import sklearn.utils.validation as skv
16
17
 
17
18
  from skfolio.moments.covariance import BaseCovariance, EmpiricalCovariance
18
19
  from skfolio.moments.expected_returns._base import BaseMu
@@ -20,7 +21,7 @@ from skfolio.utils.tools import AutoEnum, check_estimator
20
21
 
21
22
 
22
23
  class ShrunkMuMethods(AutoEnum):
23
- """Shrinkage methods for the ShrunkMu estimator
24
+ """Shrinkage methods for the ShrunkMu estimator.
24
25
 
25
26
  Parameters
26
27
  ----------
@@ -189,7 +190,7 @@ class ShrunkMu(BaseMu):
189
190
 
190
191
  # we validate and convert to numpy after all models have been fitted to keep
191
192
  # features names information.
192
- X = self._validate_data(X)
193
+ X = skv.validate_data(self, X)
193
194
  n_observations, n_assets = X.shape
194
195
 
195
196
  covariance = self.covariance_estimator_.covariance_
@@ -1,3 +1,5 @@
1
+ """Optimization module."""
2
+
1
3
  from skfolio.optimization._base import BaseOptimization
2
4
  from skfolio.optimization.cluster import (
3
5
  BaseHierarchicalOptimization,
@@ -17,20 +19,20 @@ from skfolio.optimization.ensemble import BaseComposition, StackingOptimization
17
19
  from skfolio.optimization.naive import EqualWeighted, InverseVolatility, Random
18
20
 
19
21
  __all__ = [
22
+ "BaseComposition",
23
+ "BaseHierarchicalOptimization",
20
24
  "BaseOptimization",
21
- "InverseVolatility",
22
- "EqualWeighted",
23
- "Random",
24
- "ObjectiveFunction",
25
25
  "ConvexOptimization",
26
- "MeanRisk",
27
- "RiskBudgeting",
28
26
  "DistributionallyRobustCVaR",
29
- "MaximumDiversification",
30
- "BaseHierarchicalOptimization",
31
- "HierarchicalRiskParity",
27
+ "EqualWeighted",
32
28
  "HierarchicalEqualRiskContribution",
29
+ "HierarchicalRiskParity",
30
+ "InverseVolatility",
31
+ "MaximumDiversification",
32
+ "MeanRisk",
33
33
  "NestedClustersOptimization",
34
- "BaseComposition",
34
+ "ObjectiveFunction",
35
+ "Random",
36
+ "RiskBudgeting",
35
37
  "StackingOptimization",
36
38
  ]
@@ -1,7 +1,7 @@
1
1
  """Base Optimization estimator."""
2
2
 
3
3
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
- # License: BSD 3 clause
4
+ # SPDX-License-Identifier: BSD-3-Clause
5
5
 
6
6
  from abc import ABC, abstractmethod
7
7
 
@@ -16,7 +16,7 @@ from skfolio.portfolio import Portfolio
16
16
 
17
17
  # Copyright (c) 2023
18
18
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
19
- # License: BSD 3 clause
19
+ # SPDX-License-Identifier: BSD-3-Clause
20
20
  # Implementation derived from:
21
21
  # scikit-portfolio, Copyright (c) 2022, Carlo Nicolini, Licensed under MIT Licence.
22
22
  # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
@@ -1,3 +1,5 @@
1
+ """Cluster Optimization module."""
2
+
1
3
  from skfolio.optimization.cluster._nco import NestedClustersOptimization
2
4
  from skfolio.optimization.cluster.hierarchical import (
3
5
  BaseHierarchicalOptimization,
@@ -7,7 +9,7 @@ from skfolio.optimization.cluster.hierarchical import (
7
9
 
8
10
  __all__ = [
9
11
  "BaseHierarchicalOptimization",
10
- "HierarchicalRiskParity",
11
12
  "HierarchicalEqualRiskContribution",
13
+ "HierarchicalRiskParity",
12
14
  "NestedClustersOptimization",
13
15
  ]