Skip to content

Commit 9f4aef1

Browse files
committed
consistent use of "optimization"
1 parent b34179b commit 9f4aef1

37 files changed

+209
-211
lines changed

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Please refer to the roadmap for a list of areas that I think PyPortfolioOpt coul
44
from. In addition, the following is always welcome::
55

66
- 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).
88
- 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.
99

1010
## Guidelines
@@ -37,7 +37,7 @@ If you have questions unrelated to the project, drop me an email – contact det
3737

3838
## Bugs/issues
3939

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:
4141

4242
- Descriptive title so that other users can see the existing issues
4343
- Operating system, python version, and python distribution (optional).

README.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626

2727
<!-- content -->
2828

29-
PyPortfolioOpt is a library that implements portfolio optimisation methods, including
30-
classical mean-variance optimisation techniques and Black-Litterman allocation, as well as more
29+
PyPortfolioOpt is a library that implements portfolio optimization methods, including
30+
classical mean-variance optimization techniques and Black-Litterman allocation, as well as more
3131
recent developments in the field like shrinkage and Hierarchical Risk Parity, along with
3232
some novel experimental features like exponentially-weighted covariance matrices.
3333

@@ -49,14 +49,14 @@ Head over to the [documentation on ReadTheDocs](https://pyportfolioopt.readthedo
4949
- [For development](#for-development)
5050
- [A quick example](#a-quick-example)
5151
- [What's new](#whats-new)
52-
- [An overview of classical portfolio optimisation methods](#an-overview-of-classical-portfolio-optimisation-methods)
52+
- [An overview of classical portfolio optimization methods](#an-overview-of-classical-portfolio-optimization-methods)
5353
- [Features](#features)
5454
- [Expected returns](#expected-returns)
5555
- [Risk models (covariance)](#risk-models-covariance)
5656
- [Objective functions](#objective-functions)
5757
- [Adding constraints or different objectives](#adding-constraints-or-different-objectives)
5858
- [Black-Litterman allocation](#black-litterman-allocation)
59-
- [Other optimisers](#other-optimisers)
59+
- [Other optimizers](#other-optimizers)
6060
- [Advantages over existing implementations](#advantages-over-existing-implementations)
6161
- [Project principles and design decisions](#project-principles-and-design-decisions)
6262
- [Testing](#testing)
@@ -124,7 +124,7 @@ df = pd.read_csv("tests/resources/stock_prices.csv", parse_dates=True, index_col
124124
mu = expected_returns.mean_historical_return(df)
125125
S = risk_models.sample_cov(df)
126126

127-
# Optimise for maximal Sharpe ratio
127+
# Optimize for maximal Sharpe ratio
128128
ef = EfficientFrontier(mu, S)
129129
raw_weights = ef.max_sharpe()
130130
cleaned_weights = ef.clean_weights()
@@ -206,23 +206,23 @@ As of v1.2.0:
206206
new plots. All other plotting functions (scattered in different classes) have been retained,
207207
but are now deprecated.
208208

209-
## An overview of classical portfolio optimisation methods
209+
## An overview of classical portfolio optimization methods
210210

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**.
212212

213213
<center>
214214
<img src="https://github.com/robertmartin8/PyPortfolioOpt/blob/master/media/efficient_frontier_white.png" style="width:60%;"/>
215215
</center>
216216

217217
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.
219219

220220
Thus this project provides four major sets of functionality (though of course they are intimately related)
221221

222222
- Estimates of expected returns
223223
- 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.
226226

227227
A key design goal of PyPortfolioOpt is **modularity** – the user should be able to swap in their
228228
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
253253
- an unbiased estimate of the covariance matrix
254254
- relatively easy to compute
255255
- 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.
257257
- Semicovariance: a measure of risk that focuses on downside variation.
258258
- Exponential covariance: an improvement over sample covariance that gives more weight to recent data
259259
- 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
280280

281281
### Adding constraints or different objectives
282282

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:
284284

285285
```python
286286
ef = EfficientFrontier(mu, S, weight_bounds=(-1, 1))
@@ -299,7 +299,7 @@ ef.efficient_return(target_return=0.2, market_neutral=True)
299299
ef = EfficientFrontier(mu, S, weight_bounds=(0, 0.1))
300300
```
301301

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
303303
"optimal" in-sample, there is a large body of research showing that this characteristic leads
304304
mean-variance portfolios to underperform out-of-sample. To that end, I have introduced an
305305
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)
328328
ef.max_sharpe()
329329
```
330330

331-
### Other optimisers
331+
### Other optimizers
332332

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:
334334

335-
- Mean-semivariance optimisation
336-
- Mean-CVaR optimisation
335+
- Mean-semivariance optimization
336+
- Mean-CVaR optimization
337337
- Hierarchical Risk Parity, using clustering algorithms to choose uncorrelated assets
338338
- Markowitz's critical line algorithm (CLA)
339339

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.
341341

342342
## Advantages over existing implementations
343343

@@ -352,10 +352,10 @@ Please refer to the [documentation](https://pyportfolioopt.readthedocs.io/en/lat
352352

353353
## Project principles and design decisions
354354

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
356356
with the user's proprietary improvements.
357357
- 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
359359
applied to real asset prices.
360360
- Everything that has been implemented should be tested.
361361
- Inline documentation is good: dedicated (separate) documentation is better.

cookbook/1-RiskReturnModels.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@
240240
"cell_type": "markdown",
241241
"metadata": {},
242242
"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."
244244
]
245245
},
246246
{

cookbook/2-Mean-Variance-Optimisation.ipynb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
"cell_type": "markdown",
55
"metadata": {},
66
"source": [
7-
"# Mean-variance optimisation\n",
7+
"# Mean-variance optimization\n",
88
"\n",
99
"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",
1010
"\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",
1212
"\n",
1313
"Some of the things we cover:\n",
1414
"\n",
@@ -827,7 +827,7 @@
827827
"source": [
828828
"## Long/short min variance\n",
829829
"\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."
831831
]
832832
},
833833
{
@@ -1353,7 +1353,7 @@
13531353
"cell_type": "markdown",
13541354
"metadata": {},
13551355
"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",
13571357
"\n",
13581358
"- 10% of the portfolio in AMZN\n",
13591359
"- Less than 5% of my portfolio in TSLA"
@@ -1564,7 +1564,7 @@
15641564
"cell_type": "markdown",
15651565
"metadata": {},
15661566
"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."
15681568
]
15691569
},
15701570
{
@@ -1837,7 +1837,7 @@
18371837
"cell_type": "markdown",
18381838
"metadata": {},
18391839
"source": [
1840-
"## Efficient semi-variance optimisation\n",
1840+
"## Efficient semi-variance optimization\n",
18411841
"\n",
18421842
"In this example, we will minimise the portfolio semivariance (i.e downside volatility) subject to a return constraint (target 20%).\n",
18431843
"\n",
@@ -1927,7 +1927,7 @@
19271927
"cell_type": "markdown",
19281928
"metadata": {},
19291929
"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."
19311931
]
19321932
},
19331933
{
@@ -2001,7 +2001,7 @@
20012001
"cell_type": "markdown",
20022002
"metadata": {},
20032003
"source": [
2004-
"## Efficient CVaR optimisation\n",
2004+
"## Efficient CVaR optimization\n",
20052005
"\n",
20062006
"In this example, we will find the portfolio that maximises return subject to a CVaR constraint.\n",
20072007
"\n",
@@ -2423,7 +2423,7 @@
24232423
"cell_type": "markdown",
24242424
"metadata": {},
24252425
"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:"
24272427
]
24282428
},
24292429
{

0 commit comments

Comments
 (0)