import numpy_financial as npf
spending = 100000
num_spending_years = 25
num_saving_years = 30
r = 0.06
pv_spending_at_retirement = npf.pv(
rate=r,
nper=num_spending_years,
pmt=-spending
)
print(f"We need to have ${pv_spending_at_retirement:,.0f} at retirement.")
We need to have $1,278,336 at retirement.
savings = - npf.pmt(
pv=pv_spending_at_retirement / (1+r)**num_saving_years,
rate=r,
fv=0,
nper=num_saving_years
)
print(f"We need to save ${savings:,.0f} each year.")
We need to save $16,170 each year.
savings = - npf.pmt(
pv=0,
rate=r,
fv=pv_spending_at_retirement,
nper=num_saving_years
)
print(f"We need to save ${savings:,.0f} each year.")
We need to save $16,170 each year.
import numpy as np
g = 0.03
m = num_saving_years
factors = (1+g) ** np.arange(m)
factors *= (1+r) ** np.arange(m-1, -1, -1)
x = pv_spending_at_retirement / np.sum(factors)
print(f"We need to save ${x:,.0f} each year.")
We need to save $11,564 each year.
mean = 0.1
stdev = 0.15
np.random.seed(0)
np.random.normal(loc=mean, scale=stdev)
0.36460785189514955
n = 10
np.random.seed(0)
rets = np.random.normal(
loc=mean,
scale=stdev,
size=n
)
rets
array([ 0.36460785, 0.16002358, 0.2468107 , 0.43613398, 0.3801337 , -0.04659168, 0.24251326, 0.07729642, 0.08451717, 0.16158978])
print(f"$1 would grow to ${np.prod(1+rets): .3f}")
print(f"the total return is {np.prod(1+rets)-1: .1%}")
$1 would grow to $ 6.289 the total return is 528.9%
num_prds = 10
num_sims = 5
np.random.seed(0)
rets = np.random.normal(
loc=mean,
scale=stdev,
size=(num_prds, num_sims)
)
np.prod((1+rets), axis=0)
array([1.30568504, 4.01010011, 2.92173927, 2.62512839, 4.17660966])
num_sims = 1000
np.random.seed(0)
rets = np.random.normal(
loc=mean,
scale=stdev,
size=(num_prds, num_sims)
)
compound_rets = np.prod((1+rets), axis=0) - 1
import pandas as pd
pd.Series(compound_rets).describe()
count 1000.000000 mean 1.525291 std 1.123597 min -0.464922 25% 0.737312 50% 1.330335 75% 2.061266 max 7.906556 dtype: float64
import plotly.express as px
px.histogram(compound_rets)
# central moments
np.random.seed(0)
x = np.random.normal(size=100000)
mean = np.mean(x)
variance = np.mean(
(x-mean)**2
)
third = np.mean(
(x-mean)**3
)
fourth = np.mean(
(x-mean)**4
)
print(f"mean={mean:.2f}, variance={variance:.2f}, third={third:.2f}, fourth={fourth:.2f}")
mean=0.00, variance=0.99, third=-0.01, fourth=3.00
# standardized central moments
stdev = np.sqrt(variance)
skewness = third / stdev**3
kurtosis = fourth / stdev**4
print(f"stdev={stdev:.2f}, skewness={skewness:.2f}, kurtosis={kurtosis:.2f}")
stdev=1.00, skewness=-0.01, kurtosis=3.03
For any normal distribution, skewness = 0 and kurtosis = 3.
# central moments
y = np.exp(x)
mean = np.mean(y)
variance = np.mean(
(y-mean)**2
)
third = np.mean(
(y-mean)**3
)
fourth = np.mean(
(y-mean)**4
)
print(f"mean={mean:.2f}, variance={variance:.2f}, third={third:.2f}, fourth={fourth:.2f}")
mean=1.65, variance=4.60, third=55.13, fourth=1429.58
# standardized central moments
stdev = np.sqrt(variance)
skewness = third / stdev**3
kurtosis = fourth / stdev**4
print(f"stdev={stdev:.2f}, skewness={skewness:.2f}, kurtosis={kurtosis:.2f}")
stdev=2.15, skewness=5.58, kurtosis=67.44
px.histogram(y)
np.random.seed(0)
x1 = np.random.normal(
loc=0.1,
scale=0.1,
size=100000
)
x2 = np.random.normal(
loc=0.1,
scale=0.5,
size=100000
)
z = np.random.randint(2, size=100000)
y = np.where(z, x1, x2)
px.histogram(y)
# central moments
mean = np.mean(y)
variance = np.mean(
(y-mean)**2
)
third = np.mean(
(y-mean)**3
)
fourth = np.mean(
(y-mean)**4
)
print(f"mean={mean:.2f}, variance={variance:.2f}, third={third:.2f}, fourth={fourth:.2f}")
mean=0.10, variance=0.13, third=0.00, fourth=0.09
# standardized central moments
stdev = np.sqrt(variance)
skewness = third / stdev**3
kurtosis = fourth / stdev**4
print(f"stdev={stdev:.2f}, skewness={skewness:.2f}, kurtosis={kurtosis:.2f}")
stdev=0.36, skewness=0.01, kurtosis=5.56