Equivalent Normal Monte Carlo Methods for Portfolio Returns
Summary
The document explains two ways to simulate the return of a fixed-weight portfolio under a normal-return assumption. One method samples directly from a univariate normal distribution using the portfolio’s expected return and variance. The other draws asset returns jointly from a multivariate normal distribution, then combines them using the portfolio weights.
For the joint simulation, the answer describes generating independent standard normal draws and transforming them with a factorization of the asset covariance matrix, such as a Cholesky factor. The resulting asset-return samples should have the specified means and covariance, and their weighted portfolio returns should converge to the same mean and variance as direct portfolio sampling. The equivalence follows because a linear combination of jointly normal asset returns is normally distributed. This conclusion depends on fixed weights and correctly specified Gaussian inputs; it does not address non-normal returns, changing weights, or other real-world departures from the assumptions.
Key ideas
- Fixed portfolio weights imply portfolio returns are a linear combination of asset returns.
- A multivariate normal simulation can encode asset means and cross-asset covariances.
- A covariance factorization transforms independent normal draws into correlated asset-return draws.
- Under Gaussian assumptions, direct portfolio sampling and weighted asset sampling yield the same portfolio distribution.
Tags
Full text
# Sample from aggregate portfolio distribution versus individual asset distributions
# Sample from aggregate portfolio distribution versus individual asset distributions
Suppose I have three assets $x_1,x_2,x_3$ in a portfolio with weights $W=\begin{bmatrix} w_1 \\ w_2 \\ w_3 \end{bmatrix} $, expected returns $R=\begin{bmatrix} \mu_1 \\ \mu_2 \\ \mu_3 \end{bmatrix}$, and a covariance matrix $V$.
The expected return of my portfolio is $\mu_p=W^TR$ and the variance of my portfolio is $\sigma^2_p=W^TVW$.
I would like to run Monte Carlo simulations on my portfolio using a normal distribution.
I can do this either by:
- Sampling from the distribution of portfolio returns $N(\mu_p,\sigma^2_p)$.
- Sample from the three individual asset returns and use those three returns to compute my overall portfolio return.
First, how would I accomplish the second approach (would I be sampling from a multivariate normal distribution)?
Second, are these two approaches equivalent as long as I assume that the weights $W$ of my portfolio remain the same?
## Answer by Sebapi (score 3, accepted)
https://quant.stackexchange.com/a/42751
For the first case, you would directly sample $n$ random normals $x$ and compute: $$R^p_i = \mu_p + \sigma_p x_i, i \in [1,n]$$
For the second case, you can sample $n$ x $3$ independent normals, compute the Cholesky decomposition matrix $C$ of $V$, which is the matrix $C$ such that $V=C^t C$, and get $n$ samples of vectors $X$ of size 3.
The return $R_i$ for random draw $i$ is given by: $$R_i = \mu_p + C . X_i, i \in [1,n]$$ You can check for high values of $n$ the convergence towards the limit values: $$E(R_i) = R$$ $$Cov(R_i) = V$$ The portfolio return is then computed as: $$R^p_i = W.T R_i$$ and you can check it converges towards the same mean and variance $\mu_p$, $\sigma_p^2$ for a large enough $n$.
The two approaches are mathematically equivalent as a linear combination of independent normals is normally distributed. This works so long as the random normal variables generated are iid gaussian normals.
With numpy, iid normals can be generated with np.random.normal. As pointed out below, np.random.multivariate_normal can be used to generate the multivariate gaussian vector.
## Answer by TomDecimus (score 0)
https://quant.stackexchange.com/a/42755
Basically what @sebapi said. "The two approaches are equivalent so long as the random normal variables generated are iid gaussian normals."
Q: How does this compare to using docs.scipy.org/doc/numpy-1.15.1/reference/generated/…?
A: You might use scipy.stats.multivariate_normal (rv = multivariate_normal(mean=None, cov=1, allow_singular=False))Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.