skfolio 0.10.0__py3-none-any.whl → 0.10.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.
- skfolio/measures/_measures.py +4 -2
- skfolio/prior/_entropy_pooling.py +9 -9
- {skfolio-0.10.0.dist-info → skfolio-0.10.1.dist-info}/METADATA +12 -10
- {skfolio-0.10.0.dist-info → skfolio-0.10.1.dist-info}/RECORD +7 -7
- {skfolio-0.10.0.dist-info → skfolio-0.10.1.dist-info}/WHEEL +0 -0
- {skfolio-0.10.0.dist-info → skfolio-0.10.1.dist-info}/licenses/LICENSE +0 -0
- {skfolio-0.10.0.dist-info → skfolio-0.10.1.dist-info}/top_level.txt +0 -0
skfolio/measures/_measures.py
CHANGED
@@ -136,7 +136,9 @@ def variance(
|
|
136
136
|
if sample_weight is None:
|
137
137
|
return np.var(returns, ddof=0 if biased else 1, axis=0)
|
138
138
|
|
139
|
-
biased_var =
|
139
|
+
biased_var = (
|
140
|
+
sample_weight @ (returns - mean(returns, sample_weight=sample_weight)) ** 2
|
141
|
+
)
|
140
142
|
if biased:
|
141
143
|
return biased_var
|
142
144
|
n_eff = 1 / np.sum(sample_weight**2)
|
@@ -177,7 +179,7 @@ def semi_variance(
|
|
177
179
|
If `returns` is a 2D-array, the result is a ndarray of shape (n_assets,).
|
178
180
|
"""
|
179
181
|
if min_acceptable_return is None:
|
180
|
-
min_acceptable_return = mean(returns)
|
182
|
+
min_acceptable_return = mean(returns, sample_weight=sample_weight)
|
181
183
|
|
182
184
|
biased_semi_var = mean(
|
183
185
|
np.maximum(0, min_acceptable_return - returns) ** 2, sample_weight=sample_weight
|
@@ -589,10 +589,10 @@ class EntropyPooling(BasePrior):
|
|
589
589
|
|
590
590
|
Parameters
|
591
591
|
----------
|
592
|
-
a : ndarray of shape (n_observations,
|
592
|
+
a : ndarray of shape (n_observations, n_constraints)
|
593
593
|
Left matrix in `x @ a == b` or `x @ a <= b`.
|
594
594
|
|
595
|
-
a : ndarray of shape (n_observations,
|
595
|
+
a : ndarray of shape (n_observations, n_constraints)
|
596
596
|
Right vector in `x @ a == b` or `x @ a <= b`.
|
597
597
|
|
598
598
|
Returns
|
@@ -1029,16 +1029,16 @@ class EntropyPooling(BasePrior):
|
|
1029
1029
|
|
1030
1030
|
"""
|
1031
1031
|
n_observations, _ = self._returns.shape
|
1032
|
-
# Init
|
1032
|
+
# Init constraints with sum(p)==1, rescaled by its norm
|
1033
1033
|
# Has better convergence than the normalized form done inside the dual.
|
1034
1034
|
a = [np.ones(n_observations).reshape(-1, 1) / np.sqrt(n_observations)]
|
1035
1035
|
b = [np.array([1.0]) / np.sqrt(n_observations)]
|
1036
1036
|
bounds = [(None, None)]
|
1037
|
-
for name,
|
1038
|
-
if
|
1039
|
-
a.append(
|
1040
|
-
b.append(
|
1041
|
-
s =
|
1037
|
+
for name, constraints in self._constraints.items():
|
1038
|
+
if constraints is not None:
|
1039
|
+
a.append(constraints[0])
|
1040
|
+
b.append(constraints[1])
|
1041
|
+
s = constraints[1].size
|
1042
1042
|
match name:
|
1043
1043
|
case "equality" | "cvar_equality":
|
1044
1044
|
bounds += [(None, None)] * s
|
@@ -1145,7 +1145,7 @@ class EntropyPooling(BasePrior):
|
|
1145
1145
|
|
1146
1146
|
if self._constraints["fixed_equality"] is not None:
|
1147
1147
|
a, b = self._constraints["fixed_equality"]
|
1148
|
-
#
|
1148
|
+
# Relax the problem with slack variables with a norm1 penalty to avoid
|
1149
1149
|
# solver infeasibility that may arise from overly tight constraints from
|
1150
1150
|
# fixing the moments.
|
1151
1151
|
slack = cp.Variable(b.size)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: skfolio
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.1
|
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>, Matteo Manzi <matteomanzi09@gmail.com>
|
@@ -385,6 +385,7 @@ Imports
|
|
385
385
|
)
|
386
386
|
from skfolio.optimization import (
|
387
387
|
MeanRisk,
|
388
|
+
HierarchicalRiskParity,
|
388
389
|
NestedClustersOptimization,
|
389
390
|
ObjectiveFunction,
|
390
391
|
RiskBudgeting,
|
@@ -584,11 +585,13 @@ Factor Model
|
|
584
585
|
|
585
586
|
factor_prices = load_factors_dataset()
|
586
587
|
|
587
|
-
X,
|
588
|
-
X_train, X_test,
|
588
|
+
X, factors = prices_to_returns(prices, factor_prices)
|
589
|
+
X_train, X_test, factors_train, factors_test = train_test_split(
|
590
|
+
X, factors, test_size=0.33, shuffle=False
|
591
|
+
)
|
589
592
|
|
590
593
|
model = MeanRisk(prior_estimator=FactorModel())
|
591
|
-
model.fit(X_train,
|
594
|
+
model.fit(X_train, factors_train)
|
592
595
|
|
593
596
|
print(model.weights_)
|
594
597
|
|
@@ -597,7 +600,6 @@ Factor Model
|
|
597
600
|
print(portfolio.calmar_ratio)
|
598
601
|
print(portfolio.summary())
|
599
602
|
|
600
|
-
|
601
603
|
Factor Model & Covariance Detoning
|
602
604
|
----------------------------------
|
603
605
|
.. code-block:: python
|
@@ -658,7 +660,7 @@ Combinatorial Purged Cross-Validation
|
|
658
660
|
|
659
661
|
cv = CombinatorialPurgedCV(n_folds=10, n_test_folds=2)
|
660
662
|
|
661
|
-
print(cv.
|
663
|
+
print(cv.summary(X_train))
|
662
664
|
|
663
665
|
population = cross_val_predict(model, X_train, cv=cv)
|
664
666
|
|
@@ -674,7 +676,7 @@ Minimum CVaR Optimization on Synthetic Returns
|
|
674
676
|
.. code-block:: python
|
675
677
|
|
676
678
|
vine = VineCopula(log_transform=True, n_jobs=-1)
|
677
|
-
prior =
|
679
|
+
prior = SyntheticData(distribution_estimator=vine, n_samples=2000)
|
678
680
|
model = MeanRisk(risk_measure=RiskMeasure.CVAR, prior_estimator=prior)
|
679
681
|
model.fit(X)
|
680
682
|
print(model.weights_)
|
@@ -684,7 +686,7 @@ Stress Test
|
|
684
686
|
-----------
|
685
687
|
.. code-block:: python
|
686
688
|
|
687
|
-
vine = VineCopula(log_transform=True, central_assets=["BAC"]
|
689
|
+
vine = VineCopula(log_transform=True, central_assets=["BAC"], n_jobs=-1)
|
688
690
|
vine.fit(X)
|
689
691
|
X_stressed = vine.sample(n_samples=10_000, conditioning = {"BAC": -0.2})
|
690
692
|
ptf_stressed = model.predict(X_stressed)
|
@@ -702,7 +704,7 @@ Minimum CVaR Optimization on Synthetic Factors
|
|
702
704
|
)
|
703
705
|
factor_model = FactorModel(factor_prior_estimator=factor_prior)
|
704
706
|
model = MeanRisk(risk_measure=RiskMeasure.CVAR, prior_estimator=factor_model)
|
705
|
-
model.fit(X,
|
707
|
+
model.fit(X, factors)
|
706
708
|
print(model.weights_)
|
707
709
|
|
708
710
|
|
@@ -713,7 +715,7 @@ Factor Stress Test
|
|
713
715
|
factor_model.set_params(factor_prior_estimator__sample_args=dict(
|
714
716
|
conditioning={"QUAL": -0.5}
|
715
717
|
))
|
716
|
-
factor_model.fit(X,
|
718
|
+
factor_model.fit(X, factors)
|
717
719
|
stressed_dist = factor_model.return_distribution_
|
718
720
|
stressed_ptf = model.predict(stressed_dist)
|
719
721
|
|
@@ -37,7 +37,7 @@ skfolio/distribution/univariate/_selection.py,sha256=6KL4gngiLKwaBUpCDX19ABOkMBz
|
|
37
37
|
skfolio/distribution/univariate/_student_t.py,sha256=GcI4fKp6q5XegfvT_i3AqfWlUMxCq7A5sX6Xsf4pye8,4553
|
38
38
|
skfolio/measures/__init__.py,sha256=saJ3tGQyZ5MRtwnj0tVS9L4yvnLJVSdyXVyH5_FyoNo,1683
|
39
39
|
skfolio/measures/_enums.py,sha256=S6WOT8NHzm-eMHELuOjngIBupCctCdiTA2BaJlWl-4E,8956
|
40
|
-
skfolio/measures/_measures.py,sha256
|
40
|
+
skfolio/measures/_measures.py,sha256=-pF9DtJqsFliSiv9Ek_7IzytTmoKQFdqCxUl5fdSlYQ,28790
|
41
41
|
skfolio/metrics/__init__.py,sha256=ebu5h7Q9X0f3ZZ1VFmAEBPic2sirboKG_zNBHO5abjo,98
|
42
42
|
skfolio/metrics/_scorer.py,sha256=L-qct4cby15a4xC4arSaG5__1mxBCQYeMjlrHBIVnSY,4325
|
43
43
|
skfolio/model_selection/__init__.py,sha256=BT8VCXW7C4bXI2Oam4amTHOcJVlKxLpkcsHjB63pZHQ,524
|
@@ -100,7 +100,7 @@ skfolio/prior/__init__.py,sha256=4bi4u7Y-D9vLKb0nxlAXYEZUuYkjPXQcC7qlYUu_DMA,720
|
|
100
100
|
skfolio/prior/_base.py,sha256=aSqyhBYc35RpWq4XpM3UsOu88Bvxbqn7QhctK9bP0I0,2217
|
101
101
|
skfolio/prior/_black_litterman.py,sha256=oRH6wUjsL5bkjiNbVtxaIPMNi34rqPp7WBmDbJiklKM,10675
|
102
102
|
skfolio/prior/_empirical.py,sha256=zRceQNsbeWdkZHIaFvO91AhZTqkPd8YE2f60cK39M-U,7486
|
103
|
-
skfolio/prior/_entropy_pooling.py,sha256=
|
103
|
+
skfolio/prior/_entropy_pooling.py,sha256=x4qd-bU52ZGePwduPNY5fBhWwrNHfI77oWp5x0KyLPc,59285
|
104
104
|
skfolio/prior/_factor_model.py,sha256=lbXFsuidDJvLBX7fwp6fXXvgdL3MzkL5lJCx7HEABcA,12241
|
105
105
|
skfolio/prior/_opinion_pooling.py,sha256=dBZ8TjlAOKWA9lZFD4DS_PH5HG8iZYgtNrJLPnqwX0o,19055
|
106
106
|
skfolio/prior/_synthetic_data.py,sha256=HsxcIQa9lwcYh81Y-o00xsSr9-djgrTQtRTE4SCNpKo,8735
|
@@ -116,8 +116,8 @@ skfolio/utils/figure.py,sha256=2U0PuHRuza_1N6o_fWD8amNDc0IhgfzM5owFl3zBzwg,5744
|
|
116
116
|
skfolio/utils/sorting.py,sha256=F7gfIBfnulfDUiqvzrlR-pba4PPLJT6NH7-5s4sdRhw,3521
|
117
117
|
skfolio/utils/stats.py,sha256=glVHo7rjwy06dl5kkULLOADMrEkVJcfXXAz-1qmYQL4,17005
|
118
118
|
skfolio/utils/tools.py,sha256=XQ-bkbhIqBTuv_ZLK-vDnDx8NGFCFvmWoJF8Ui1tj38,23020
|
119
|
-
skfolio-0.10.
|
120
|
-
skfolio-0.10.
|
121
|
-
skfolio-0.10.
|
122
|
-
skfolio-0.10.
|
123
|
-
skfolio-0.10.
|
119
|
+
skfolio-0.10.1.dist-info/licenses/LICENSE,sha256=F6Gi-ZJX5BlVzYK8R9NcvAkAsKa7KO29xB1OScbrH6Q,1526
|
120
|
+
skfolio-0.10.1.dist-info/METADATA,sha256=LwEyMOUgw9X1asJvXVAVvkNSYeKXvqo35bZsZBFQ28o,25136
|
121
|
+
skfolio-0.10.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
122
|
+
skfolio-0.10.1.dist-info/top_level.txt,sha256=NXEaoS9Ms7t32gxkb867nV0OKlU0KmssL7IJBVo0fJs,8
|
123
|
+
skfolio-0.10.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|