Skip to content

Instantly share code, notes, and snippets.

@dariocazzani
Last active April 27, 2019 21:59
Show Gist options
  • Save dariocazzani/1d778ac970db85a19f39ca9764968a47 to your computer and use it in GitHub Desktop.
Save dariocazzani/1d778ac970db85a19f39ca9764968a47 to your computer and use it in GitHub Desktop.
Savings for Pension
import numpy as np
import random
from termcolor import colored
"""
https://www.slickcharts.com/sp500/returns
"""
SP500_history = list(reversed([-4.38, 21.83, 11.96, 1.38, 13.69, 32.39, 16, 2.11, 15.06, 26.46, -37, 5.49, 15.79, 4.91, 10.88, 28.68, -22.1, -11.89, -9.1, 21.04, 28.58, 33.36, 22.96, 37.58, 1.32, 10.08, 7.62, 30.47, -3.1, 31.69, 16.61, 5.25, 18.67, 31.73, 6.27, 22.56, 21.55, -4.91, 32.42, 18.44, 6.56, -7.18, 23.84, 37.2, -26.47, -14.66, 18.98, 14.31, 4.01, -8.5, 11.06, 23.98, -10.06, 12.45, 16.48, 22.8, -8.73, 26.89, 0.47, 11.96, 43.36, -10.78, 6.56, 31.56, 52.62, -0.99, 18.37, 24.02, 31.71, 18.79, 5.5, 5.71, -8.07, 36.44, 19.75, 25.9, 20.34, -11.59, -9.78, -0.41, 31.12, -35.03, 33.92, 47.67, -1.44, 53.99, -8.19, -43.34, -24.9, -8.42, 43.61, 37.49, 11.62]))
initial_withdraw = 1.
increase = 1
LOW_RISK_INTEREST = 2.4
SP500_avg_interest = np.mean(SP500_history)
initial_amount = float(input("How much money have you saved? "))
total_years = int(input("How many years to you want to enjoy your pension for? "))
taxes = float(input("How much taxes do you pay on the gains? (in %) "))
print("We assume you need to increase the amount by 1% every year")
# Sadly, it goes down as years pass
def lowrisk_year_interest(year, low_risk_avg_interest, std=0.1):
low_risk_avg_interest -= (year/100)
return float(np.random.normal(low_risk_avg_interest, 0.1, 1) / 100.)
def circshift(l, n):
return l[n:] + l[:n]
prev_withdraws = []
withdraws = []
withdraw = initial_withdraw
while True:
prev_withdraws = withdraws
withdraws = []
amount = initial_amount
withdraw += increase
for i in range(1, total_years):
withdraws.append(withdraw)
amount -= withdraw
withdraw *= 1.01
if amount < 0:
break
new_amount = amount*(1+lowrisk_year_interest(i, LOW_RISK_INTEREST))
taxes_owed = (new_amount-amount) * (taxes/100)
amount = new_amount - np.maximum(0, taxes_owed)
if amount < 0:
break
low_risk_initial_withdraw = prev_withdraws[0]
print(colored("\n*********\nLow risk investments:", 'yellow'))
print("With an initial savings of ", end="")
print(colored("${:.2f}".format(initial_amount), 'blue'))
print("A compound interest of ", end='')
print(colored("~{:.2f}%".format(LOW_RISK_INTEREST), "cyan"))
print("You can start withdrawing ", end='')
print(colored("${:.2f}".format(low_risk_initial_withdraw), 'green'), end="")
print(" for {} years".format(total_years))
prev_withdraws = []
withdraws = []
all_initial_withdraws = []
withdraw = initial_withdraw
lowest_withdraw = np.inf
highest_withdraw = 0
for history in range(len(SP500_history)):
# Make up a possible outcome for S&P500
possible_outcome = SP500_history.copy()
possible_outcome = circshift(possible_outcome, history)
withdraw = initial_withdraw
while True:
prev_withdraws = withdraws.copy()
withdraws = []
amount = initial_amount
withdraw += increase
for i in range(1, total_years):
withdraws.append(withdraw)
amount -= withdraw
withdraw *= 1.01
if amount < 0:
break
new_amount = amount*(1+(possible_outcome[i]/100))
taxes_owed = (new_amount-amount) * (taxes/100)
amount = new_amount - np.maximum(0, taxes_owed)
if amount < 0:
break
if prev_withdraws[0] < lowest_withdraw:
lowest_withdraw = prev_withdraws[0]
if prev_withdraws[0] > highest_withdraw:
highest_withdraw = prev_withdraws[0]
all_initial_withdraws.append(prev_withdraws[0])
print(colored("\n*********\nHish risk investments:", 'yellow'))
print("With an initial savings of ", end="")
print(colored("${:.2f}".format(initial_amount), 'blue'))
print("A compound interest of ", end="")
print(colored("~{:.2f}%".format(SP500_avg_interest), 'cyan'))
print("In the worst case scenario you start withdrawing ", end="")
print(colored("${:.2f} ".format(lowest_withdraw), 'red'))
print("In the best case scenario you start withdrawing ", end="")
print(colored("${:.2f} ".format(highest_withdraw), "green"), end="")
print("For {} years".format(total_years))
print("All initial withdraws stats. Avg: {:.2f}, Std: {:.2f}".format(np.mean(all_initial_withdraws), np.std(all_initial_withdraws)))
worse_than_lowrisk = len(np.where(np.array(all_initial_withdraws) < low_risk_initial_withdraw)[0]) / len(SP500_history)
print("Probability of doing worse than low risk: ", end="")
print(colored("{:.2f}%".format(worse_than_lowrisk*100), "green"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment