diversification_ratio#

pymc_marketing.mmm.utility.diversification_ratio(samples, budgets)[source]#

Calculate the Diversification Ratio of a portfolio to evaluate risk distribution.

The Diversification Ratio measures the effectiveness of diversification by comparing the weighted average volatility of individual assets to the overall portfolio volatility. A higher ratio indicates better diversification, as it reflects lower correlations among assets, leading to reduced portfolio risk. It provides insight into how individual asset volatilities and their correlations contribute to the overall portfolio risk.

The Diversification Ratio is calculated as:

\[DR = \frac{\sum_{i=1}^{n} w_i \cdot \sigma_i}{\sigma_p}\]

where:

  • \(w_i\) is the weight of asset \(i\)

  • \(\sigma_i\) is the volatility (standard deviation) of asset \(i\)

  • \(\sigma_p\) is the volatility of the portfolio

Parameters:
samplesXTensorVariable

2D PyTensor tensor variable where each column represents the returns of an asset.

budgetsXTensorVariable

1D PyTensor tensor variable representing the investment amounts in each asset.

Returns:
XTensorVariable

Diversification Ratio.

Raises:
ValueError

If samples is not 2D with a sample dim, if budgets is not 1D, or if the dim budgets is labelled with is not a dim of samples.

Notes

samples must have exactly two dims: sample and the asset dim that budgets is labelled with. The response distributions BudgetOptimizer passes to a utility function do not have that shape out of the box: the default response_variable is a 1D (sample,) total, and per-channel variables carry a date dim as well. Reduce over date before calling this function. The optimizer invokes the utility with keyword arguments, so a wrapper’s parameters must be named samples and budgets.

The ratio is undefined when the portfolio volatility is zero: a channel at exactly zero budget contributes zero in every sample, and a channel driven deep into saturation is numerically constant. Both give 0 / 0 for the value and an infinite gradient, which the optimizer reports as an opaque solver failure. The default bounds allow zero budgets, so pass budget_bounds with strictly positive lower bounds when optimizing for diversification.

References

  • Choueifaty, Y., & Coignard, Y. (2008). Toward Maximum Diversification. Journal of Portfolio Management.

  • Meucci, A. (2009). Managing Diversification. Risk, 22(5), 74-79.

Examples

Optimize a fitted MMM for diversification of the per-channel contribution:

from pymc_marketing.mmm.utility import diversification_ratio

optimizer = mmm.budget_optimizer(
    start_date="2025-01-06",
    end_date="2025-03-31",
    response_variable="channel_contribution",
    utility_function=lambda samples, budgets: diversification_ratio(
        samples.sum(dim="date"), budgets
    ),
)
result = optimizer.allocate_budget(
    total_budget=100.0,
    budget_bounds={channel: (1.0, 100.0) for channel in mmm.channel_columns},
)