Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Refactor the code below to include 5 unique class methods. The classes can be anything to enhance the code. Developed a retirement calculator using a

Refactor the code below to include 5 unique class methods. The classes can be anything to enhance the code. image text in transcribed

"""Developed a retirement calculator using a Monte Carlo simulation"""

import sys

import random

import matplotlib.pyplot as plt

def read_to_list(file_name):

"""Open financial data in percent, convert to a decimal and return a list"""

with open(file_name) as in_file:

lines = [float(line.strip()) for line in in_file]

decimal = [round(line / 100, 5) for line in lines]

return decimal

def default_input(prompt, default=None):

"""Allow default values in input"""

# prompt = '{} [{}]: '.format(prompt, default)

prompt = f'{prompt} [{default}]: '

response = input(prompt)

if not response and default:

return default

else:

return response

# Financial data to be loaded from files with original data in percent form

print(" Note: Input data should be in percent, not decimal! ")

try:

bonds = read_to_list('10-yr_TBond_returns_1926-2013_pct.txt')

stocks = read_to_list('SP500_returns_1926-2013_pct.txt')

blend_40_50_10 = read_to_list('S-B-C_blend_1926-2013_pct.txt')

blend_50_50 = read_to_list('S-B_blend_1926-2013_pct.txt')

infl_rate = read_to_list('annual_infl_rate_1926-2013_pct.txt')

except IOError as e:

print(f"{e}. Terminating program.", file=sys.stderr)

sys.exit(1)

# Get user input; use dictionary for investment-type arguments

investment_type_args = {

'bonds': bonds,

'stocks': stocks,

'sb_blend': blend_50_50,

'sbc_blend': blend_40_50_10

}

# Print input legend for user

print(" stocks = SP500")

print(" bonds = 10-yr Treasury Bond")

print(" sb_blend = 50% SP500/50% TBond")

print("sbc_blend = 40% SP500/50% TBond/10% Cash ")

print("Press ENTER to take default value shown in [brackets]. ")

# get user input

invest_type = default_input("Enter investment type: (stocks, bonds, sb_blend,"\

" sbc_blend): ", 'bonds').lower()

while invest_type not in investment_type_args:

invest_type = input("Invalid investment. Enter investment type " \

"as listed in prompt: ")

start_value = default_input("Input starting value of investments: ", \

'2000000')

while not start_value.isdigit():

start_value = input("Invalid input! Input integer only: ")

withdrawal = default_input("Input annual pre-tax withdrawal" \

" (today's $): ", '80000')

while not withdrawal.isdigit():

withdrawal = input("Invalid input! Input integer only: ")

min_years = default_input("Input minimum years in retirement: ", '18')

while not min_years.isdigit():

min_years = input("Invalid input! Input integer only: ")

most_likely_years = default_input("Input most-likely years in retirement: ",

'25')

while not most_likely_years.isdigit():

most_likely_years = input("Invalid input! Input integer only: ")

max_years = default_input("Input maximum years in retirement: ", '40')

while not max_years.isdigit():

max_years = input("Invalid input! Input integer only: ")

num_cases = default_input("Input number of cases to run: ", '50000')

while not num_cases.isdigit():

num_cases = input("Invalid input! Input integer only: ")

# check for other erroneous input

if not int(min_years)

or int(max_years) > 99:

print(" Problem with input years.", file=sys.stderr)

print("Requires Min

sys.exit(1)

def montecarlo(returns):

"""Run MCS and return investment value at end-of-plan and bankrupt count."""

case_count = 0

bankrupt_count = 0

outcome = []

while case_count

investments = int(start_value)

start_year = random.randrange(0, len(returns))

duration = int(

random.triangular(int(min_years), int(max_years),

int(most_likely_years)))

end_year = start_year + duration

lifespan = [i for i in range(start_year, end_year)]

bankrupt = 'no'

# build temporary lists for each case

lifespan_returns = []

lifespan_infl = []

for i in lifespan:

lifespan_returns.append(returns[i % len(returns)])

lifespan_infl.append(infl_rate[i % len(infl_rate)])

# loop through each year of retirement for each case run

for index, i in enumerate(lifespan_returns):

infl = lifespan_infl[index]

# don't adjust for inflation the first year

if index == 0:

withdraw_infl_adj = int(withdrawal)

else:

withdraw_infl_adj = int(withdraw_infl_adj * (1 + infl))

investments -= withdraw_infl_adj

investments = int(investments * (1 + i))

if investments

bankrupt = 'yes'

break

if bankrupt == 'yes':

outcome.append(0)

bankrupt_count += 1

else:

outcome.append(investments)

case_count += 1

return outcome, bankrupt_count

def bankrupt_prob(outcome, bankrupt_count):

"""Calculate and return chance of running out of money & other stats."""

total = len(outcome)

odds = round(100 * bankrupt_count / total, 1)

print(f" Investment type: {invest_type}")

print("Starting value: ${:,}".format(int(start_value)))

print("Annual withdrawal: ${:,}".format(int(withdrawal)))

print("Years in retirement (min-ml-max): {}-{}-{}".format(

min_years, most_likely_years, max_years))

print("Number of runs: {:,} ".format(len(outcome)))

print("Odds of running out of money: {}% ".format(odds))

print("Average outcome: ${:,}".format(int(sum(outcome) / total)))

print("Minimum outcome: ${:,}".format(min(i for i in outcome)))

print("Maximum outcome: ${:,}".format(max(i for i in outcome)))

return odds

def main():

"""Call MCS & bankrupt functions and draw bar chart of results."""

outcome, bankrupt_count = montecarlo(investment_type_args[invest_type])

odds = bankrupt_prob(outcome, bankrupt_count)

# generate matplotlib bar chart

plotdata = outcome[:3000] # only plot first 3000 runs

plt.figure('Outcome by Case (showing first {} runs)'.format(len(plotdata)),

figsize=(16, 5)) # size is width, height in inches

index = [i + 1 for i in range(len(plotdata))]

plt.bar(index, plotdata, color='black')

plt.xlabel('Simulated Lives', fontsize=18)

plt.ylabel('$ Remaining', fontsize=18)

plt.ticklabel_format(style='plain', axis='y')

ax = plt.gca()

ax.get_yaxis().set_major_formatter(

plt.FuncFormatter(lambda x, loc: "{:,}".format(int(x))))

plt.title('Probability of running out of money = {}%'.format(odds),

fontsize=20,

color='red')

plt.show()

# run program

if __name__ == '__main__':

main()

# Refactor the code below to include 5 Unique Class Methods. # Refactor the existing code with at least 5 unique class methods to demonstrate varying levels of complexity. # The objects should be different levels of complexity, for example some may be basic containers # and others should manage those containers (e.g. Consumer Class) as well as demonstrating various flow control and data types. # One example could be refactoring the code below to include: class Consumer: def __init__(self, w): "Initialize consumer with w dollars of wealth" self.wealth = w def earn(self, y): "The consumer earns y dollars" self.wealth += y def spend(self, x): "The consumer spends x dollars if feasible" new_wealth = self.wealth - X if new_wealth

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image_2

Step: 3

blur-text-image_3

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Database Administration The Complete Guide To Dba Practices And Procedures

Authors: Craig S. Mullins

2nd Edition

0321822943, 978-0321822949

More Books

Students also viewed these Databases questions

Question

7. Discuss the implications of a skill-based pay plan for training.

Answered: 1 week ago

Question

What is the most important part of any HCM Project Map and why?

Answered: 1 week ago