# QuantFinanceToGo, module 16: Monte Carlo Simulation. Python implementation.
# Runs on its own with Python 3 and numpy. The 10,000 paths of Figure 1, seed 17.

import numpy as np                               # numpy draws the random numbers

start, years, paths = 10_000, 30, 10_000         # $10,000, 30 years, 10,000 paths
mu, sigma = 0.08, 0.20                           # average return and volatility a year
rng = np.random.default_rng(17)                  # fixed seed: the same paths every run
g = mu - sigma ** 2 / 2                          # the growth rate of the log returns
log_ret = rng.normal(g, sigma, (paths, years))   # a random log return per path and year
final = start * np.exp(log_ret.sum(axis=1))      # what $10,000 grows into on each path
avg = final.mean()                               # the Monte Carlo estimate, an average
s = final.std(ddof=1)                            # the spread of one path result
se = s / paths ** 0.5                            # the standard error, s over root of M
print(f"spread of one path: ${s:,.0f}")          # print the spread s
print(f"average ${avg:,.0f} +/- ${se:,.0f}")     # the estimate and its standard error
