You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Although much development has been made in the subject, more than half a century later,
224
+
Although much development has been made in the subject, more than half a century later,
188
225
Markowitz's core ideas are still fundamentally important and see daily use in many portfolio management firms.
189
-
The main drawback of mean-variance optimization is that the theoretical
226
+
The main drawback of mean-variance optimization is that the theoretical
190
227
treatment requires knowledge of the expected returns and the future risk-characteristics (covariance) of the assets. Obviously, if we knew the expected returns of a stock life would be much easier, but the whole game is that stock returns are notoriously hard to forecast. As a substitute, we can derive estimates of the expected return and covariance based on historical data – though we do lose the theoretical guarantees provided by Markowitz, the closer our estimates are to the real values, the better our portfolio will be.
191
228
192
229
Thus this project provides four major sets of functionality (though of course they are intimately related)
@@ -254,32 +291,94 @@ The covariance matrix encodes not just the volatility of an asset, but also how
254
291
255
292
- Long/short: by default all of the mean-variance optimization methods in PyPortfolioOpt are long-only, but they can be initialised to allow for short positions by changing the weight bounds:
256
293
294
+
<!--pytest-codeblocks:cont-->
295
+
257
296
```python
258
297
ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1))
259
298
```
260
299
300
+
```result
301
+
```
302
+
261
303
- Market neutrality: for the `efficient_risk` and `efficient_return` methods, PyPortfolioOpt provides an option to form a market-neutral portfolio (i.e weights sum to zero). This is not possible for the max Sharpe portfolio and the min volatility portfolio because in those cases because they are not invariant with respect to leverage. Market neutrality requires negative weights:
262
304
305
+
<!--pytest-codeblocks:cont-->
306
+
263
307
```python
264
308
ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1))
for name, value in ef.efficient_return(target_return=0.2, market_neutral=True).items():
310
+
print(f"{name}: {value:.4f}")
311
+
```
312
+
313
+
```result
314
+
GOOG: 0.0747
315
+
AAPL: 0.0532
316
+
FB: 0.0664
317
+
BABA: 0.0116
318
+
AMZN: 0.0518
319
+
GE: -0.0595
320
+
AMD: -0.0679
321
+
WMT: -0.0817
322
+
BAC: -0.1413
323
+
GM: -0.1402
324
+
T: -0.1371
325
+
UAA: 0.0003
326
+
SHLD: -0.0706
327
+
XOM: -0.0775
328
+
RRC: -0.0510
329
+
BBY: 0.0349
330
+
MA: 0.3758
331
+
PFE: 0.1112
332
+
JPM: 0.0141
333
+
SBUX: 0.0330
266
334
```
267
335
268
336
- Minimum/maximum position size: it may be the case that you want no security to form more than 10% of your portfolio. This is easy to encode:
269
337
338
+
<!--pytest-codeblocks:cont-->
339
+
270
340
```python
271
341
ef = EfficientFrontier(mu, S, weight_bounds=(0, 0.1))
272
342
```
273
343
344
+
```result
345
+
```
274
346
One issue with mean-variance optimization is that it leads to many zero-weights. While these are
275
347
"optimal" in-sample, there is a large body of research showing that this characteristic leads
276
348
mean-variance portfolios to underperform out-of-sample. To that end, I have introduced an
277
349
objective function that can reduce the number of negligible weights for any of the objective functions. Essentially, it adds a penalty (parameterised by `gamma`) on small weights, with a term that looks just like L2 regularisation in machine learning. It may be necessary to try several `gamma` values to achieve the desired number of non-negligible weights. For the test portfolio of 20 securities, `gamma ~ 1` is sufficient
@@ -290,14 +389,42 @@ posterior estimate. This results in much better estimates of expected returns th
290
389
the mean historical return. Check out the [docs](https://pyportfolioopt.readthedocs.io/en/latest/BlackLitterman.html) for a discussion of the theory, as well as advice
291
390
on formatting inputs.
292
391
392
+
<!--pytest-codeblocks:cont-->
393
+
293
394
```python
395
+
from pypfopt import risk_models, BlackLittermanModel
0 commit comments