Skip to content

Commit dba1350

Browse files
authored
Merge pull request #77 from PyFE/riskparity
Update assetalloc.py
2 parents e08c60a + af53eda commit dba1350

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

pyfeng/assetalloc.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def __init__(self, sigma=None, cor=None, cov=None, ret=None, longshort=1):
3030
# when sigma and cor are given
3131

3232
self.sigma = np.atleast_1d(sigma)
33-
self.n_asset = self.sigma.shape[0]
33+
self.n_asset = len(self.sigma)
3434

3535
if self.n_asset == 1:
3636
raise ValueError(f"The number of assets should be more than one.")
@@ -64,7 +64,7 @@ def __init__(self, sigma=None, cor=None, cov=None, ret=None, longshort=1):
6464
elif np.isscalar(longshort):
6565
self.longshort = np.full(self.n_asset, np.sign(longshort), dtype=np.int8) # long-only
6666
else:
67-
assert self.n_asset == longshort.shape[0]
67+
assert self.n_asset == len(longshort)
6868
self.longshort = np.sign(longshort, dtype=np.int8) # long-only
6969

7070

@@ -85,11 +85,20 @@ class RiskParity(AssetAllocABC):
8585
[ -1.178, -7.901, 0.503, 5.460, 1.057 ],
8686
[ 8.778, 84.954, 45.184, 1.057, 34.126 ]
8787
])/10000
88+
8889
>>> m = pf.RiskParity(cov=cov)
8990
>>> m.weight()
9091
array([0.125, 0.047, 0.083, 0.613, 0.132])
9192
>>> m._result
9293
{'err': 2.2697290741335863e-07, 'n_iter': 6}
94+
95+
>>> m = pf.RiskParity(cov=cov, budget=[0.1, 0.1, 0.2, 0.3, 0.3])
96+
>>> m.weight()
97+
array([0.077, 0.025, 0.074, 0.648, 0.176])
98+
99+
>>> m = pf.RiskParity(cov=cov, longshort=[-1, -1, 1, 1, 1])
100+
>>> m.weight()
101+
array([-0.216, -0.162, 0.182, 0.726, 0.47 ])
93102
"""
94103

95104
budget = None
@@ -111,9 +120,9 @@ def __init__(self, sigma=None, cor=None, cov=None, ret=None, budget=None, longsh
111120
if budget is None:
112121
self.budget = np.full(self.n_asset, 1 / self.n_asset)
113122
else:
114-
assert self.n_asset == budget.shape[0]
123+
assert self.n_asset == len(budget)
115124
assert np.isclose(np.sum(budget), 1)
116-
self.budget = budget
125+
self.budget = np.array(budget)
117126

118127
@classmethod
119128
def init_random(cls, n_asset=10, zero_ev=0, budget=False):
@@ -137,7 +146,6 @@ def init_random(cls, n_asset=10, zero_ev=0, budget=False):
137146
m = cls(cov=cor)
138147
return m
139148

140-
141149
def weight(self, tol=1e-6):
142150
"""
143151
Risk parity weight using the improved CCD method of Choi and Chen (2022)
@@ -174,7 +182,6 @@ def weight(self, tol=1e-6):
174182
self._result = {'err': err, 'n_iter': k}
175183
return None
176184

177-
178185
def weight_ccd_original(self, tol=1e-6):
179186
"""
180187
Risk parity weight using original CCD method of Griveau-Billion et al. (2013).
@@ -227,7 +234,6 @@ def _newton_jacobian(w, cov, bud):
227234
jac = cov + np.diag(bud / (w * w))
228235
return jac
229236

230-
231237
def weight_newton(self, tol=1e-6):
232238
"""
233239
Risk parity weight using Newton method
@@ -238,6 +244,10 @@ def weight_newton(self, tol=1e-6):
238244
239245
Returns:
240246
risk parity weight
247+
248+
References:
249+
- Spinu, F. (2013). An Algorithm for Computing Risk Parity Weights (SSRN Scholarly Paper ID 2297383). Social Science Research Network. https://doi.org/10.2139/ssrn.2297383
250+
241251
"""
242252
cor = self.cor_m
243253

0 commit comments

Comments
 (0)