skfolio 0.0.1__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 (79) hide show
  1. skfolio/__init__.py +29 -0
  2. skfolio/cluster/__init__.py +8 -0
  3. skfolio/cluster/_hierarchical.py +387 -0
  4. skfolio/datasets/__init__.py +20 -0
  5. skfolio/datasets/_base.py +389 -0
  6. skfolio/datasets/data/__init__.py +0 -0
  7. skfolio/datasets/data/factors_dataset.csv.gz +0 -0
  8. skfolio/datasets/data/sp500_dataset.csv.gz +0 -0
  9. skfolio/datasets/data/sp500_index.csv.gz +0 -0
  10. skfolio/distance/__init__.py +26 -0
  11. skfolio/distance/_base.py +55 -0
  12. skfolio/distance/_distance.py +574 -0
  13. skfolio/exceptions.py +30 -0
  14. skfolio/measures/__init__.py +76 -0
  15. skfolio/measures/_enums.py +355 -0
  16. skfolio/measures/_measures.py +607 -0
  17. skfolio/metrics/__init__.py +3 -0
  18. skfolio/metrics/_scorer.py +121 -0
  19. skfolio/model_selection/__init__.py +18 -0
  20. skfolio/model_selection/_combinatorial.py +407 -0
  21. skfolio/model_selection/_validation.py +194 -0
  22. skfolio/model_selection/_walk_forward.py +221 -0
  23. skfolio/moments/__init__.py +41 -0
  24. skfolio/moments/covariance/__init__.py +29 -0
  25. skfolio/moments/covariance/_base.py +101 -0
  26. skfolio/moments/covariance/_covariance.py +1108 -0
  27. skfolio/moments/expected_returns/__init__.py +21 -0
  28. skfolio/moments/expected_returns/_base.py +31 -0
  29. skfolio/moments/expected_returns/_expected_returns.py +415 -0
  30. skfolio/optimization/__init__.py +36 -0
  31. skfolio/optimization/_base.py +147 -0
  32. skfolio/optimization/cluster/__init__.py +13 -0
  33. skfolio/optimization/cluster/_nco.py +348 -0
  34. skfolio/optimization/cluster/hierarchical/__init__.py +13 -0
  35. skfolio/optimization/cluster/hierarchical/_base.py +440 -0
  36. skfolio/optimization/cluster/hierarchical/_herc.py +406 -0
  37. skfolio/optimization/cluster/hierarchical/_hrp.py +368 -0
  38. skfolio/optimization/convex/__init__.py +16 -0
  39. skfolio/optimization/convex/_base.py +1944 -0
  40. skfolio/optimization/convex/_distributionally_robust.py +392 -0
  41. skfolio/optimization/convex/_maximum_diversification.py +417 -0
  42. skfolio/optimization/convex/_mean_risk.py +974 -0
  43. skfolio/optimization/convex/_risk_budgeting.py +560 -0
  44. skfolio/optimization/ensemble/__init__.py +6 -0
  45. skfolio/optimization/ensemble/_base.py +87 -0
  46. skfolio/optimization/ensemble/_stacking.py +326 -0
  47. skfolio/optimization/naive/__init__.py +3 -0
  48. skfolio/optimization/naive/_naive.py +173 -0
  49. skfolio/population/__init__.py +3 -0
  50. skfolio/population/_population.py +883 -0
  51. skfolio/portfolio/__init__.py +13 -0
  52. skfolio/portfolio/_base.py +1096 -0
  53. skfolio/portfolio/_multi_period_portfolio.py +610 -0
  54. skfolio/portfolio/_portfolio.py +842 -0
  55. skfolio/pre_selection/__init__.py +7 -0
  56. skfolio/pre_selection/_pre_selection.py +342 -0
  57. skfolio/preprocessing/__init__.py +3 -0
  58. skfolio/preprocessing/_returns.py +114 -0
  59. skfolio/prior/__init__.py +18 -0
  60. skfolio/prior/_base.py +63 -0
  61. skfolio/prior/_black_litterman.py +238 -0
  62. skfolio/prior/_empirical.py +163 -0
  63. skfolio/prior/_factor_model.py +268 -0
  64. skfolio/typing.py +50 -0
  65. skfolio/uncertainty_set/__init__.py +23 -0
  66. skfolio/uncertainty_set/_base.py +108 -0
  67. skfolio/uncertainty_set/_bootstrap.py +281 -0
  68. skfolio/uncertainty_set/_empirical.py +237 -0
  69. skfolio/utils/__init__.py +0 -0
  70. skfolio/utils/bootstrap.py +115 -0
  71. skfolio/utils/equations.py +350 -0
  72. skfolio/utils/sorting.py +117 -0
  73. skfolio/utils/stats.py +466 -0
  74. skfolio/utils/tools.py +567 -0
  75. skfolio-0.0.1.dist-info/LICENSE +29 -0
  76. skfolio-0.0.1.dist-info/METADATA +568 -0
  77. skfolio-0.0.1.dist-info/RECORD +79 -0
  78. skfolio-0.0.1.dist-info/WHEEL +5 -0
  79. skfolio-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,355 @@
1
+ """Module that includes all Measures enums used across `skfolio`."""
2
+
3
+ # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
+ # License: BSD 3 clause
5
+
6
+ from abc import abstractmethod
7
+ from enum import auto
8
+
9
+ from skfolio.utils.tools import AutoEnum
10
+
11
+
12
+ class BaseMeasure(AutoEnum):
13
+ """Base Enum of measures"""
14
+
15
+ def __repr__(self) -> str:
16
+ """Enum representation for improved reading"""
17
+ words = [
18
+ (
19
+ word.capitalize()
20
+ if len(word) > 3
21
+ else word.upper() if len(word) != 2 else word.lower()
22
+ )
23
+ for word in self.value.split("_")
24
+ ]
25
+ if len(words[0]) in [3, 4] and words[0][-2:].lower() == "ar":
26
+ s = list(words[0].upper())
27
+ s[-2] = str(s[-2].lower())
28
+ words[0] = "".join(s)
29
+ string = " ".join(words).replace("Semi ", "Semi-")
30
+ return string
31
+
32
+ def __str__(self) -> str:
33
+ return self.__repr__()
34
+
35
+ @property
36
+ @abstractmethod
37
+ def is_perf(self):
38
+ pass
39
+
40
+ @property
41
+ @abstractmethod
42
+ def is_risk(self):
43
+ pass
44
+
45
+ @property
46
+ @abstractmethod
47
+ def is_ratio(self):
48
+ pass
49
+
50
+ @property
51
+ def is_annualized(self) -> bool:
52
+ return self.name[:10] == "ANNUALIZED"
53
+
54
+ @property
55
+ def annualized_measure(self):
56
+ if self.is_annualized:
57
+ raise ValueError(f"{self.name} is already an annualized measure")
58
+ try:
59
+ return getattr(self.__class__, f"ANNUALIZED_{self.name}")
60
+ except AttributeError:
61
+ raise AttributeError(
62
+ f"{self.name} doesn't have a annualized version"
63
+ ) from None
64
+
65
+ @property
66
+ def non_annualized_measure(self):
67
+ if not self.is_annualized:
68
+ raise ValueError(f"{self.name} is already a non-annualized measure")
69
+ return getattr(self.__class__, self.name[11:])
70
+
71
+
72
+ class PerfMeasure(BaseMeasure):
73
+ """Enumeration of performance measures
74
+
75
+ Attributes
76
+ ----------
77
+ MEAN : str
78
+ Mean
79
+
80
+ ANNUALIZED_MEAN : str
81
+ Annualized Mean
82
+ """
83
+
84
+ MEAN = auto()
85
+
86
+ # Annualized measures
87
+ ANNUALIZED_MEAN = auto()
88
+
89
+ @property
90
+ def is_perf(self) -> bool:
91
+ return True
92
+
93
+ @property
94
+ def is_risk(self) -> bool:
95
+ return False
96
+
97
+ @property
98
+ def is_ratio(self) -> bool:
99
+ return False
100
+
101
+
102
+ class RiskMeasure(BaseMeasure):
103
+ """Enumeration of risk measures
104
+
105
+ Attributes
106
+ ----------
107
+ VARIANCE : str
108
+ Variance.
109
+
110
+ ANNUALIZED_VARIANCE : str
111
+ Annualized Variance.
112
+
113
+ SEMI_VARIANCE : str
114
+ Semi-variance (Second Lower Partial Moment or Downside Variance).
115
+
116
+ ANNUALIZED_SEMI_VARIANCE : str
117
+ Annualized Semi-variance.
118
+
119
+ STANDARD_DEVIATION : str
120
+ Standard-deviation
121
+
122
+ ANNUALIZED_STANDARD_DEVIATION : str
123
+ Annualized Standard-deviation.
124
+
125
+ SEMI_DEVIATION : str
126
+ Semi-deviation.
127
+
128
+ ANNUALIZED_SEMI_DEVIATION : str
129
+ Annualized Semi-deviation.
130
+
131
+ MEAN_ABSOLUTE_DEVIATION : str
132
+ Mean Absolute Deviation.
133
+
134
+ CVAR : str
135
+ Conditional Value at Risk or Expected Shortfall.
136
+
137
+ EVAR : str
138
+ Entropic Value at Risk.
139
+
140
+ WORST_REALIZATION : str
141
+ Worst Realization (Worst Return).
142
+
143
+ CDAR : str
144
+ Conditional Drawdown at Risk.
145
+
146
+ MAX_DRAWDOWN : str
147
+ Maximum Drawdown.
148
+
149
+ AVERAGE_DRAWDOWN : str
150
+ Average Drawdown.
151
+
152
+ EDAR : str
153
+ Entropic Drawdown at Risk.
154
+
155
+ FIRST_LOWER_PARTIAL_MOMENT : str
156
+ First Lower Partial Moment.
157
+
158
+ ULCER_INDEX : str
159
+ Ulcer Index.
160
+
161
+ GINI_MEAN_DIFFERENCE : str
162
+ Gini Mean Difference.
163
+ """
164
+
165
+ VARIANCE = auto()
166
+ ANNUALIZED_VARIANCE = auto()
167
+ SEMI_VARIANCE = auto()
168
+ ANNUALIZED_SEMI_VARIANCE = auto()
169
+ STANDARD_DEVIATION = auto()
170
+ ANNUALIZED_STANDARD_DEVIATION = auto()
171
+ SEMI_DEVIATION = auto()
172
+ ANNUALIZED_SEMI_DEVIATION = auto()
173
+ MEAN_ABSOLUTE_DEVIATION = auto()
174
+ CVAR = auto()
175
+ EVAR = auto()
176
+ WORST_REALIZATION = auto()
177
+ CDAR = auto()
178
+ MAX_DRAWDOWN = auto()
179
+ AVERAGE_DRAWDOWN = auto()
180
+ EDAR = auto()
181
+ FIRST_LOWER_PARTIAL_MOMENT = auto()
182
+ ULCER_INDEX = auto()
183
+ GINI_MEAN_DIFFERENCE = auto()
184
+
185
+ @property
186
+ def is_perf(self) -> bool:
187
+ return False
188
+
189
+ @property
190
+ def is_risk(self) -> bool:
191
+ return True
192
+
193
+ @property
194
+ def is_ratio(self) -> bool:
195
+ return False
196
+
197
+
198
+ class ExtraRiskMeasure(BaseMeasure):
199
+ """Enumeration of other risk measures not used in convex optimization
200
+
201
+ Attributes
202
+ ----------
203
+ VALUE_AT_RISK : str
204
+ Value at Risk (VaR).
205
+
206
+ DRAWDOWN_AT_RISK : str
207
+ Drawdown at Risk.
208
+
209
+ ENTROPIC_RISK_MEASURE : str
210
+ Entropic Risk Measure.
211
+
212
+ FOURTH_CENTRAL_MOMENT : str
213
+ Fourth Central Moment.
214
+
215
+ FOURTH_LOWER_PARTIAL_MOMENT : str
216
+ Fourth Lower Central Moment.
217
+
218
+ SKEW : str
219
+ Skew.
220
+
221
+ KURTOSIS : str
222
+ Kurtosis.
223
+ """
224
+
225
+ VALUE_AT_RISK = auto()
226
+ DRAWDOWN_AT_RISK = auto()
227
+ ENTROPIC_RISK_MEASURE = auto()
228
+ FOURTH_CENTRAL_MOMENT = auto()
229
+ FOURTH_LOWER_PARTIAL_MOMENT = auto()
230
+ SKEW = auto()
231
+ KURTOSIS = auto()
232
+
233
+ @property
234
+ def is_perf(self) -> bool:
235
+ return False
236
+
237
+ @property
238
+ def is_risk(self) -> bool:
239
+ return True
240
+
241
+ @property
242
+ def is_ratio(self) -> bool:
243
+ return False
244
+
245
+
246
+ class RatioMeasure(BaseMeasure):
247
+ """Enumeration of ratio measures
248
+
249
+ Attributes
250
+ ----------
251
+ SHARPE_RATIO : str
252
+ Ratio of the excess Mean divided by the Standard-deviation.
253
+
254
+ ANNUALIZED_SHARPE_RATIO : str
255
+ Annualized Sharpe ratio.
256
+
257
+ SORTINO_RATIO : str
258
+ Ratio of the excess Mean divided by the Semi standard-deviation.
259
+
260
+ ANNUALIZED_SORTINO_RATIO : str
261
+ Annualized Sortino ratio.
262
+
263
+ MEAN_ABSOLUTE_DEVIATION_RATIO : str
264
+ Ratio of the excess Mean divided by the Mean Absolute Deviation.
265
+
266
+ FIRST_LOWER_PARTIAL_MOMENT_RATIO : str
267
+ Ratio of the excess Mean divided by the First Lower Partial Moment.
268
+
269
+ VALUE_AT_RISK_RATIO : str
270
+ Ratio of the excess Mean divided by the Value at Risk.
271
+
272
+ CVAR_RATIO : str
273
+ Ratio of the excess Mean divided by the Conditional Value at Risk.
274
+
275
+ ENTROPIC_RISK_MEASURE_RATIO : str
276
+ Ratio of the excess Mean divided by the Entropic Risk Measure.
277
+
278
+ EVAR_RATIO : str
279
+ Ratio of the excess Mean divided by the Entropic Value at Risk.
280
+
281
+ WORST_REALIZATION_RATIO : str
282
+ Ratio of the excess Mean divided by the Worst Realization.
283
+
284
+ DRAWDOWN_AT_RISK_RATIO : str
285
+ Ratio of the excess Mean divided by the Drawdown at Risk.
286
+
287
+ CDAR_RATIO : str
288
+ Ratio of the excess Mean divided by the Conditional Drawdown at Risk.
289
+
290
+ CALMAR_RATIO : str
291
+ Ratio of the excess Mean divided by the Maximum Drawdown.
292
+
293
+ AVERAGE_DRAWDOWN_RATIO : str
294
+ Ratio of the excess Mean divided by the Average Drawdown.
295
+
296
+ EDAR_RATIO : str
297
+ Ratio of the excess Mean divided by the Entropic Drawdown at Risk.
298
+
299
+ ULCER_INDEX_RATIO : str
300
+ Ratio of the excess Mean divided by the Ulcer Index.
301
+
302
+ GINI_MEAN_DIFFERENCE_RATIO : str
303
+ Ratio of the excess Mean divided by the Gini Mean Difference.
304
+ """
305
+
306
+ SHARPE_RATIO = auto()
307
+ ANNUALIZED_SHARPE_RATIO = auto()
308
+ SORTINO_RATIO = auto()
309
+ ANNUALIZED_SORTINO_RATIO = auto()
310
+ MEAN_ABSOLUTE_DEVIATION_RATIO = auto()
311
+ FIRST_LOWER_PARTIAL_MOMENT_RATIO = auto()
312
+ VALUE_AT_RISK_RATIO = auto()
313
+ CVAR_RATIO = auto()
314
+ ENTROPIC_RISK_MEASURE_RATIO = auto()
315
+ EVAR_RATIO = auto()
316
+ WORST_REALIZATION_RATIO = auto()
317
+ DRAWDOWN_AT_RISK_RATIO = auto()
318
+ CDAR_RATIO = auto()
319
+ CALMAR_RATIO = auto()
320
+ AVERAGE_DRAWDOWN_RATIO = auto()
321
+ EDAR_RATIO = auto()
322
+ ULCER_INDEX_RATIO = auto()
323
+ GINI_MEAN_DIFFERENCE_RATIO = auto()
324
+
325
+ @property
326
+ def is_perf(self) -> bool:
327
+ return False
328
+
329
+ @property
330
+ def is_risk(self) -> bool:
331
+ return False
332
+
333
+ @property
334
+ def is_ratio(self) -> bool:
335
+ return True
336
+
337
+ @property
338
+ def linked_risk_measure(self) -> RiskMeasure | ExtraRiskMeasure:
339
+ match self:
340
+ case RatioMeasure.SHARPE_RATIO:
341
+ return RiskMeasure.STANDARD_DEVIATION
342
+ case RatioMeasure.ANNUALIZED_SHARPE_RATIO:
343
+ return RiskMeasure.ANNUALIZED_STANDARD_DEVIATION
344
+ case RatioMeasure.SORTINO_RATIO:
345
+ return RiskMeasure.SEMI_DEVIATION
346
+ case RatioMeasure.ANNUALIZED_SORTINO_RATIO:
347
+ return RiskMeasure.ANNUALIZED_SEMI_DEVIATION
348
+ case RatioMeasure.CALMAR_RATIO:
349
+ return RiskMeasure.MAX_DRAWDOWN
350
+ case _:
351
+ risk_measure = str(self.value).replace("_ratio", "")
352
+ try:
353
+ return RiskMeasure(risk_measure)
354
+ except ValueError:
355
+ return ExtraRiskMeasure(risk_measure)