skfolio 0.0.10__py3-none-any.whl → 0.1.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 (54) hide show
  1. skfolio/cluster/_hierarchical.py +5 -4
  2. skfolio/datasets/_base.py +5 -0
  3. skfolio/distance/_base.py +1 -0
  4. skfolio/distance/_distance.py +1 -0
  5. skfolio/exceptions.py +1 -0
  6. skfolio/measures/_enums.py +1 -0
  7. skfolio/measures/_measures.py +28 -0
  8. skfolio/metrics/_scorer.py +5 -0
  9. skfolio/model_selection/_combinatorial.py +5 -0
  10. skfolio/model_selection/_validation.py +5 -0
  11. skfolio/model_selection/_walk_forward.py +6 -1
  12. skfolio/moments/covariance/_base.py +7 -0
  13. skfolio/moments/covariance/_covariance.py +7 -0
  14. skfolio/moments/expected_returns/_base.py +4 -0
  15. skfolio/moments/expected_returns/_expected_returns.py +5 -0
  16. skfolio/optimization/_base.py +8 -0
  17. skfolio/optimization/cluster/_nco.py +5 -0
  18. skfolio/optimization/cluster/hierarchical/_base.py +4 -0
  19. skfolio/optimization/cluster/hierarchical/_herc.py +3 -1
  20. skfolio/optimization/cluster/hierarchical/_hrp.py +4 -0
  21. skfolio/optimization/convex/_base.py +4 -1
  22. skfolio/optimization/convex/_distributionally_robust.py +1 -0
  23. skfolio/optimization/convex/_maximum_diversification.py +2 -1
  24. skfolio/optimization/convex/_mean_risk.py +5 -2
  25. skfolio/optimization/convex/_risk_budgeting.py +3 -0
  26. skfolio/optimization/ensemble/_base.py +4 -0
  27. skfolio/optimization/ensemble/_stacking.py +4 -0
  28. skfolio/population/_population.py +1 -0
  29. skfolio/portfolio/_base.py +9 -9
  30. skfolio/portfolio/_multi_period_portfolio.py +9 -5
  31. skfolio/portfolio/_portfolio.py +3 -2
  32. skfolio/pre_selection/_pre_selection.py +1 -0
  33. skfolio/preprocessing/_returns.py +2 -1
  34. skfolio/prior/_base.py +1 -0
  35. skfolio/prior/_black_litterman.py +4 -0
  36. skfolio/prior/_empirical.py +2 -0
  37. skfolio/prior/_factor_model.py +5 -0
  38. skfolio/typing.py +1 -0
  39. skfolio/uncertainty_set/_base.py +1 -0
  40. skfolio/uncertainty_set/_bootstrap.py +5 -0
  41. skfolio/uncertainty_set/_empirical.py +5 -0
  42. skfolio/utils/bootstrap.py +3 -0
  43. skfolio/utils/equations.py +1 -0
  44. skfolio/utils/fixes/__init__.py +3 -0
  45. skfolio/utils/fixes/_dendrogram.py +389 -0
  46. skfolio/utils/sorting.py +1 -0
  47. skfolio/utils/stats.py +4 -1
  48. skfolio/utils/tools.py +4 -0
  49. {skfolio-0.0.10.dist-info → skfolio-0.1.0.dist-info}/METADATA +18 -7
  50. skfolio-0.1.0.dist-info/RECORD +81 -0
  51. skfolio-0.0.10.dist-info/RECORD +0 -79
  52. {skfolio-0.0.10.dist-info → skfolio-0.1.0.dist-info}/LICENSE +0 -0
  53. {skfolio-0.0.10.dist-info → skfolio-0.1.0.dist-info}/WHEEL +0 -0
  54. {skfolio-0.0.10.dist-info → skfolio-0.1.0.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,12 @@
1
1
  """Factor Model estimator"""
2
2
 
3
+ # Copyright (c) 2023
3
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
5
  # License: BSD 3 clause
6
+ # Implementation derived from:
7
+ # Riskfolio-Lib, Copyright (c) 2020-2023, Dany Cajas, Licensed under BSD 3 clause.
8
+ # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
9
+ # Grisel Licensed under BSD 3 clause.
5
10
 
6
11
  from abc import ABC, abstractmethod
7
12
 
skfolio/typing.py CHANGED
@@ -1,5 +1,6 @@
1
1
  """Custom typing module."""
2
2
 
3
+ # Copyright (c) 2023
3
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
5
  # License: BSD 3 clause
5
6
 
@@ -1,5 +1,6 @@
1
1
  """Base Uncertainty estimator"""
2
2
 
3
+ # Copyright (c) 2023
3
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
5
  # License: BSD 3 clause
5
6
 
@@ -1,7 +1,12 @@
1
1
  """Bootstrap Uncertainty Set estimators."""
2
2
 
3
+ # Copyright (c) 2023
3
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
5
  # License: BSD 3 clause
6
+ # Implementation derived from:
7
+ # Riskfolio-Lib, Copyright (c) 2020-2023, Dany Cajas, Licensed under BSD 3 clause.
8
+ # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
9
+ # Grisel Licensed under BSD 3 clause.
5
10
 
6
11
  import numpy as np
7
12
  import numpy.typing as npt
@@ -1,7 +1,12 @@
1
1
  """Empirical Uncertainty Set estimators."""
2
2
 
3
+ # Copyright (c) 2023
3
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
5
  # License: BSD 3 clause
6
+ # Implementation derived from:
7
+ # Riskfolio-Lib, Copyright (c) 2020-2023, Dany Cajas, Licensed under BSD 3 clause.
8
+ # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
9
+ # Grisel Licensed under BSD 3 clause.
5
10
 
6
11
  import numpy as np
7
12
  import numpy.typing as npt
@@ -1,7 +1,10 @@
1
1
  """Bootstrap module."""
2
2
 
3
+ # Copyright (c) 2023
3
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
5
  # License: BSD 3 clause
6
+ # Implementation derived from:
7
+ # Riskfolio-Lib, Copyright (c) 2020-2023, Dany Cajas, Licensed under BSD 3 clause.
5
8
 
6
9
  import numpy as np
7
10
 
@@ -1,5 +1,6 @@
1
1
  """Equation module"""
2
2
 
3
+ # Copyright (c) 2023
3
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
5
  # License: BSD 3 clause
5
6
 
@@ -0,0 +1,3 @@
1
+ from skfolio.utils.fixes._dendrogram import create_dendrogram
2
+
3
+ __all__ = ["create_dendrogram"]
@@ -0,0 +1,389 @@
1
+ """Compatibility fixes for plotly"""
2
+
3
+ # Fixes of the create_dendrogram plotly function until
4
+ # https://github.com/plotly/plotly.py/pull/4487 is corrected
5
+
6
+ from collections import OrderedDict
7
+
8
+ import numpy as np
9
+ import scipy.cluster.hierarchy as sch
10
+ import scipy.spatial as scs
11
+ from plotly import exceptions
12
+ from plotly.graph_objs import graph_objs
13
+
14
+
15
+ def create_dendrogram(
16
+ X,
17
+ orientation="bottom",
18
+ labels=None,
19
+ colorscale=None,
20
+ distfun=None,
21
+ linkagefun=lambda x: sch.linkage(x, "complete"),
22
+ hovertext=None,
23
+ color_threshold=None,
24
+ ):
25
+ """
26
+ Function that returns a dendrogram Plotly figure object. This is a thin
27
+ wrapper around scipy.cluster.hierarchy.dendrogram.
28
+
29
+ See also https://dash.plot.ly/dash-bio/clustergram.
30
+
31
+ :param (ndarray) X: Matrix of observations as array of arrays
32
+ :param (str) orientation: 'top', 'right', 'bottom', or 'left'
33
+ :param (list) labels: List of axis category labels(observation labels)
34
+ :param (list) colorscale: Optional colorscale for the dendrogram tree.
35
+ Requires 8 colors to be specified, the 7th of
36
+ which is ignored. With scipy>=1.5.0, the 2nd, 3rd
37
+ and 6th are used twice as often as the others.
38
+ Given a shorter list, the missing values are
39
+ replaced with defaults and with a longer list the
40
+ extra values are ignored.
41
+ :param (function) distfun: Function to compute the pairwise distance from
42
+ the observations
43
+ :param (function) linkagefun: Function to compute the linkage matrix from
44
+ the pairwise distances
45
+ :param (list[list]) hovertext: List of hovertext for constituent traces of dendrogram
46
+ clusters
47
+ :param (double) color_threshold: Value at which the separation of clusters will be made
48
+
49
+ Example 1: Simple bottom oriented dendrogram
50
+
51
+ >>> from plotly.figure_factory import create_dendrogram
52
+
53
+ >>> import numpy as np
54
+
55
+ >>> X = np.random.rand(10,10)
56
+ >>> fig = create_dendrogram(X)
57
+ >>> fig.show()
58
+
59
+ Example 2: Dendrogram to put on the left of the heatmap
60
+
61
+ >>> from plotly.figure_factory import create_dendrogram
62
+
63
+ >>> import numpy as np
64
+
65
+ >>> X = np.random.rand(5,5)
66
+ >>> names = ['Jack', 'Oxana', 'John', 'Chelsea', 'Mark']
67
+ >>> dendro = create_dendrogram(X, orientation='right', labels=names)
68
+ >>> dendro.update_layout({'width':700, 'height':500}) # doctest: +SKIP
69
+ >>> dendro.show()
70
+
71
+ Example 3: Dendrogram with Pandas
72
+
73
+ >>> from plotly.figure_factory import create_dendrogram
74
+
75
+ >>> import numpy as np
76
+ >>> import pandas as pd
77
+
78
+ >>> Index= ['A','B','C','D','E','F','G','H','I','J']
79
+ >>> df = pd.DataFrame(abs(np.random.randn(10, 10)), index=Index)
80
+ >>> fig = create_dendrogram(df, labels=Index)
81
+ >>> fig.show()
82
+ """
83
+
84
+ s = X.shape
85
+ if len(s) != 2:
86
+ exceptions.PlotlyError("X should be 2-dimensional array.")
87
+
88
+ if distfun is None:
89
+ distfun = scs.distance.pdist
90
+
91
+ dendrogram = _Dendrogram(
92
+ X,
93
+ orientation,
94
+ labels,
95
+ colorscale,
96
+ distfun=distfun,
97
+ linkagefun=linkagefun,
98
+ hovertext=hovertext,
99
+ color_threshold=color_threshold,
100
+ )
101
+
102
+ return graph_objs.Figure(data=dendrogram.data, layout=dendrogram.layout)
103
+
104
+
105
+ class _Dendrogram:
106
+ """Refer to FigureFactory.create_dendrogram() for docstring."""
107
+
108
+ def __init__(
109
+ self,
110
+ X,
111
+ orientation="bottom",
112
+ labels=None,
113
+ colorscale=None,
114
+ width=np.inf,
115
+ height=np.inf,
116
+ xaxis="xaxis",
117
+ yaxis="yaxis",
118
+ distfun=None,
119
+ linkagefun=lambda x: sch.linkage(x, "complete"),
120
+ hovertext=None,
121
+ color_threshold=None,
122
+ ):
123
+ self.orientation = orientation
124
+ self.labels = labels
125
+ self.xaxis = xaxis
126
+ self.yaxis = yaxis
127
+ self.data = []
128
+ self.leaves = []
129
+ self.sign = {self.xaxis: 1, self.yaxis: 1}
130
+ self.layout = {self.xaxis: {}, self.yaxis: {}}
131
+
132
+ if self.orientation in ["left", "bottom"]:
133
+ self.sign[self.xaxis] = 1
134
+ else:
135
+ self.sign[self.xaxis] = -1
136
+
137
+ if self.orientation in ["right", "bottom"]:
138
+ self.sign[self.yaxis] = 1
139
+ else:
140
+ self.sign[self.yaxis] = -1
141
+
142
+ if distfun is None:
143
+ distfun = scs.distance.pdist
144
+
145
+ (dd_traces, xvals, yvals, ordered_labels, leaves) = self.get_dendrogram_traces(
146
+ X, colorscale, distfun, linkagefun, hovertext, color_threshold
147
+ )
148
+
149
+ self.labels = ordered_labels
150
+ self.leaves = leaves
151
+ yvals_flat = yvals.flatten()
152
+ xvals_flat = xvals.flatten()
153
+
154
+ self.zero_vals = []
155
+
156
+ for i in range(len(yvals_flat)):
157
+ if yvals_flat[i] == 0.0 and xvals_flat[i] not in self.zero_vals:
158
+ self.zero_vals.append(xvals_flat[i])
159
+
160
+ if len(self.zero_vals) > len(yvals) + 1:
161
+ # If the length of zero_vals is larger than the length of yvals,
162
+ # it means that there are wrong vals because of the identicial samples.
163
+ # Three and more identicial samples will make the yvals of spliting
164
+ # center into 0 and it will accidentally take it as leaves.
165
+ l_border = int(min(self.zero_vals))
166
+ r_border = int(max(self.zero_vals))
167
+ correct_leaves_pos = range(
168
+ l_border, r_border + 1, int((r_border - l_border) / len(yvals))
169
+ )
170
+ # Regenerating the leaves pos from the self.zero_vals with equally intervals.
171
+ self.zero_vals = [v for v in correct_leaves_pos]
172
+
173
+ self.zero_vals.sort()
174
+ self.layout = self.set_figure_layout(width, height)
175
+ self.data = dd_traces
176
+
177
+ def get_color_dict(self, colorscale):
178
+ """
179
+ Returns colorscale used for dendrogram tree clusters.
180
+
181
+ :param (list) colorscale: Colors to use for the plot in rgb format.
182
+ :rtype (dict): A dict of default colors mapped to the user colorscale.
183
+
184
+ """
185
+
186
+ # These are the color codes returned for dendrograms
187
+ # We're replacing them with nicer colors
188
+ # This list is the colors that can be used by dendrogram, which were
189
+ # determined as the combination of the default above_threshold_color and
190
+ # the default color palette (see scipy/cluster/hierarchy.py)
191
+ d = {
192
+ "r": "red",
193
+ "g": "green",
194
+ "b": "blue",
195
+ "c": "cyan",
196
+ "m": "magenta",
197
+ "y": "yellow",
198
+ "k": "black",
199
+ # palette in scipy/cluster/hierarchy.py
200
+ "w": "white",
201
+ }
202
+ default_colors = OrderedDict(sorted(d.items(), key=lambda t: t[0]))
203
+
204
+ if colorscale is None:
205
+ rgb_colorscale = [
206
+ "rgb(0,116,217)", # blue
207
+ "rgb(35,205,205)", # cyan
208
+ "rgb(61,153,112)", # green
209
+ "rgb(40,35,35)", # black
210
+ "rgb(133,20,75)", # magenta
211
+ "rgb(255,65,54)", # red
212
+ "rgb(255,255,255)", # white
213
+ "rgb(255,220,0)", # yellow
214
+ ]
215
+ else:
216
+ rgb_colorscale = colorscale
217
+
218
+ for i in range(len(default_colors.keys())):
219
+ k = list(default_colors.keys())[i] # PY3 won't index keys
220
+ if i < len(rgb_colorscale):
221
+ default_colors[k] = rgb_colorscale[i]
222
+
223
+ # add support for cyclic format colors as introduced in scipy===1.5.0
224
+ # before this, the colors were named 'r', 'b', 'y' etc., now they are
225
+ # named 'C0', 'C1', etc. To keep the colors consistent regardless of the
226
+ # scipy version, we try as much as possible to map the new colors to the
227
+ # old colors
228
+ # this mapping was found by inpecting scipy/cluster/hierarchy.py (see
229
+ # comment above).
230
+ new_old_color_map = [
231
+ ("C0", "b"),
232
+ ("C1", "g"),
233
+ ("C2", "r"),
234
+ ("C3", "c"),
235
+ ("C4", "m"),
236
+ ("C5", "y"),
237
+ ("C6", "k"),
238
+ ("C7", "g"),
239
+ ("C8", "r"),
240
+ ("C9", "c"),
241
+ ]
242
+ for nc, oc in new_old_color_map:
243
+ try:
244
+ default_colors[nc] = default_colors[oc]
245
+ except KeyError:
246
+ # it could happen that the old color isn't found (if a custom
247
+ # colorscale was specified), in this case we set it to an
248
+ # arbitrary default.
249
+ default_colors[nc] = "rgb(0,116,217)"
250
+
251
+ return default_colors
252
+
253
+ def set_axis_layout(self, axis_key):
254
+ """
255
+ Sets and returns default axis object for dendrogram figure.
256
+
257
+ :param (str) axis_key: E.g., 'xaxis', 'xaxis1', 'yaxis', yaxis1', etc.
258
+ :rtype (dict): An axis_key dictionary with set parameters.
259
+
260
+ """
261
+ axis_defaults = {
262
+ "type": "linear",
263
+ "ticks": "outside",
264
+ "mirror": "allticks",
265
+ "rangemode": "tozero",
266
+ "showticklabels": True,
267
+ "zeroline": False,
268
+ "showgrid": False,
269
+ "showline": True,
270
+ }
271
+
272
+ if len(self.labels) != 0:
273
+ axis_key_labels = self.xaxis
274
+ if self.orientation in ["left", "right"]:
275
+ axis_key_labels = self.yaxis
276
+ if axis_key_labels not in self.layout:
277
+ self.layout[axis_key_labels] = {}
278
+ self.layout[axis_key_labels]["tickvals"] = [
279
+ zv * self.sign[axis_key] for zv in self.zero_vals
280
+ ]
281
+ self.layout[axis_key_labels]["ticktext"] = self.labels
282
+ self.layout[axis_key_labels]["tickmode"] = "array"
283
+
284
+ self.layout[axis_key].update(axis_defaults)
285
+
286
+ return self.layout[axis_key]
287
+
288
+ def set_figure_layout(self, width, height):
289
+ """
290
+ Sets and returns default layout object for dendrogram figure.
291
+
292
+ """
293
+ self.layout.update({
294
+ "showlegend": False,
295
+ "autosize": False,
296
+ "hovermode": "closest",
297
+ "width": width,
298
+ "height": height,
299
+ })
300
+
301
+ self.set_axis_layout(self.xaxis)
302
+ self.set_axis_layout(self.yaxis)
303
+
304
+ return self.layout
305
+
306
+ def get_dendrogram_traces(
307
+ self, X, colorscale, distfun, linkagefun, hovertext, color_threshold
308
+ ):
309
+ """
310
+ Calculates all the elements needed for plotting a dendrogram.
311
+
312
+ :param (ndarray) X: Matrix of observations as array of arrays
313
+ :param (list) colorscale: Color scale for dendrogram tree clusters
314
+ :param (function) distfun: Function to compute the pairwise distance
315
+ from the observations
316
+ :param (function) linkagefun: Function to compute the linkage matrix
317
+ from the pairwise distances
318
+ :param (list) hovertext: List of hovertext for constituent traces of dendrogram
319
+ :rtype (tuple): Contains all the traces in the following order:
320
+ (a) trace_list: List of Plotly trace objects for dendrogram tree
321
+ (b) icoord: All X points of the dendrogram tree as array of arrays
322
+ with length 4
323
+ (c) dcoord: All Y points of the dendrogram tree as array of arrays
324
+ with length 4
325
+ (d) ordered_labels: leaf labels in the order they are going to
326
+ appear on the plot
327
+ (e) P['leaves']: left-to-right traversal of the leaves
328
+
329
+ """
330
+ d = distfun(X)
331
+ Z = linkagefun(d)
332
+ P = sch.dendrogram(
333
+ Z,
334
+ orientation=self.orientation,
335
+ labels=self.labels,
336
+ no_plot=True,
337
+ color_threshold=color_threshold,
338
+ )
339
+
340
+ icoord = np.array(P["icoord"])
341
+ dcoord = np.array(P["dcoord"])
342
+ ordered_labels = np.array(P["ivl"])
343
+ color_list = np.array(P["color_list"])
344
+ colors = self.get_color_dict(colorscale)
345
+
346
+ trace_list = []
347
+
348
+ for i in range(len(icoord)):
349
+ # xs and ys are arrays of 4 points that make up the '∩' shapes
350
+ # of the dendrogram tree
351
+ if self.orientation in ["top", "bottom"]:
352
+ xs = icoord[i]
353
+ else:
354
+ xs = dcoord[i]
355
+
356
+ if self.orientation in ["top", "bottom"]:
357
+ ys = dcoord[i]
358
+ else:
359
+ ys = icoord[i]
360
+ color_key = color_list[i]
361
+ hovertext_label = None
362
+ if hovertext:
363
+ hovertext_label = hovertext[i]
364
+ trace = dict(
365
+ type="scatter",
366
+ x=np.multiply(self.sign[self.xaxis], xs),
367
+ y=np.multiply(self.sign[self.yaxis], ys),
368
+ mode="lines",
369
+ marker=dict(color=colors[color_key]),
370
+ text=hovertext_label,
371
+ hoverinfo="text",
372
+ )
373
+
374
+ try:
375
+ x_index = int(self.xaxis[-1])
376
+ except ValueError:
377
+ x_index = ""
378
+
379
+ try:
380
+ y_index = int(self.yaxis[-1])
381
+ except ValueError:
382
+ y_index = ""
383
+
384
+ trace["xaxis"] = "x" + x_index
385
+ trace["yaxis"] = "y" + y_index
386
+
387
+ trace_list.append(trace)
388
+
389
+ return trace_list, icoord, dcoord, ordered_labels, P["leaves"]
skfolio/utils/sorting.py CHANGED
@@ -1,5 +1,6 @@
1
1
  """Fast non-dominated sorting module"""
2
2
 
3
+ # Copyright (c) 2023
3
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
5
  # License: BSD 3 clause
5
6
 
skfolio/utils/stats.py CHANGED
@@ -1,8 +1,11 @@
1
1
  """Tools module"""
2
2
 
3
+ # Copyright (c) 2023
3
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
5
  # License: BSD 3 clause
5
-
6
+ # Implementation derived from:
7
+ # Riskfolio-Lib, Copyright (c) 2020-2023, Dany Cajas, Licensed under BSD 3 clause.
8
+ # Statsmodels, Copyright (C) 2006, Jonathan E. Taylor, Licensed under BSD 3 clause.
6
9
 
7
10
  from enum import auto
8
11
 
skfolio/utils/tools.py CHANGED
@@ -1,7 +1,11 @@
1
1
  """Tools module"""
2
2
 
3
+ # Copyright (c) 2023
3
4
  # Author: Hugo Delatte <delatte.hugo@gmail.com>
4
5
  # License: BSD 3 clause
6
+ # Implementation derived from:
7
+ # scikit-learn, Copyright (c) 2007-2010 David Cournapeau, Fabian Pedregosa, Olivier
8
+ # Grisel Licensed under BSD 3 clause.
5
9
 
6
10
  from collections.abc import Callable, Iterator
7
11
  from enum import Enum
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: skfolio
3
- Version: 0.0.10
3
+ Version: 0.1.0
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>
@@ -37,7 +37,7 @@ Project-URL: API Reference, https://www.skfolio.org/api_reference.html
37
37
  Project-URL: Documentation, https://www.skfolio.org
38
38
  Project-URL: Tutorials, https://www.skfolio.org
39
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
40
+ Keywords: portfolio,optimization,optimisation,finance,asset,allocation,quantitative,quant,investment,strategy,machine-learning,scikit-learn,data-mining,data-science
41
41
  Classifier: Intended Audience :: Developers
42
42
  Classifier: Intended Audience :: Science/Research
43
43
  Classifier: Intended Audience :: Financial and Insurance Industry
@@ -85,12 +85,12 @@ Requires-Dist: ruff ; extra == 'tests'
85
85
 
86
86
  .. -*- mode: rst -*-
87
87
 
88
- |Licence|_ |Codecov|_ |Black|_ |PythonVersion|_ |PyPi|_ |CI/CD|_
88
+ |Licence|_ |Codecov|_ |Black|_ |PythonVersion|_ |PyPi|_ |CI/CD|_ |Downloads|_ |Ruff|_ |Contribution|_ |Website|_
89
89
 
90
90
  .. |Licence| image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
91
91
  .. _Licence: https://github.com/skfolio/skfolio/blob/main/LICENSE
92
92
 
93
- .. |Codecov| image:: https://codecov.io/gh/skfolio/skfolio/branch/main/graph/badge.svg
93
+ .. |Codecov| image:: https://codecov.io/gh/skfolio/skfolio/graph/badge.svg?token=KJ0SE4LHPV
94
94
  .. _Codecov: https://codecov.io/gh/skfolio/skfolio
95
95
 
96
96
  .. |PythonVersion| image:: https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue
@@ -105,6 +105,17 @@ Requires-Dist: ruff ; extra == 'tests'
105
105
  .. |CI/CD| image:: https://img.shields.io/github/actions/workflow/status/skfolio/skfolio/release.yml?logo=github
106
106
  .. _CI/CD: https://github.com/skfolio/skfolio/raw/main/LICENSE
107
107
 
108
+ .. |Downloads| image:: https://static.pepy.tech/badge/skfolio
109
+ .. _Downloads: https://pepy.tech/project/skfolio
110
+
111
+ .. |Ruff| image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
112
+ .. _Ruff: https://github.com/astral-sh/ruff
113
+
114
+ .. |Contribution| image:: https://img.shields.io/badge/Contributions-Welcome-blue
115
+ .. _Contribution: https://github.com/skfolio/skfolio/blob/main/CONTRIBUTING.md
116
+
117
+ .. |Website| image:: https://img.shields.io/website-up-down-53cc0d-red/http/skfolio.org
118
+ .. _Website: https://skfolio.org
108
119
 
109
120
  .. |PythonMinVersion| replace:: 3.10
110
121
  .. |NumpyMinVersion| replace:: 1.23.4
@@ -119,7 +130,7 @@ Requires-Dist: ruff ; extra == 'tests'
119
130
  ===============
120
131
  |icon| skfolio
121
132
  ===============
122
- .. |icon| image:: https://raw.githubusercontent.com/skfolio/skfolio/master/docs/_static/favicon.png
133
+ .. |icon| image:: https://raw.githubusercontent.com/skfolio/skfolio/master/docs/_static/logo_animate.svg
123
134
  :width: 100
124
135
  :alt: skfolio documentation
125
136
  :target: https://skfolio.org/
@@ -465,7 +476,7 @@ Randomized Search of the L2 Norm
465
476
 
466
477
  randomized_search = RandomizedSearchCV(
467
478
  estimator=MeanRisk(),
468
- cv=WalkForward(train_size=255, test_size=60),
479
+ cv=WalkForward(train_size=252, test_size=60),
469
480
  param_distributions={
470
481
  "l2_coef": loguniform(1e-3, 1e-1),
471
482
  },
@@ -634,7 +645,7 @@ If you use `skfolio` in a scientific publication, we would appreciate citations:
634
645
  Bibtex entry::
635
646
 
636
647
  @misc{skfolio,
637
- author = {Hugo Delatte},
648
+ author = {Hugo Delatte, Carlo Nicolini},
638
649
  title = {skfolio},
639
650
  year = {2023},
640
651
  url = {https://github.com/skfolio/skfolio}
@@ -0,0 +1,81 @@
1
+ skfolio/__init__.py,sha256=5pn5LpTz6v2j2sxGkY97cVRrSPsN3Yav9b6Uw08boEI,618
2
+ skfolio/exceptions.py,sha256=-XniKql9QHgfitMgHsE9UXWVPdjWpNGO2dVk2SsdPWE,662
3
+ skfolio/typing.py,sha256=yEZiCZ6UIyfYUqtfj9Kf2KA9mrjUbmxyzpH9uqVboJs,1378
4
+ skfolio/cluster/__init__.py,sha256=4g-PFB_ld9BhiQ1ZPvvAorpFbRwd_p_DkeRlulDv2Hk,251
5
+ skfolio/cluster/_hierarchical.py,sha256=SoISGgdyq4Rgqq1_TCzMbLv69c8a2Q91j_s9-jqaB3E,12817
6
+ skfolio/datasets/__init__.py,sha256=9Tpf0Uj8wgr-g7xqvqQP4S4TUYDUNmNmK8t6lqBw2Fs,407
7
+ skfolio/datasets/_base.py,sha256=GYvblFzTyfTs-Tij20FKWgVDCIT1n7y4uwx4TkZzdHc,13915
8
+ skfolio/datasets/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ skfolio/datasets/data/factors_dataset.csv.gz,sha256=brCJlT25DJo40yg1gnUXAakNtvWZZYR_1ksFeN5JcWE,36146
10
+ skfolio/datasets/data/sp500_dataset.csv.gz,sha256=7iHKwovvsdCnOanOsiGE-ZU5RyaqDP3pohlB0awErA0,426065
11
+ skfolio/datasets/data/sp500_index.csv.gz,sha256=iUw0QxwoT4aqZKRn4Xbio8m2l8hX65qzUAbC3VXT_fI,41898
12
+ skfolio/distance/__init__.py,sha256=vpdmjFlJeI0AvPV3r5tp2zooAG4N9ihCwPlaqqdVj1w,547
13
+ skfolio/distance/_base.py,sha256=jBgRk6lZrP1woSI9541fTfxBBkp4WCTLlRPmWcmA3j4,1326
14
+ skfolio/distance/_distance.py,sha256=PHDqEourtqKSSFYiXKaUPQQqNFEqIEBhWcbWwe3fxjg,18539
15
+ skfolio/measures/__init__.py,sha256=Wm8soTkAapZ-g82INBpljgKfxkwCAIJdqjBOGVZBeQ8,1571
16
+ skfolio/measures/_enums.py,sha256=oy8wPm3EGsHokgLXe9xfUKet4vAuvch0cJuISH9RNvk,8902
17
+ skfolio/measures/_measures.py,sha256=nrpfaOVF94_ZpZXe2ciaBNzioGVTkzuYTmkYp9_EMec,16826
18
+ skfolio/metrics/__init__.py,sha256=MomHJ5_bgjq4qUwGS2bfhNmG_ld0oQ4wK6y0Yy_Eonc,75
19
+ skfolio/metrics/_scorer.py,sha256=h1VuZk-zzn4rIChHl9FvM7RxqVT3b-jR1CEB-cr9F2s,4306
20
+ skfolio/model_selection/__init__.py,sha256=QYYm5lYyioZuPnsTu-b3lz-tCcl3Gwrx-y9IIvep13A,453
21
+ skfolio/model_selection/_combinatorial.py,sha256=z4nhqIq98iGMP9I3GM8ng1WRJDJQn4eQ56bYaw5JWog,14716
22
+ skfolio/model_selection/_validation.py,sha256=uPk9HhOak1jh3PEjNMyi3jx4PzIW2fxnqdC7u1yWGwY,7644
23
+ skfolio/model_selection/_walk_forward.py,sha256=pbMD8VM1OoKiEtrlPeCLG29xVijsq1RArSjTvGO1FnU,7539
24
+ skfolio/moments/__init__.py,sha256=BaP6FjU-CEsV_mcC2AOKXNFy-_wXZsk-jqzJG6mTpsM,746
25
+ skfolio/moments/covariance/__init__.py,sha256=KuzhGuiu-eOwQMgWmEhFhqCcOmiayrYp5yeL1NsFW98,563
26
+ skfolio/moments/covariance/_base.py,sha256=mJ61A-zWU6mIXmGKzP3hoGEZyMpPV6qNeSM-VcScaWY,3955
27
+ skfolio/moments/covariance/_covariance.py,sha256=AyLm15Y5aziAJGg5P58_sXoW4jf4inV8PAs2Ye1zEyA,39003
28
+ skfolio/moments/expected_returns/__init__.py,sha256=NETEcKKYKsQvzUU4ZIq6mgT14zdrgGS6pb5Dy3qMEAE,367
29
+ skfolio/moments/expected_returns/_base.py,sha256=xk9mzi48uCOHaMTGQBMr3FU7Ai_shxYhmGeOsVwjv9Q,871
30
+ skfolio/moments/expected_returns/_expected_returns.py,sha256=T_tt_dsYgXrjIM2REUii7_4_R8IEc3xdtuv45yYM-5o,13388
31
+ skfolio/optimization/__init__.py,sha256=vXIbwWJL48zJ1jy7ZB2PPBVx7rZo0vVA8QQQuD-L6ts,1021
32
+ skfolio/optimization/_base.py,sha256=5GEMjlw5jrbygTp-4ZCk7cmwjJ0PBOoNdULqypVlfQM,5606
33
+ skfolio/optimization/cluster/__init__.py,sha256=M3xVdYhNKp4e9CB7hzb4yjTxkkNCHh7Mt_KGFFrkOgs,388
34
+ skfolio/optimization/cluster/_nco.py,sha256=MKzNvDIAbqS_D41Vp7tNa7OrXYq_bYVSQEVbVCHOEWA,14834
35
+ skfolio/optimization/cluster/hierarchical/__init__.py,sha256=YnfcPHvjwB6kcG4hoQqc0NqIJKaG7OjBtmXNbOxCq08,405
36
+ skfolio/optimization/cluster/hierarchical/_base.py,sha256=0FtVcrMOFsQIJVaShf_qoHBRSuVmR4qzmJdvJc214HI,17255
37
+ skfolio/optimization/cluster/hierarchical/_herc.py,sha256=JyXYX4PE17alCzIv6piF-G7_nprgzdzfYp35kjAeWMo,17235
38
+ skfolio/optimization/cluster/hierarchical/_hrp.py,sha256=xdnbYNcY1Vpv-mDw-JAGz5o--Rl2b8CfGzyunLJe75M,16121
39
+ skfolio/optimization/convex/__init__.py,sha256=F6BPFikTo0B-7JCKazqLGEwM3RkgTNbFm5GAGkaq9Uo,570
40
+ skfolio/optimization/convex/_base.py,sha256=rw9j-FM6gfY0UvAZG99rdrbZsH9neQ_MxeJr6AGIwlQ,75423
41
+ skfolio/optimization/convex/_distributionally_robust.py,sha256=nQW_MD0wlVY_tvLvRq_CvezOn4q92YC7wHfzFE9k9tY,17308
42
+ skfolio/optimization/convex/_maximum_diversification.py,sha256=8wQn5eFEat5wixmu0cfaswAee8D5C-hzV4s5ntUoAFM,19137
43
+ skfolio/optimization/convex/_mean_risk.py,sha256=ivAjLXis4fUZ9XOvh_iOemfnvgDAzrK3LDvrlaa2TpA,43130
44
+ skfolio/optimization/convex/_risk_budgeting.py,sha256=wXCgn64w2alAGG-dGJ8IwFrhYVtybM-O2hXiFaXietg,23618
45
+ skfolio/optimization/ensemble/__init__.py,sha256=8TXxcxH2_gG3C1xtgQj9OHHr0Le8lhdejtlURL6T3ZY,158
46
+ skfolio/optimization/ensemble/_base.py,sha256=vOi08U1MjoceD_xMFKTdM8egd1sY0GsCh1BSJuKH_fQ,3445
47
+ skfolio/optimization/ensemble/_stacking.py,sha256=3yqGHE1MpnugkJ0Z6fp7bfYLOuImsfmeiMQ8XDdIdZY,13098
48
+ skfolio/optimization/naive/__init__.py,sha256=Dkr55R48urC-jfYN007NTbei16N91Na_EDYLVqzhGgQ,147
49
+ skfolio/optimization/naive/_naive.py,sha256=sadsU8TnNRf28EDLg-KZ4yJm2FvV204vdsb1MhVJyMQ,5561
50
+ skfolio/population/__init__.py,sha256=rsPPMUv95aTK7vmpPeQwF8NzFuBwk6RDo5g4HNaPzNM,80
51
+ skfolio/population/_population.py,sha256=cyHdpZr6Ib725CRE_rr0irI4sHEcVEAY-Gmy--1goKo,29242
52
+ skfolio/portfolio/__init__.py,sha256=YYtcAPmA2zeCxFGTXegg2FXcA7py6CxOX7IMTdYuXl0,586
53
+ skfolio/portfolio/_base.py,sha256=XHSFrQJRY6nIyUG8sd8ZgbwZt7_ZKlMRNCfOqdls0Rw,38314
54
+ skfolio/portfolio/_multi_period_portfolio.py,sha256=63RwL0oTn-3L5LON6f2e9J58zw9q8S2gQ5c8JfSnN28,22759
55
+ skfolio/portfolio/_portfolio.py,sha256=axthHXaavCll_qXrYvJqfk-6AuMNDb-syD__jU_9acU,30714
56
+ skfolio/pre_selection/__init__.py,sha256=VtUtDn-U-Mn_xR2k7yfld0Yb0rPhLakEAiBwUyi-4Z8,189
57
+ skfolio/pre_selection/_pre_selection.py,sha256=w84T14nKmzkgzbw5CW_AIlci741lXYxKUwB5pBjhTTI,12163
58
+ skfolio/preprocessing/__init__.py,sha256=15A1bzfPsbfxxXgGP1gstf4R0E_347Wn18z5W5jH-hk,94
59
+ skfolio/preprocessing/_returns.py,sha256=_7UtXugQPWitNrrZ3M2dUOAun8aVr0lI45Ms6KFiS94,3826
60
+ skfolio/prior/__init__.py,sha256=jql8NTiWlykPKJUXTOPdqm531mP8Pul1QAR6hXTXA6c,446
61
+ skfolio/prior/_base.py,sha256=Dx6rX0X6ymDiieFOI-ik3xMNNFhYEtwLSXOdajf5wZY,1927
62
+ skfolio/prior/_black_litterman.py,sha256=JuwVXLXY5qHETBZDg0wmBGMSQehJp_1t7c1-kanKaiU,9397
63
+ skfolio/prior/_empirical.py,sha256=YhCYW8R3vqs3ntF4WSokuwLW6Gd98df7f8LL8zCS-D0,5740
64
+ skfolio/prior/_factor_model.py,sha256=E42sx_CbT-GbkT-BBb59XrUP4DMYJzuf3I2MEcGEnyE,9608
65
+ skfolio/uncertainty_set/__init__.py,sha256=LlMHtYv9G9fgtM7m4sCSToS9et57Pm2Q2gGchTVrj6c,617
66
+ skfolio/uncertainty_set/_base.py,sha256=rZ3g2AhDKFQTPajgh6Fz5S5TTf0qM4Ie6RGxPhp32D8,3301
67
+ skfolio/uncertainty_set/_bootstrap.py,sha256=Rig8ZGc8rEOnYygPyTaDSu5lp3wGuZrQVRoJTm3UuAA,10301
68
+ skfolio/uncertainty_set/_empirical.py,sha256=81DoTFxWsx8dALVRbvVEc6mBfgC-QIkUOK60dhkgFUI,8429
69
+ skfolio/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
+ skfolio/utils/bootstrap.py,sha256=3zY2kO_GQURKEcQMCasJOSByde9Mt2IAi3KJH0_a4mk,3550
71
+ skfolio/utils/equations.py,sha256=w0HsYjA7cS0mHYsI9MpixHLkof3HN26nc14ZfqFrHlE,11047
72
+ skfolio/utils/sorting.py,sha256=lSjMvH2L-sSj-06B3MlwBrH1rtjCeGEe4hG894W7TE0,3504
73
+ skfolio/utils/stats.py,sha256=IP36nMc5j5Hcqjbg7lvDIsGp1GWRdOh5jU3W6Z8nkYs,13132
74
+ skfolio/utils/tools.py,sha256=roj4zTwmfunPb8HtxcOPAsCKpk0ZPEPnQztSglE9t4o,15351
75
+ skfolio/utils/fixes/__init__.py,sha256=knHau8PRZP07XDHR59CW8VWxkpTP0gdr6RAHJrO-zaA,95
76
+ skfolio/utils/fixes/_dendrogram.py,sha256=QK0OYAmlDe4sdrbFtRvxIlKfPlOGyA2zmsZIz1fIMsM,13505
77
+ skfolio-0.1.0.dist-info/LICENSE,sha256=F6Gi-ZJX5BlVzYK8R9NcvAkAsKa7KO29xB1OScbrH6Q,1526
78
+ skfolio-0.1.0.dist-info/METADATA,sha256=zUZtTWjCZIla8MbEauTnhntSsQbJut6GWXk2cjJPMuE,19613
79
+ skfolio-0.1.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
80
+ skfolio-0.1.0.dist-info/top_level.txt,sha256=NXEaoS9Ms7t32gxkb867nV0OKlU0KmssL7IJBVo0fJs,8
81
+ skfolio-0.1.0.dist-info/RECORD,,