where $\sigma_i=$ std dev of $r_i$ and $\rho$ is the correlation of $r_1$ and $r_2$.
Lower correlation implies lower portfolio risk!
mu1, mu2 = 0.06, 0.1
sigma1, sigma2 = 0.2, 0.3
rho = 0.3
w1, w2 = 0.4, 0.6
import numpy as np
mn = w1*mu1 + w2*mu2
var = w1**2*sigma1**2 + w2**2*sigma2**2 + 2*w1*w2*rho*sigma1*sigma2
print(f"mean portfolio return is {mn:.2%}")
print(f"std dev of portfolio return is {np.sqrt(var):.2%}")
mean portfolio return is 8.40% std dev of portfolio return is 21.78%
cov = [
[sigma1**2, rho*sigma1*sigma2],
[rho*sigma1*sigma2, sigma2**2]
]
from scipy.stats import multivariate_normal as multinorm
rets = multinorm.rvs(
mean=[mu1, mu2],
cov=cov,
size=1000000
)
rp = w1*rets[:,0] + w2*rets[:,1]
print(f"simulated mean is {np.mean(rp):.2%}")
print(f"simulated std dev is {np.std(rp):.2%}")
simulated mean is 8.39% simulated std dev is 21.77%
# example
w = np.array([0.2, 0.2, 0.4])
sigma1, sigma2, sigma3 = 0.2, 0.3, 0.1
rho12, rho13, rho23 = 0.3, 0.5, 0.4
cov = np.array([
[sigma1**2, rho12*sigma1*sigma2, rho13*sigma1*sigma3],
[rho12*sigma1*sigma2, sigma2**2, rho23*sigma2*sigma3],
[rho13*sigma1*sigma3, rho23*sigma2*sigma3, sigma3**2]
])
stdev = np.sqrt(w @ cov @ w)
print(f"portfolio std dev is {stdev:.2%}")
portfolio std dev is 10.84%
# continuing prior example
rf = 0.04
mu1, mu2, mu3 = 0.1, 0.12, 0.08
mu = np.array([mu1, mu2, mu3])
port_mean = w @ mu + (1-np.sum(w))*rf
print(f"portfolio mean is {port_mean:.2%}")
portfolio mean is 8.40%
import yfinance as yf
tickers = ["SPY", "IEF", "GLD"]
prices = yf.download(tickers, start="1970-01-01")["Adj Close"]
rets = prices.pct_change().dropna()
rets.head(3)
[*********************100%%**********************] 3 of 3 completed
GLD | IEF | SPY | |
---|---|---|---|
Date | |||
2004-11-19 | 0.009013 | -0.005480 | -0.011117 |
2004-11-22 | 0.003796 | 0.000704 | 0.004769 |
2004-11-23 | -0.004449 | -0.000938 | 0.001526 |
rets.corr()
GLD | IEF | SPY | |
---|---|---|---|
GLD | 1.000000 | 0.208371 | 0.049425 |
IEF | 0.208371 | 1.000000 | -0.320228 |
SPY | 0.049425 | -0.320228 | 1.000000 |
print(f"annualized means are \n{252*rets.mean()}")
print(f"\nannualized std devs are \n{np.sqrt(252)*rets.std()}")
annualized means are GLD 0.090313 IEF 0.031442 SPY 0.106698 dtype: float64 annualized std devs are GLD 0.176744 IEF 0.068225 SPY 0.193171 dtype: float64
w = np.array([0.2, 0.3, 0.5])
mean = w @ rets.mean()
var = w @ rets.cov() @ w
stdev = np.sqrt(var)
print(f"annualized mean portfolio return is {252*mean:.2%}")
print(f"annualized std dev is {np.sqrt(252)*stdev:.2%}")
annualized mean portfolio return is 8.08% annualized std dev is 10.18%