Entropy Pooling
Meucci's framework for blending views with market-implied probabilities
Entropy pooling lets you take a prior distribution (e.g., historical returns or market-implied probabilities) and tilt it toward your views while staying as close to the original as possible. It solves a convex optimization that minimizes KL divergence between the posterior and prior, subject to your view constraints. The result is a new set of scenario probabilities you can feed into any portfolio optimizer.
API
Core function
python
# prior_probs: (S,) array of scenario probabilities summing to 1
# view_matrix: (K, S) matrix encoding K linear view constraints
# view_bounds: (K,) array of view targets
posterior = hz.entropy_pool(prior_probs, view_matrix, view_bounds)
posterior.probabilities # (S,) re-weighted scenario probabilities
posterior.kl_divergence # KL(posterior || prior)
posterior.effective_n # effective number of scenarios (entropy-based)
Moments from the posterior
python
# scenarios: (S, N) matrix of N asset returns across S scenarios
mu = hz.posterior_mean(scenarios, posterior.probabilities)
cov = hz.posterior_covariance(scenarios, posterior.probabilities)
Equality and inequality views
python
import numpy as np
S = 1000 # scenarios
N = 3 # assets
scenarios = np.random.randn(S, N) * 0.02 # simulated returns
prior = np.ones(S) / S # equal-weighted prior
# View 1 (equality): "expected return of asset 0 = 0.5%"
H_eq = scenarios[:, 0].reshape(1, -1)
h_eq = np.array([0.005])
# View 2 (inequality): "expected return of asset 1 > 0.2%"
# Encode as equality on a slack variable, or use the inequality interface:
posterior = hz.entropy_pool(
prior_probs=prior,
view_matrix=H_eq,
view_bounds=h_eq,
)
How it works
Given prior probabilities p and view constraints Hp' = h, entropy pooling finds posterior p' by solving:
minimize KL(p' || p) = sum(p'_s * ln(p'_s / p_s))
subject to H @ p' = h
sum(p') = 1
p' >= 0
The dual problem is unconstrained and low-dimensional (K variables for K views), so it solves quickly even with thousands of scenarios.
Example: tilting election probabilities
python
# 500 Monte Carlo scenarios for 3 prediction markets
scenarios = np.random.randn(500, 3) * 0.05
prior = np.ones(500) / 500
# Your view: market 0 will return +3% on average (you think the odds are mispriced)
H = scenarios[:, 0].reshape(1, -1)
h = np.array([0.03])
post = hz.entropy_pool(prior, H, h)
# New moments reflecting your view
mu = hz.posterior_mean(scenarios, post.probabilities)
cov = hz.posterior_covariance(scenarios, post.probabilities)
print(f"Prior mean[0]: {scenarios[:, 0].mean():.4f}")
print(f"Posterior mean[0]: {mu[0]:.4f}") # should be ~0.03
When to use
- View blending: you have a statistical model (prior) but also a qualitative view. Entropy pooling merges them without discarding either.
- Stress testing: tilt the distribution so that a crash scenario has higher probability, then re-optimize the portfolio under the stressed distribution.
- Cross-asset allocation: start from market-implied returns and overlay your edge estimates for specific markets.