Monte Carlo Simulation in Finance Python Part-2

Monte Carlo simulation is a technique that approximate the solution to a problem through statistical sampling method. In short the model simulated a large number of possibilities.

Monte carlo is highly used in risk assessment. The popular use case is to calculate risk or drawdown of a portfolio/strategy. It simulates high number of possible outcomes of various portfolios which help investors in calculating risk.

Other use case is to estimate return of different portfolios. Portfolio returns can be simulated by Monte carlo which gives us probabilistic view of expected return in futures. Return of mutual funds and various SIP can be also estimate by the simulation.

Lets address the problem of portfolio return estimation .

Estimation of portfolio/SIP return using python:

A classic problem statement of a common investor is, how much return I will get if I invest 100k in this portfolio or SIP ?

In this post we will try to make a Quantitative model which answers the problem statement using statistical method i.e Monte Carlo.

Problem Statement:-

Starting a SIP and investing 10k annually for 20 years, what is the probability that you will have at least 500k by investing in Nifty50 portfolio ?

To generate the return we will use two factors

  1. Annual Return of Nifty50
  2. Volatility in terms of Standard deviation of Nifty50

The Annual return of Nifty50 index is around 6% where the STD is around 14%. Lets use the above given parameters to generate simulations.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
investment = 10000
expected_returns = 0.06
volatility = 0.14
duration = 20
sip = 10000
print('  \t Returns', '\t\tEnding Value'.rjust(18))
for year in range(duration):
    print(year)
    market_return = np.random.normal(expected_returns, volatility)
    final_value = sip + (1+ market_return)* investment
    print("\t{}".ljust(10).format(round(market_return, 4)),
 "\t{}".rjust(10).format(round(final_value, 4)))
    investment = final_value

Above code simulates return of 20 years and returns final value of portfolio.

Output:-

Returns     		Ending Value
0
0.2561 22561.1289
1
0.0928 34655.5092
2
-0.138 39872.5064
3
0.0865 53321.1093
4
0.1583 71759.1796
5
0.1259 90790.097
6
0.1115 110909.6445
7
0.1718 139965.8365
8
-0.0201 147155.0691
9
0.2655 196220.1049
10
-0.0236 201591.5015
11
-0.042 203119.0258
12
0.167 247035.5294
13
0.1628 297265.0747
14
0.1371 348032.9352
15
0.1336 404539.7198
16
0.007 417365.869
17
0.1163 475910.538
18
0.2389 599617.6013
19
0.0652 648696.5622

As by the current simulation result, it seems like the answer is Yes. The resultant portfolio value is above 500k and the result looks pretty decent.

A single simulation can turns out to be an outlier and we need to increase our sample size to see the whole picture to decide where to put our hard money or not.

Lets try to simulate and generate results which will give us insight of the situation.

df = pd.DataFrame()
for i in range(500):
    investment = 10000
    expected_returns = 0.06
    volatility = 0.14
    duration = 20
    sip = 10000
    
    lst = []
#     print('  \t Returns', '\t\tEnding Value'.rjust(18))
    for year in range(duration):
#         print(year)
        market_return = np.random.normal(expected_returns, volatility)
        final_value = sip + (1+ market_return)* investment
#         print("\t{}".ljust(10).format(round(market_return, 4)), "\t{}".rjust(10).format(round(final_value, 4)))
        investment = final_value
        lst.append(final_value)
    df[i] = lst

Above code simulate over 500 times and we store these simulation data in pandas dataframe. Lets visualize a part of the dataframe.

To get insight of simulation results we are using statistical metrics.

print('Mean: ', round(df.iloc[-1,:].mean(), 2))
print('STD: ', round(df.iloc[-1,:].std(), 2))
print('MAX: ', round(df.iloc[-1,:].max(), 2))
print('Min: ', round(df.iloc[-1,:].min(), 2))

output :

Mean:  394473.53
STD: 155635.64
MAX: 1226694.81
Min: 111881.56

We can see the Mean of simulation is around 400k where max value is around 1200k and min portfolio value is around 100k.

Histogram provides a clear insight of distribution. Lets try to plot histogram of simulated returns.

plt.hist(df.iloc[-1,:], bins = 100);
Histogram

As expected histogram returns are symmetrically distributed while the mean is in between 300–400 k.

As per the problem lets find out the probability of achieving more than 500k return on investment.

sum(df.iloc[-1,:] >= 500000)/len(df.iloc[-1,:])

output: 0.212

So as per the current simulations the probability of 500k return on investment is around 20%.

Although returns aren’t turn out to as much we expected but lets divide the returns into probabilities further.

percentile = np.percentile(df.iloc[-1,:],
 [5, 10, 15, 25, 50, 75, 85, 90, 95] )
for i in range(len(percentile)):
    l = [5, 10, 15, 25, 50, 75, 85, 90, 95]
    print(f'  { 100 - l[i] } % percent probability finalvalue >= {round( percentile[i], 2)} ')

output :

  95 % percent probability final value >= 201723.86 
  90 % percent probability final value >= 223506.64 
  85 % percent probability final value >= 248068.5 
  75 % percent probability final value >= 281118.68 
  50 % percent probability final value >= 367363.73 
  25 % percent probability final value >= 464394.42 
  15 % percent probability final value >= 540143.74 
  10 % percent probability final value >= 586180.1 
   5 % percent probability final value >= 681661.15

The above code divide the simulations into probability chunks which helps us to get better understanding of returns with probability.

Wrapping Things Up

In this tutorial, we learned how to use Monte Carlo simulations in estimating return on investment.

Check back soon for Part 3 of this tutorial where we’ll go over how to use the model for risk management.

Good luck, and as always feel free to drop questions and comments.:)