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
@@ -0,0 +1,196 @@
1
+ """Bivariate Independent Copula Estimation."""
2
+
3
+ # Copyright (c) 2025
4
+ # Author: Hugo Delatte <delatte.hugo@gmail.com>
5
+ # Credits: Matteo Manzi, Vincent Maladière, Carlo Nicolini
6
+ # SPDX-License-Identifier: BSD-3-Clause
7
+
8
+ import numpy as np
9
+ import numpy.typing as npt
10
+ import sklearn.utils.validation as skv
11
+
12
+ from skfolio.distribution.copula._base import BaseBivariateCopula
13
+
14
+
15
+ class IndependentCopula(BaseBivariateCopula):
16
+ r"""Bivariate Independent Copula (also called the product copula).
17
+
18
+ It is defined by:
19
+
20
+ .. math::
21
+ C(u, v) = u \cdot v
22
+
23
+ Parameters
24
+ ----------
25
+ random_state : int, RandomState instance or None, default=None
26
+ Seed or random state to ensure reproducibility.
27
+
28
+ References
29
+ ----------
30
+ .. [1] "An Introduction to Copulas (2nd ed.)",
31
+ Nelsen (2006)
32
+
33
+ .. [2] "Multivariate Models and Dependence Concepts",
34
+ Joe, Chapman & Hall (1997)
35
+
36
+ .. [3] "Quantitative Risk Management: Concepts, Techniques and Tools",
37
+ McNeil, Frey & Embrechts (2005)
38
+
39
+ .. [4] "The t Copula and Related Copulas",
40
+ Demarta & McNeil (2005)
41
+
42
+ .. [5] "Copula Methods in Finance",
43
+ Cherubini, Luciano & Vecchiato (2004)
44
+ """
45
+
46
+ _n_params = 0
47
+
48
+ def __init__(self, random_state: int | None = None):
49
+ super().__init__(random_state=random_state)
50
+
51
+ def fit(self, X: npt.ArrayLike, y=None) -> "IndependentCopula":
52
+ """Fit the Bivariate Independent Copula.
53
+
54
+ Provided for compatibility with the API.
55
+
56
+ Parameters
57
+ ----------
58
+ X : array-like of shape (n_observations, 2)
59
+ An array of bivariate inputs `(u, v)` where each row represents a
60
+ bivariate observation. Both `u` and `v` must be in the interval [0, 1],
61
+ having been transformed to uniform marginals.
62
+
63
+ y : None
64
+ Ignored. Provided for compatibility with scikit-learn's API.
65
+
66
+ Returns
67
+ -------
68
+ self : IndependentCopula
69
+ Returns the instance itself.
70
+ """
71
+ _ = self._validate_X(X, reset=True)
72
+ return self
73
+
74
+ def cdf(self, X: npt.ArrayLike) -> np.ndarray:
75
+ """Compute the CDF of the bivariate Independent copula.
76
+
77
+ Parameters
78
+ ----------
79
+ X : array-like of shape (n_observations, 2)
80
+ An array of bivariate inputs `(u, v)` where each row represents a
81
+ bivariate observation. Both `u` and `v` must be in the interval `[0, 1]`,
82
+ having been transformed to uniform marginals.
83
+
84
+ Returns
85
+ -------
86
+ cdf : ndarray of shape (n_observations,)
87
+ CDF values for each observation in X.
88
+ """
89
+ skv.check_is_fitted(self)
90
+ X = self._validate_X(X, reset=False)
91
+ cdf = X.prod(axis=1)
92
+ return cdf
93
+
94
+ def partial_derivative(
95
+ self, X: npt.ArrayLike, first_margin: bool = False
96
+ ) -> np.ndarray:
97
+ r"""Compute the h-function (partial derivative) for the bivariate Independent
98
+ copula.
99
+
100
+ The h-function with respect to the second margin represents the conditional
101
+ distribution function of :math:`u` given :math:`v`:
102
+
103
+ .. math::
104
+ \frac{\partial C(u,v)}{\partial v}=u,
105
+
106
+ Parameters
107
+ ----------
108
+ X : array-like of shape (n_samples, 2)
109
+ Array of pairs :math:`(u,v)`, where each value is in the interval [0,1].
110
+
111
+ Returns
112
+ -------
113
+ np.ndarray
114
+ Array of h-function values for each observation in X.
115
+ """
116
+ skv.check_is_fitted(self)
117
+ X = self._validate_X(X, reset=False)
118
+ h = X[:, 1] if first_margin else X[:, 0]
119
+ return h
120
+
121
+ def inverse_partial_derivative(
122
+ self, X: npt.ArrayLike, first_margin: bool = False
123
+ ) -> np.ndarray:
124
+ r"""Compute the inverse of the bivariate copula's partial derivative, commonly
125
+ known as the inverse h-function.
126
+
127
+ For the independent copula, the h-function with respect to the second margin is
128
+
129
+ .. math::
130
+ h(u\mid v)= u,
131
+
132
+ and the derivative with respect to the first margin is
133
+
134
+ .. math::
135
+ g(u,v)= v.
136
+
137
+ Their inverses are trivial:
138
+
139
+ - Given (p,v) for h(u|v)= p, we have u = p.
140
+ - Given (p,u) for g(u,v)= p, we have v = p.
141
+
142
+ Parameters
143
+ ----------
144
+ X : array-like of shape (n_observations, 2)
145
+ An array of bivariate inputs `(p, v)`, each in the interval `[0, 1]`.
146
+ - The first column `p` corresponds to the value of the h-function.
147
+ - The second column `v` is the conditioning variable.
148
+
149
+ first_margin : bool, default=False
150
+ If True, compute the inverse partial derivative with respect to the first
151
+ margin `u`; otherwise, compute the inverse partial derivative with respect
152
+ to the second margin `v`.
153
+
154
+ Returns
155
+ -------
156
+ u : ndarray of shape (n_observations,)
157
+ A 1D-array of length `n_observations`, where each element is the computed
158
+ :math:`u = h^{-1}(p \mid v)` for the corresponding pair in `X`.
159
+ """
160
+ skv.check_is_fitted(self)
161
+ X = self._validate_X(X, reset=False)
162
+ u = X[:, 1] if first_margin else X[:, 0]
163
+ return u
164
+
165
+ def score_samples(self, X: npt.ArrayLike) -> np.ndarray:
166
+ """Compute the log-likelihood of each sample (log-pdf) under the model.
167
+
168
+ Parameters
169
+ ----------
170
+ X : array-like of shape (n_samples, 2)
171
+ The input data where each row represents a bivariate observation.
172
+ The data should be transformed to uniform marginals in [0, 1].
173
+
174
+ Returns
175
+ -------
176
+ density : ndarray of shape (n_samples,)
177
+ The log-likelihood of each sample under the fitted copula.
178
+ """
179
+ skv.check_is_fitted(self)
180
+ X = self._validate_X(X, reset=False)
181
+ return np.zeros(X.shape[0]) # log(1.0)
182
+
183
+ @property
184
+ def lower_tail_dependence(self) -> float:
185
+ """Theoretical lower tail dependence coefficient."""
186
+ return 0
187
+
188
+ @property
189
+ def upper_tail_dependence(self) -> float:
190
+ """Theoretical upper tail dependence coefficient."""
191
+ return 0
192
+
193
+ @property
194
+ def fitted_repr(self) -> str:
195
+ """String representation of the fitted copula."""
196
+ return f"{self.__class__.__name__}()"