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
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ Please refer to the roadmap for a list of areas that I think PyPortfolioOpt coul
4
4
from. In addition, the following is always welcome::
5
5
6
6
- Improve performance of existing code (but not at the cost of readability) – are there any nice numpy tricks I've missed?
7
-
- Add new optimisation objective functions. For example, if you think that the best performance metric has not been included, write it into a function (or suggest it in [Issues](https://github.com/robertmartin8/PyPortfolioOpt/issues) and I will have a go).
7
+
- Add new optimization objective functions. For example, if you think that the best performance metric has not been included, write it into a function (or suggest it in [Issues](https://github.com/robertmartin8/PyPortfolioOpt/issues) and I will have a go).
8
8
- Help me write more tests! If you are someone learning about quant finance and/or unit testing in python, what better way to practice than to write some tests on an open-source project! Feel free to check for edge cases, or test performance on a dataset with more stocks.
9
9
10
10
## Guidelines
@@ -37,7 +37,7 @@ If you have questions unrelated to the project, drop me an email – contact det
37
37
38
38
## Bugs/issues
39
39
40
-
If you find any bugs or the portfolio optimisation is not working as expected, feel free to [raise an issue](https://github.com/robertmartin8/PyPortfolioOpt/issues). I would ask that you provide the following information in the issue:
40
+
If you find any bugs or the portfolio optimization is not working as expected, feel free to [raise an issue](https://github.com/robertmartin8/PyPortfolioOpt/issues). I would ask that you provide the following information in the issue:
41
41
42
42
- Descriptive title so that other users can see the existing issues
43
43
- Operating system, python version, and python distribution (optional).
new plots. All other plotting functions (scattered in different classes) have been retained,
207
207
but are now deprecated.
208
208
209
-
## An overview of classical portfolio optimisation methods
209
+
## An overview of classical portfolio optimization methods
210
210
211
-
Harry Markowitz's 1952 paper is the undeniable classic, which turned portfolio optimisation from an art into a science. The key insight is that by combining assets with different expected returns and volatilities, one can decide on a mathematically optimal allocation which minimises the risk for a target return – the set of all such optimal portfolios is referred to as the **efficient frontier**.
211
+
Harry Markowitz's 1952 paper is the undeniable classic, which turned portfolio optimization from an art into a science. The key insight is that by combining assets with different expected returns and volatilities, one can decide on a mathematically optimal allocation which minimises the risk for a target return – the set of all such optimal portfolios is referred to as the **efficient frontier**.
Although much development has been made in the subject, more than half a century later, Markowitz's core ideas are still fundamentally important and see daily use in many portfolio management firms.
218
-
The main drawback of mean-variance optimisation is that the theoretical 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.
218
+
The main drawback of mean-variance optimization is that the theoretical 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.
219
219
220
220
Thus this project provides four major sets of functionality (though of course they are intimately related)
221
221
222
222
- Estimates of expected returns
223
223
- Estimates of risk (i.e covariance of asset returns)
224
-
- Objective functions to be optimised
225
-
-Optimisers.
224
+
- Objective functions to be optimized
225
+
-Optimizers.
226
226
227
227
A key design goal of PyPortfolioOpt is **modularity** – the user should be able to swap in their
228
228
components while still making use of the framework that PyPortfolioOpt provides.
@@ -253,7 +253,7 @@ The covariance matrix encodes not just the volatility of an asset, but also how
253
253
- an unbiased estimate of the covariance matrix
254
254
- relatively easy to compute
255
255
- the de facto standard for many years
256
-
- however, it has a high estimation error, which is particularly dangerous in mean-variance optimisation because the optimiser is likely to give excess weight to these erroneous estimates.
256
+
- however, it has a high estimation error, which is particularly dangerous in mean-variance optimization because the optimizer is likely to give excess weight to these erroneous estimates.
257
257
- Semicovariance: a measure of risk that focuses on downside variation.
258
258
- Exponential covariance: an improvement over sample covariance that gives more weight to recent data
259
259
- Covariance shrinkage: techniques that involve combining the sample covariance matrix with a structured estimator, to reduce the effect of erroneous weights. PyPortfolioOpt provides wrappers around the efficient vectorised implementations provided by `sklearn.covariance`.
@@ -280,7 +280,7 @@ The covariance matrix encodes not just the volatility of an asset, but also how
280
280
281
281
### Adding constraints or different objectives
282
282
283
-
- Long/short: by default all of the mean-variance optimisation methods in PyPortfolioOpt are long-only, but they can be initialised to allow for short positions by changing the weight bounds:
283
+
- 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:
284
284
285
285
```python
286
286
ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1))
ef = EfficientFrontier(mu, S, weight_bounds=(0, 0.1))
300
300
```
301
301
302
-
One issue with mean-variance optimisation is that it leads to many zero-weights. While these are
302
+
One issue with mean-variance optimization is that it leads to many zero-weights. While these are
303
303
"optimal" in-sample, there is a large body of research showing that this characteristic leads
304
304
mean-variance portfolios to underperform out-of-sample. To that end, I have introduced an
305
305
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
@@ -328,16 +328,16 @@ ef = EfficientFrontier(rets, S)
328
328
ef.max_sharpe()
329
329
```
330
330
331
-
### Other optimisers
331
+
### Other optimizers
332
332
333
-
The features above mostly pertain to solving mean-variance optimisation problems via quadratic programming (though this is taken care of by `cvxpy`). However, we offer different optimisers as well:
333
+
The features above mostly pertain to solving mean-variance optimization problems via quadratic programming (though this is taken care of by `cvxpy`). However, we offer different optimizers as well:
334
334
335
-
- Mean-semivariance optimisation
336
-
- Mean-CVaR optimisation
335
+
- Mean-semivariance optimization
336
+
- Mean-CVaR optimization
337
337
- Hierarchical Risk Parity, using clustering algorithms to choose uncorrelated assets
338
338
- Markowitz's critical line algorithm (CLA)
339
339
340
-
Please refer to the [documentation](https://pyportfolioopt.readthedocs.io/en/latest/OtherOptimisers.html) for more.
340
+
Please refer to the [documentation](https://pyportfolioopt.readthedocs.io/en/latest/OtherOptimizers.html) for more.
341
341
342
342
## Advantages over existing implementations
343
343
@@ -352,10 +352,10 @@ Please refer to the [documentation](https://pyportfolioopt.readthedocs.io/en/lat
352
352
353
353
## Project principles and design decisions
354
354
355
-
- It should be easy to swap out individual components of the optimisation process
355
+
- It should be easy to swap out individual components of the optimization process
356
356
with the user's proprietary improvements.
357
357
- Usability is everything: it is better to be self-explanatory than consistent.
358
-
- There is no point in portfolio optimisation unless it can be practically
358
+
- There is no point in portfolio optimization unless it can be practically
359
359
applied to real asset prices.
360
360
- Everything that has been implemented should be tested.
361
361
- Inline documentation is good: dedicated (separate) documentation is better.
Copy file name to clipboardExpand all lines: cookbook/1-RiskReturnModels.ipynb
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -240,7 +240,7 @@
240
240
"cell_type": "markdown",
241
241
"metadata": {},
242
242
"source": [
243
-
"The exponential moving average is marginally better than the others, but the improvement is almost unnoticeable. We also note that the mean absolute deviations are above 25%, meaning that if your expected annual returns are 10%, on average the realised annual return could be anywhere from a 15% loss to a 35% gain. This is a massive range, and gives some context to the advice in the docs suggesting that you optimise without providing an estimate of returns."
243
+
"The exponential moving average is marginally better than the others, but the improvement is almost unnoticeable. We also note that the mean absolute deviations are above 25%, meaning that if your expected annual returns are 10%, on average the realised annual return could be anywhere from a 15% loss to a 35% gain. This is a massive range, and gives some context to the advice in the docs suggesting that you optimize without providing an estimate of returns."
Copy file name to clipboardExpand all lines: cookbook/2-Mean-Variance-Optimisation.ipynb
+9-9Lines changed: 9 additions & 9 deletions
Original file line number
Diff line number
Diff line change
@@ -4,11 +4,11 @@
4
4
"cell_type": "markdown",
5
5
"metadata": {},
6
6
"source": [
7
-
"# Mean-variance optimisation\n",
7
+
"# Mean-variance optimization\n",
8
8
"\n",
9
9
"In this cookbook recipe, we work on several examples demonstrating PyPortfolioOpt's mean-variance capabilities. I will discuss what I think should be your \"default\" options, based on my experience in optimising portfolios.\n",
10
10
"\n",
11
-
"To start, you need a list of tickers. Some people just provide the whole universe of stocks, but I don't think this is a good idea - portfolio optimisation is quite different from asset selection. I would suggest anywhere from 10-50 stocks as a starting point.\n",
11
+
"To start, you need a list of tickers. Some people just provide the whole universe of stocks, but I don't think this is a good idea - portfolio optimization is quite different from asset selection. I would suggest anywhere from 10-50 stocks as a starting point.\n",
12
12
"\n",
13
13
"Some of the things we cover:\n",
14
14
"\n",
@@ -827,7 +827,7 @@
827
827
"source": [
828
828
"## Long/short min variance\n",
829
829
"\n",
830
-
"In this section, we construct a long/short portfolio with the objective of minimising variance. There is a good deal of research that demonstrates that these global-minimum variance (GMV) portfolios outperform mean-variance optimised portfolios."
830
+
"In this section, we construct a long/short portfolio with the objective of minimising variance. There is a good deal of research that demonstrates that these global-minimum variance (GMV) portfolios outperform mean-variance optimized portfolios."
831
831
]
832
832
},
833
833
{
@@ -1353,7 +1353,7 @@
1353
1353
"cell_type": "markdown",
1354
1354
"metadata": {},
1355
1355
"source": [
1356
-
"We then set up the optimiser and add our constraints. We can use `ef.add_objective()` to add other constraints. For example, let's say that in addition to the above sector constraints, I specifically want:\n",
1356
+
"We then set up the optimizer and add our constraints. We can use `ef.add_objective()` to add other constraints. For example, let's say that in addition to the above sector constraints, I specifically want:\n",
1357
1357
"\n",
1358
1358
"- 10% of the portfolio in AMZN\n",
1359
1359
"- Less than 5% of my portfolio in TSLA"
@@ -1564,7 +1564,7 @@
1564
1564
"cell_type": "markdown",
1565
1565
"metadata": {},
1566
1566
"source": [
1567
-
"While this portfolio seems like it meets our objectives, we might be worried by the fact that a lot of the tickers have been assigned zero weight. In effect, the optimiser is \"overfitting\" to the data you have provided -- you are much more likely to get better results by enforcing some level of diversification. One way of doing this is to use **L2 regularisation** – essentially, adding a penalty on the number of near-zero weights."
1567
+
"While this portfolio seems like it meets our objectives, we might be worried by the fact that a lot of the tickers have been assigned zero weight. In effect, the optimizer is \"overfitting\" to the data you have provided -- you are much more likely to get better results by enforcing some level of diversification. One way of doing this is to use **L2 regularisation** – essentially, adding a penalty on the number of near-zero weights."
1568
1568
]
1569
1569
},
1570
1570
{
@@ -1837,7 +1837,7 @@
1837
1837
"cell_type": "markdown",
1838
1838
"metadata": {},
1839
1839
"source": [
1840
-
"## Efficient semi-variance optimisation\n",
1840
+
"## Efficient semi-variance optimization\n",
1841
1841
"\n",
1842
1842
"In this example, we will minimise the portfolio semivariance (i.e downside volatility) subject to a return constraint (target 20%).\n",
1843
1843
"\n",
@@ -1927,7 +1927,7 @@
1927
1927
"cell_type": "markdown",
1928
1928
"metadata": {},
1929
1929
"source": [
1930
-
"However, this solution is not truly optimal in mean-semivariance space. To do the optimisation properly, we must use the `EfficientSemivariance` class. This requires us to first compute the returns and drop NaNs."
1930
+
"However, this solution is not truly optimal in mean-semivariance space. To do the optimization properly, we must use the `EfficientSemivariance` class. This requires us to first compute the returns and drop NaNs."
1931
1931
]
1932
1932
},
1933
1933
{
@@ -2001,7 +2001,7 @@
2001
2001
"cell_type": "markdown",
2002
2002
"metadata": {},
2003
2003
"source": [
2004
-
"## Efficient CVaR optimisation\n",
2004
+
"## Efficient CVaR optimization\n",
2005
2005
"\n",
2006
2006
"In this example, we will find the portfolio that maximises return subject to a CVaR constraint.\n",
2007
2007
"\n",
@@ -2423,7 +2423,7 @@
2423
2423
"cell_type": "markdown",
2424
2424
"metadata": {},
2425
2425
"source": [
2426
-
"As per the docs, *before* we call any optimisation function, we should pass this to the plotting module:"
2426
+
"As per the docs, *before* we call any optimization function, we should pass this to the plotting module:"
0 commit comments