Retirement Simulator #3: Use a Gaussian distribution of rates!

Published Dec. 31, 2021, 4:35 p.m.

Welcome to the third tutorial.  In this tutorial we will continue building from our last tutorial.  We last left with something like the following:

import sys, os
import numpy as np
from datetime import date, timedelta


todays_date = date.today()

two_weeks = timedelta(days = 14)
one_year = timedelta(days = 365.25)
one_month = one_year/12
semi_monthly = one_month/2

pay_frequency = two_weeks

amount_already_in_retirement = 10000

paychecks_per_year = int(round(one_year/pay_frequency, 0))

Current_Salary = 50000
one_paycheck = Current_Salary/paychecks_per_year
add_to_retirement = 0.10*one_paycheck
# add_to_retirement = 100

retirement_date = date(2030, 3, 31)

retirement = amount_already_in_retirement

annual_interst_rate = 0.10


"""
want to convert annual_interst_rate into a bi-weekly interest rate equivalent.

bwir should be such that (1+bwir)**26 =  air (annual_interst_rate)

26*log((1+bwir)) = log(1+air)

log((1+bwir)) = (1/26)*log(1+air)

1 + bwir = exp((1/26)*log(1+air))

bwir = exp((1/26)*log(1+air)) - 1

"""

def get_paycheck_interest_rate(annual_interst_rate, paychecks_per_year):
    return np.exp((1/paychecks_per_year)*np.log(1+annual_interst_rate)) - 1

paycheck_interest_rate = get_paycheck_interest_rate(annual_interst_rate, paychecks_per_year)


while todays_date < retirement_date:
    retirement += add_to_retirement
    retirement *= (1+paycheck_interest_rate)
    todays_date += pay_frequency
    
    # print(retirement, todays_date)
    
### TEST: ###
retirement = 100
print("TEST")
for i in range(paychecks_per_year):
    retirement *= (1+paycheck_interest_rate)
    print(np.round(retirement,2))

 

This time we are going to add the feature of picking an interest rate using a gassian distribution.  First we'll need to go to the top of the script and import the random module:

import sys, os
import numpy as np
from datetime import date, timedelta
import random

Once imported, it can be used!  Now, lucky for us the random module has a 'gauss' function that only requires a mean and sigma for input.  If you don't know what a "Gaussian" function is then go look it up!  Cliff notes version: it's a bell curve.  It has a "mean" value (top of the bell) and a "sigma" value (width of the bell).  Quick rule of thumb:  plus or minus 2*sigma should cover 95% of the probability space.  Translation: if your mean value is 0.05 (5%) and your sigma is 0.01 (1%) then 95 times out of 100 a random sample will be between 0.03 and 0.07 (or 0.05 + 2*0.01 and 0.05 - 3*0.01).

Again, don't worry if you don't totally understand.  If you want to understand it stare at it until beads of blood come out of your head.  That should help.

We will define a mean of 0.07 and a width that is the same (0.07).  To be clear, this is totally contrived from thin air (so far).  However, based on the statements above we can expect that 95% of samples from this distribution will be between -0.07 and 0.21.  That means we expect postive interest rates more often than negative ones but we do expect some negative rates to be selected.  With a mean and sigma defined be can used the random.gauss function to select our annual interest rate:

mean = 0.07
sigma = 0.07
annual_interst_rate  = random.gauss(mean, sigma)
paycheck_interest_rate = get_paycheck_interest_rate(annual_interst_rate, paychecks_per_year)

This should be defined after any other declarations of annual interest rate (but before we determine the paycheck interest rate).

For this to be used more than once in the code we need to have a way to determine when we have come upon a new year.  In essesce when the year changes, we want to pick the new annual interest rate.  To do this we will need to add something that can check and interupt our "while" loop.  First, before the loop we will establish a variable called 'year_check'.

Then inside the loop near the top (but after the addition of pay_frequency) we will establish 'this_year'.  We can access the year of a datetime.date using the ".year" extension.

year_check = todays_date.year
while todays_date < retirement_date:
    retirement += add_to_retirement
    retirement *= (1+paycheck_interest_rate)
    todays_date += pay_frequency
    this_year = todays_date.year

Next we want to add a test (using an 'if' statement) to test if 'this_year' is greater than 'year_check':

year_check = todays_date.year
while todays_date < retirement_date:
    retirement += add_to_retirement
    retirement *= (1+paycheck_interest_rate)
    todays_date += pay_frequency
    this_year = todays_date.year
    if this_year > year_check:
        annual_interst_rate  = random.gauss(mean, sigma)
        paycheck_interest_rate = get_paycheck_interest_rate(annual_interst_rate, paychecks_per_year)

If true, then we want to select a new annual_interest_rate and compute a new "paycheck_interest rate".  To check this we can print the year and the annual interest rate.  After the 'if' statement we proceed as normal but we add a new 'year_check' at the end of our 'while' loop:

year_check = todays_date.year
while todays_date < retirement_date:
    retirement += add_to_retirement
    retirement *= (1+paycheck_interest_rate)
    todays_date += pay_frequency
    this_year = todays_date.year
    if this_year > year_check:
        annual_interst_rate  = random.gauss(mean, sigma)
        paycheck_interest_rate = get_paycheck_interest_rate(annual_interst_rate, paychecks_per_year)
        print(this_year, annual_interst_rate)
    year_check = todays_date.year

If this runs correctly you should see the list of years until your selected retirement date print out along with a number representing the annual interest rate.  Next time we will add a verification step for this work by plotting a selection of rates picked this way as a histogram.  Thanks for watching!

skip_nextRetirement Simulator #3+: Verify our Gaussian distribution!
  • Retirement Simulator Introduction and Overview

  • Retirement Simulator #1: March through time with datetime and put money under the mattress!

  • Retirement Simulator #2: Apply an interest rate and verify it!

  • Retirement Simulator #3: Use a Gaussian distribution of rates!
    (currently viewing)
  • Retirement Simulator #3+: Verify our Gaussian distribution!

  • Retirement Simulator #4: Make a US market rates distribution

  • Retirement Simulator #5: Fit the Market Data with scipy curve_fit

  • Retirement Simulator #6: Sampling from our custom market distribution

  • Retirement Simulator #7: Organize multiple plots with subplots! and learn about plt.pause()

  • Retirement Simulator #8: Multiverse Investing: Simulate 1000 random investors

  • Retirement Simulator #9: Track averages and final outcomes

  • Retirement Simulator #10: Test and Compare Different Retirement dates (And make it pretty!)