Maximum Diversification
Calculate the weights of the maximum diversification portfolio: the fully invested portfolio with the highest diversification ratio, the weighted average volatility of its assets divided by its own volatility. The ratio is one for a single asset and grows as the assets move less together, so the portfolio holds the assets that diversify each other most. It needs no expected returns, and when every asset has the same Sharpe ratio it is also the maximum Sharpe ratio portfolio.
The weights maximize DR(w) = w’σ / √(w’Σw) subject to the weights summing to one and lying between the minimum and maximum weight, with σ the volatilities of the assets and Σ their annualized covariance matrix. The square of the ratio is the number of independent risk factors a long-only portfolio effectively holds.
For more information, see the following papers:
- Choueifaty, Y. and Coignard, Y. (2008). “Toward Maximum Diversification.” The Journal of Portfolio Management, 35(1), 40-51.
- Choueifaty, Y., Froidure, T. and Reynier, J. (2013). “Properties of the Most Diversified Portfolio.” Journal of Investment Strategies, 2(2), 49-70.
Also known as: most diversified portfolio, MDP, maximum diversification ratio.
Maximum Diversification in Python or via the MCP
Install the Finance Toolkit with:
pip install financetoolkit -U
Then call get_maximum_diversification_weights as shown below.
from financetoolkit import Toolkit
toolkit = Toolkit(
["AAPL", "MSFT", "JNJ", "XOM"],
api_key="FINANCIAL_MODELING_PREP_KEY",
start_date="2021-01-01",
end_date="2025-12-31",
)
toolkit.portfolio.get_maximum_diversification_weights()[
["Weight", "Volatility", "Sharpe Ratio", "Risk Contribution", "Diversification Ratio"]
]
Or, after setting up the Finance Toolkit MCP, ask:
Which weights in Apple, Microsoft, Johnson & Johnson and ExxonMobil maximized the diversification ratio, based on 2021 to 2025?
Which returns:
| Weight | Volatility | Sharpe Ratio | Risk Contribution | Diversification Ratio | |
|---|---|---|---|---|---|
| AAPL | 0.0923 | 0.2786 | 0.5727 | 0.1145 | 1 |
| MSFT | 0.2349 | 0.2572 | 0.6532 | 0.2687 | 1 |
| JNJ | 0.4194 | 0.1673 | 0.3867 | 0.3122 | 1 |
| XOM | 0.2533 | 0.2702 | 0.9522 | 0.3046 | 1 |
| Portfolio | 1 | 0.1405 | 1.043 | 1 | 1.6 |
Parameters
get_maximum_diversification_weights accepts the following parameters.
| Parameter | Type | Description | Example |
|---|---|---|---|
period | str | The frequency of the returns the covariance matrix is estimated from (daily, weekly, monthly, quarterly or yearly). Defaults to “daily”. | "weekly" |
covariance | str | The estimator of the covariance matrix: “sample” (ddof=1), “ledoit_wolf” (towards the scaled identity, Ledoit and Wolf, 2004), “ledoit_wolf_constant_correlation” (towards the average correlation, Ledoit and Wolf, 2004), “ledoit_wolf_single_factor” (towards the covariance that the benchmark as a single factor implies, Ledoit and Wolf, 2003), “oas” (Chen et al., 2010), “semicovariance” (the co-movement below a zero return, Estrada, 2007), “exponential” (recent periods weigh most, RiskMetrics) or “denoised” (the eigenvalues of the correlation matrix that random returns could produce averaged, Laloux et al., 2000). The shrinkage and denoised estimators stabilize the weights when there are many assets compared to the number of periods. Defaults to “sample”. | "sample" |
covariance_span | int | The span in periods of the “exponential” covariance; the weight of a period halves after about span / 2.9 periods. Defaults to 180. | 180 |
minimum_weight | float | dict[str, float] | The lowest weight of every asset, or per asset, e.g. {“AAPL”: 0.05} (the others keep 0); a negative value allows short positions. Defaults to 0. | 0 |
maximum_weight | float | dict[str, float] | The highest weight of every asset, or per asset, e.g. {“AAPL”: 0.3} (the others keep 1). Defaults to 1. | 1 |
sector_bounds | dict[str, tuple[float, float]] | None | The minimum and maximum total weight per sector, e.g. {“Technology”: (0, 0.4)}, with the sector of each asset from its company profile. Defaults to None. | None |
country_bounds | dict[str, tuple[float, float]] | None | The minimum and maximum total weight per country, named in full or by its two-letter code, e.g. {“United States”: (0, 0.6)}, with the country of each asset from its company profile. Defaults to None. | None |
net_exposure | float | The sum of the weights: 1 for a fully invested portfolio, 0 for a market neutral one (which needs a negative minimum_weight). Defaults to 1. | 1 |
gross_exposure | float | None | The highest sum of the absolute weights, which limits the leverage of a long-short portfolio, e.g. 1.6 for a 130/30 portfolio. Defaults to None, no limit. | None, no limit |
current_weights | dict[str, float] | None | The weights held now, e.g. {“AAPL”: 0.5, “MSFT”: 0.5} (an asset left out is not held), which the turnover is measured from; they add a Turnover column, |w_i - w0_i| per asset and its sum for the portfolio. Defaults to None, which uses the latest weights of the Portfolio the Toolkit came from when a maximum turnover or transaction cost needs them. | None, which uses the latest weights of the Portfolio the Toolkit came from when a maximum turnover or transaction cost needs them |
maximum_turnover | float | None | The highest turnover Σ |w_i - w0_i| from the current weights, e.g. 0.2 to trade at most 10% of the portfolio each way. Defaults to None, no limit. | None, no limit |
include_benchmark | bool | Whether to include the benchmark as an asset. Defaults to False. | True |
rounding | int | None | The number of decimals to round the results to. Defaults to None, which uses the Toolkit’s rounding. | 2 |