Annuity Calculator

Download as pdf or txt
Download as pdf or txt
You are on page 1of 26

#Annuities: a program to calculate various values of different types of

annuities
#Authors: Kate McCoy, Blake Ellerbusch, Clare Krajewski, and Lexi Hanna

import math
from graphics import*

def x(interest):
"""Calculates the present value multiplyer

Parameters:
interest: a float

Returns:
1 / (1 + interest)

Preconditions:
interest must be a number

Postconditions:
The present value multiplyer is calculated
"""
v = 1 / (1+interest)
return v

def a_angle(interest, duration):


"""Caclulates a angle, the annuity present value multiplyer

Parameters:
interest: a float
duration: an integer

Returns:
a angle duration using interest as the interest rate

Preconditions:
interest and duration must be a number

Postconditions:
a angle, the annuity present value multiplyer is calculated
"""
PV = (1-(x(interest)**duration))/interest
return PV

def s_angle(interest, duration):


"""Caclulates s angle, the future present value multiplyer

Parameters:
interest: a float
duration: an integer

Returns:
s angle duration using interest as the interest rate

Preconditions:
interest and duration must be a number
Postconditions:
s angle, the annuity future value multiplyer is calculated
"""
FV = (((1+interest)**duration)-1)/interest
return FV

def a_doubledot(interest, duration):


"""Caclulates a double dot, the annuity present value multiplyer for
annuities due

Parameters:
interest: a float
duration: an integer

Returns:
a double dot duration using interest as the interest rate

Preconditions:
interest and duration must be a number

Postconditions:
a double dot, the annuity present value multiplyer for annuities due is
calculated
"""
d = ConvertIRtoDR(interest)
PV = (1-(x(interest)**duration))/d
return PV

def s_doubledot(interest, duration):


"""Caclulates s double dot, the annuity future value multiplyer for
annuities due

Parameters:
interest: a float
duration: an integer

Returns:
s double dot duration using interest as the interest rate

Preconditions:
interest and duration must be a number

Postconditions:
s double dot, the annuity future value multiplyer for annuities due
"""
d = ConvertIRtoDR(interest)
FV= (((1+interest)**duration)-1)/d
return FV

def ConvertIRtoDR(interest):
"""Converts an interest rate to a discount rate

Parameters:
interest: a float

Returns:
the interest rate converted to a discount rate
Preconditions:
interest must be a number

Postconditions:
the interest rate is converted to a discount rate
"""
discount = (interest)/(1+interest)
return discount

def clear(win):
"""Clears the graphics window of any objects

Parameters:
win: a GraphWin object

Returns:
a blank graphics window

Preconditions:
win must be a GraphWin object

Postconditions:
the objects from the graphics window are cleared
"""
for item in win.items[:]:
item.undraw()
win.update()

class Calculator:
"""Displays screens of the calculator and gets values from the user"""

def __init__(self, win):


"""Initilizes Calculator class"""
self.win = win

def DisplayType(self):
"""Displays the first screen of the program where the user can choose
the type of annuity"""

rec = Rectangle(Point(0,0),Point(500,500))
rec.setFill("white")
rec.draw(self.win)

annuity = Rectangle(Point(15, 200), Point(240,300))


perpetuity = Rectangle(Point(485, 200), Point(260, 300))
geometric = Rectangle(Point(15, 330), Point(240, 480))
arithmatic = Rectangle(Point(485,330), Point(260,480))

annuity.draw(self.win)
perpetuity.draw(self.win)
geometric.draw(self.win)
arithmatic.draw(self.win)

prompt = Text(Point(250, 100), "Click the type of annuity you have.")


prompt.draw(self.win)
annuity_text = Text(Point(112.5, 250), "Regular")
perpetuity_text = Text(Point(372.5, 250), "Perpetuity")
geometric_text = Text(Point(112.5, 400), "Changing
Payments:\n\nGeometric")
arithmatic_text = Text(Point(372.5, 400), "Changing
Payments:\n\nArithmetic")

annuity_text.draw(self.win)
perpetuity_text.draw(self.win)
geometric_text.draw(self.win)
arithmatic_text.draw(self.win)

def DisplayRegValues(self):
"""Displays a screen where users can input values and what they are
trying to calculate"""
#specified for a regular annuity

rec = Rectangle(Point(0,0),Point(500,500))
rec.setFill("white")
rec.draw(self.win)

prompt = Text(Point(250, 25), "Type any known values of the annuity.")


prompt.draw(self.win)
prompt2 = Text(Point(250, 375), "Click the value you are trying to
calculate.")
prompt2.draw(self.win)

present = Rectangle(Point(15,50),Point(250,150))
present.draw(self.win)
pBox = Entry(Point(130,135), 20)
pBox.draw(self.win)
pBox.setTextColor("black")
self.pBox = pBox #Make input boxes instance variables to use later
ptext = Text(Point(130,90),"Present Value")
ptext.draw(self.win)

future = Rectangle(Point(250,150), Point(485,50))


future.draw(self.win)
fBox = Entry(Point(370,135), 20)
fBox.draw(self.win)
fBox.setTextColor("black")
self.fBox = fBox
ftext = Text(Point(370,90),"Future Value")
ftext.draw(self.win)

payment = Rectangle(Point(15,150), Point(250,250))


payment.draw(self.win)
pmtBox = Entry(Point(130,235), 20)
pmtBox.draw(self.win)
pmtBox.setTextColor("black")
self.pmtBox = pmtBox
paytext = Text(Point(130,190),"Payment Amount")
paytext.draw(self.win)

interest = Rectangle(Point(250,250), Point(485,150))


interest.draw(self.win)
iBox = Entry(Point(370,235), 20)
iBox.draw(self.win)
iBox.setTextColor("black")
self.iBox = iBox
itext = Text(Point(370,190),"Interest Rate\n(written as decimal)")
itext.draw(self.win)

duration = Rectangle(Point(15,250), Point(250,350))


duration.draw(self.win)
dBox = Entry(Point(130,335), 20)
dBox.draw(self.win)
dBox.setTextColor("black")
self.dBox = dBox
dtext = Text(Point(130,290),"Durarion")
dtext.draw(self.win)

frstpmt = Rectangle(Point(250,350), Point(485,250))


frstpmt.draw(self.win)
fpBox = Entry(Point(370,335), 20)
fpBox.draw(self.win)
fpBox.setTextColor("black")
self.fpBox = fpBox
fptext = Text(Point(370,290),"Immediate or Due")
fptext.draw(self.win)

PV = Rectangle(Point(10,400), Point(90,475))
PV.draw(self.win)
PVtext = Text(Point(50,435),"PV")
PVtext.draw(self.win)

FV = Rectangle(Point(90,400), Point(170,475))
FV.draw(self.win)
FVtext = Text(Point(130,435),"FV")
FVtext.draw(self.win)

PMT = Rectangle(Point(170,400), Point(250, 475))


PMT.draw(self.win)
PMTtext = Text(Point(210,435),"PMT")
PMTtext.draw(self.win)

IRR = Rectangle(Point(250,400), Point(330,475))


IRR.draw(self.win)
IRRtext = Text(Point(290,435),"IRR")
IRRtext.draw(self.win)

N = Rectangle(Point(330,400),Point(410,475))
N.draw(self.win)
Ntext = Text(Point(370,435),"N")
Ntext.draw(self.win)

IntAmt = Rectangle(Point(410,400),Point(490,475))
IntAmt.draw(self.win)
Inttext = Text(Point(450,435),"Total\nInterest")
Inttext.draw(self.win)

def GetRegValues(self):
"""Creates a dictionary with the values the user typed and its
corresponding label"""
#specified for a regular annuity

#assign text from input boxes to variables


presentvalue = self.pBox.getText()
futurevalue = self.fBox.getText()
payment = self.pmtBox.getText()
interest = self.iBox.getText()
duration = self.dBox.getText()
frstpmt = self.fpBox.getText()
self.FP = frstpmt.lower() #lowercase the first payment incase it
wasn't already

#create dictionary with label and value


values = {'PV':presentvalue, 'FV':futurevalue, 'PMT':payment,
'IRR':interest, 'N':duration}
try:
for item in values.keys(): #Had to use iteration to change
unempty values from strings to floats
if values[item] == '':
values[item] = values[item]
else:
value = values[item]
values[item] = float(value)
except:
raise ValueError("Values must be numbers")

self.values = values

def GetRegSolveFor(self):
"""Waits for user to click a solve for box, calls the get values
method, and identifies the solve for"""
#specified for a regular annuity

#Wait for user to click a solve for box


while self.win.isOpen():

try:
click = self.win.getMouse()
except:
break

#Calls get values and assigns an instance variable, SolveFor, based


on what was clicked
if 10 < click.getX() < 90 and 400 < click.getY() < 475:
self.GetRegValues()
self.SolveFor = 'PV'
break

if 90 < click.getX() < 170 and 400 < click.getY() < 475:
self.GetRegValues()
self.SolveFor = 'FV'
break

if 170 < click.getX() < 250 and 400 < click.getY() < 475:
self.GetRegValues()
self.SolveFor = 'PMT'
break
if 250 < click.getX() < 330 and 400 < click.getY() < 475:
self.GetRegValues()
self.SolveFor = 'IRR'
break

if 330 < click.getX() < 410 and 400 < click.getY() < 475:
self.GetRegValues()
self.SolveFor = 'N'
break

if 410 < click.getX() < 490 and 400 < click.getY() < 475:
self.GetRegValues()
self.SolveFor = 'IntAmt'
break

def DisplayPerpValues(self):
"""Displays a screen where users can input values and what they are
trying to calculate"""
#specified for a perpetuity

rec=Rectangle(Point(0,0), Point(500,500))
rec.setFill("white")
rec.draw(self.win)

prompt= Text(Point(250,25), "Type any known values of the perpetuity.")


prompt.draw(self.win)
prompt2=Text(Point(250,350), "Click the value you are trying to
calculate.")
prompt2.draw(self.win)

present=Rectangle(Point(15,50),Point(250,150))
present.draw(self.win)
pBox=Entry(Point(130,135),20)
pBox.draw(self.win)
pBox.setTextColor("black")
self.pBox=pBox
ptext=Text(Point(130,90), "Present Value")
ptext.draw(self.win)

frstpmt=Rectangle(Point(250,150),Point(485,50))
frstpmt.draw(self.win)
fpBox = Entry(Point(370,135), 20)
fpBox.draw(self.win)
fpBox.setTextColor("black")
self.fpBox=fpBox
fptext=Text(Point(370,90),"Immediate or Due")
fptext.draw(self.win)

payment=Rectangle(Point(15,150), Point(250,250))
payment.draw(self.win)
pmtBox=Entry(Point(130,235),20)
pmtBox.draw(self.win)
pmtBox.setTextColor("black")
self.pmtBox=pmtBox
paytext=Text(Point(130,190),"Payment Amount")
paytext.draw(self.win)
interest=Rectangle(Point(250,250), Point(485,150))
interest.draw(self.win)
iBox=Entry(Point(370,235),20)
iBox.draw(self.win)
iBox.setTextColor("black")
self.iBox=iBox
itext=Text(Point(370,190),"Interest Rate\n(written as decimal)")
itext.draw(self.win)

PV=Rectangle(Point(100,400), Point(200,475))
PV.draw(self.win)
PVtext=Text(Point(150,435), "PV")
PVtext.draw(self.win)

PMT=Rectangle(Point(200,400), Point(300,475))
PMT.draw(self.win)
PMTtext=Text(Point(250,435),"PMT")
PMTtext.draw(self.win)

IRR=Rectangle(Point(300,400),Point(400,475))
IRR.draw(self.win)
IRRtext=Text(Point(350,435),"IRR")
IRRtext.draw(self.win)

def GetPerpValues(self):
"""Creates a dictionary with the values the user typed and its
corresponding label"""
#specified for a perpetuity

presentvalue = self.pBox.getText()
payment = self.pmtBox.getText()
interest = self.iBox.getText()
frstpmt = self.fpBox.getText()
self.FP = frstpmt.lower()
values = {'PV':presentvalue, 'PMT':payment, 'IRR':interest}

try:
for item in values.keys():
if values[item] == '':
values[item] = values[item]
else:
value = values[item]
values[item] = float(value)
except:
raise ValueError("Values must be numbers")

self.values = values

def GetPerpSolveFor(self):
"""Waits for user to click a solve for box, calls the get values
method, and identifies the solve for"""
#specified for a perpetuity

while self.win.isOpen():
try:
click = self.win.getMouse()
except:
break

if 100 < click.getX() < 200 and 400 < click.getY() < 475:
self.GetPerpValues()
self.SolveFor = 'PV'
break

if 200 < click.getX() < 300 and 400 < click.getY() < 475:
self.GetPerpValues()
self.SolveFor = 'PMT'
break

if 300 < click.getX() < 400 and 400 < click.getY() < 475:
self.GetPerpValues()
self.SolveFor = 'IRR'
break

def DisplayGeoValues(self):
"""Displays a screen where users can input values and what they are
trying to calculate"""
#specified for geometric

rec=Rectangle(Point(0,0),Point(500,500))
rec.setFill("white")
rec.draw(self.win)

prompt=Text(Point(250,25), "Type any known values of the annuity.")


prompt.draw(self.win)
prompt2=Text(Point(250,375), "Click the value you are trying to
calculate.")
prompt2.draw(self.win)

present=Rectangle(Point(15,50), Point(250,150))
present.draw(self.win)
pBox=Entry(Point(130,135),20)
pBox.draw(self.win)
pBox.setTextColor("black")
self.pBox=pBox
ptext=Text(Point(130,90),"Present Value")
ptext.draw(self.win)

future=Rectangle(Point(250,150),Point(485,50))
future.draw(self.win)
fBox=Entry(Point(370,135),20)
fBox.draw(self.win)
fBox.setTextColor("black")
self.fBox=fBox
ftext=Text(Point(370,90),"Future Value")
ftext.draw(self.win)

payment=Rectangle(Point(15,150), Point(250,250))
payment.draw(self.win)
pmtBox=Entry(Point(130,235), 20)
pmtBox.draw(self.win)
pmtBox.setTextColor("black")
self.pmtBox=pmtBox
paytext=Text(Point(130,190), "Payment Amount")
paytext.draw(self.win)

interest=Rectangle(Point(250,250), Point(485,150))
interest.draw(self.win)
iBox=Entry(Point(370,235), 20)
iBox.draw(self.win)
iBox.setTextColor("black")
self.iBox=iBox
itext=Text(Point(370,190), "Interest Rate\n(written as decimal)")
itext.draw(self.win)

duration=Rectangle(Point(15,250), Point(250,350))
duration.draw(self.win)
dBox=Entry(Point(130,335), 20)
dBox.draw(self.win)
dBox.setTextColor("black")
self.dBox=dBox
dtext=Text(Point(130,290), "Duration")
dtext.draw(self.win)

K=Rectangle(Point(250,350), Point(485,250))
K.draw(self.win)
KBox=Entry(Point(370,335),20)
KBox.draw(self.win)
KBox.setTextColor("black")
self.KBox=KBox
Ktext=Text(Point(370,290),"Percent Increase\n(written as decimal)")
Ktext.draw(self.win)

PV=Rectangle(Point(10,400), Point(90,475))
PV.draw(self.win)
PVtext=Text(Point(50,435),"PV")
PVtext.draw(self.win)

FV=Rectangle(Point(90,400),Point(170,475))
FV.draw(self.win)
FVtext=Text(Point(130,435), "FV")
FVtext.draw(self.win)

PMT=Rectangle(Point(170,400),Point(250,475))
PMT.draw(self.win)
pmttext=Text(Point(210,435),"PMT")
pmttext.draw(self.win)

N=Rectangle(Point(250,400), Point(330,475))
N.draw(self.win)
Ntext= Text(Point(290,435),"N")
Ntext.draw(self.win)

IntAmt = Rectangle(Point(330,400),Point(410,475))
IntAmt.draw(self.win)
IntAmttext = Text(Point(370,435),"Total\nInterest")
IntAmttext.draw(self.win)
def GetGeoValues(self):
"""Creates a dictionary with the values the user typed and its
corresponding label"""
#specified for geometric

presentvalue = self.pBox.getText()
futurevalue = self.fBox.getText()
payment = self.pmtBox.getText()
interest = self.iBox.getText()
duration = self.dBox.getText()
K = self.KBox.getText()
values = {'PV':presentvalue, 'FV':futurevalue, 'PMT':payment,
'IRR':interest, 'N':duration, 'K':K}

try:
for item in values.keys():
if values[item] == '':
values[item] = values[item]
else:
value = values[item]
values[item] = float(value)
except:
raise ValueError("Values must be numbers")

self.values = values

def GetGeoSolveFor(self):
"""Waits for user to click a solve for box, calls the get values
method, and identifies the solve for"""
#specified for geometric

while self.win.isOpen():
try:
click = self.win.getMouse()
except:
break
if 10 < click.getX() < 90 and 400 < click.getY() < 475:
self.GetGeoValues()
self.SolveFor = 'PV'
break

if 90 < click.getX() < 170 and 400 < click.getY() < 475:
self.GetGeoValues()
self.SolveFor = 'FV'
break

if 170 < click.getX() < 250 and 400 < click.getY() < 475:
self.GetGeoValues()
self.SolveFor = 'PMT'
break

if 250 < click.getX() < 330 and 400 < click.getY() < 475:
self.GetGeoValues()
self.SolveFor = 'N'
break

if 330 < click.getX() < 410 and 400 < click.getY() < 475:
self.GetGeoValues()
self.SolveFor = 'IntAmt'
break

def DisplayArithValues(self):
"""Displays a screen where users can input values and what they are
trying to calculate"""
#specified for arithmetic

rec=Rectangle(Point(0,0),Point(500,500))
rec.setFill("white")
rec.draw(self.win)

prompt=Text(Point(250,25), "Type any known values of the annuity.")


prompt.draw(self.win)
prompt2=Text(Point(250,375), "Click the value you are trying to
calculate.")
prompt2.draw(self.win)

present=Rectangle(Point(15,50), Point(250,150))
present.draw(self.win)
pBox=Entry(Point(130,135),20)
pBox.draw(self.win)
pBox.setTextColor("black")
self.pBox=pBox
ptext=Text(Point(130,90),"Present Value")
ptext.draw(self.win)

future=Rectangle(Point(250,150),Point(485,50))
future.draw(self.win)
fBox=Entry(Point(370,135),20)
fBox.draw(self.win)
fBox.setTextColor("black")
self.fBox=fBox
ftext=Text(Point(370,90),"Future Value")
ftext.draw(self.win)

payment=Rectangle(Point(15,150), Point(250,250))
payment.draw(self.win)
pmtBox=Entry(Point(130,235), 20)
pmtBox.draw(self.win)
pmtBox.setTextColor("black")
self.pmtBox=pmtBox
paytext=Text(Point(130,190), "Payment Amount")
paytext.draw(self.win)

interest=Rectangle(Point(250,250), Point(485,150))
interest.draw(self.win)
iBox=Entry(Point(370,235), 20)
iBox.draw(self.win)
iBox.setTextColor("black")
self.iBox=iBox
itext=Text(Point(370,190), "Interest Rate\n(written as decimal)")
itext.draw(self.win)

duration=Rectangle(Point(15,250), Point(250,350))
duration.draw(self.win)
dBox=Entry(Point(130,335), 20)
dBox.draw(self.win)
dBox.setTextColor("black")
self.dBox=dBox
dtext=Text(Point(130,290), "Duration")
dtext.draw(self.win)

Q=Rectangle(Point(250,350), Point(485,250))
Q.draw(self.win)
QBox=Entry(Point(370,335),20)
QBox.draw(self.win)
QBox.setTextColor("black")
self.QBox=QBox
Qtext=Text(Point(370,290),"Payment Change")
Qtext.draw(self.win)

PV=Rectangle(Point(10,400), Point(90,475))
PV.draw(self.win)
PVtext=Text(Point(50,435),"PV")
PVtext.draw(self.win)

FV=Rectangle(Point(90,400),Point(170,475))
FV.draw(self.win)
FVtext=Text(Point(130,435), "FV")
FVtext.draw(self.win)

PMT=Rectangle(Point(170,400),Point(250,475))
PMT.draw(self.win)
pmttext=Text(Point(210,435),"PMT")
pmttext.draw(self.win)

Increase=Rectangle(Point(250,400), Point(330,475))
Increase.draw(self.win)
Increasetext= Text(Point(290,435),"Payment\nChange")
Increasetext.draw(self.win)

IntAmt=Rectangle(Point(330,400), Point(410,475))
IntAmt.draw(self.win)
IntAmttext= Text(Point(370,435),"Total\nInterest")
IntAmttext.draw(self.win)

def GetArithValues(self):
"""Creates a dictionary with the values the user typed and its
corresponding label"""
#specified for arithmetic

presentvalue = self.pBox.getText()
futurevalue = self.fBox.getText()
payment = self.pmtBox.getText()
duration = self.dBox.getText()
interest = self.iBox.getText()
Q = self.QBox.getText()
values = {'PV':presentvalue, 'FV':futurevalue, 'PMT':payment,
'IRR':interest, 'N':duration, 'Q':Q}
try:
for item in values.keys():
if values[item] == '':
values[item] = values[item]
else:
value = values[item]
values[item] = float(value)
except:
raise ValueError("Values must be numbers")

self.values = values

def GetArithSolveFor(self):
"""Waits for user to click a solve for box, calls the get values
method, and identifies the solve for"""
#specified for arithmetic

while self.win.isOpen():
try:
click = self.win.getMouse()
except:
break
if 10 < click.getX() < 90 and 400 < click.getY() < 475:
self.GetArithValues()
self.SolveFor = 'PV'
break

if 90 < click.getX() < 170 and 400 < click.getY() < 475:
self.GetArithValues()
self.SolveFor = 'FV'
break

if 170 < click.getX() < 250 and 400 < click.getY() < 475:
self.GetArithValues()
self.SolveFor = 'PMT'
break

if 250 < click.getX() < 330 and 400 < click.getY() < 475:
self.GetArithValues()
self.SolveFor = 'Q'
break

if 330 < click.getX() < 410 and 400 < click.getY() < 475:
self.GetArithValues()
self.SolveFor = 'IntAmt'
break

def DisplayAnswer(self, answer, solvefor):


"""Displays what the user was trying to calculate"""

clear(self.win)
rec = Rectangle(Point(0,0),Point(500,500))
rec.setFill("white")
rec.draw(self.win)
answer = str(answer)
final = Text(Point(250,200), "The " + solvefor + " of your investment
is " + answer)
final.draw(self.win)
click = Text(Point(250, 300), "Click to see your investment grow.")
click.draw(self.win)

def arrow(self, point):


"""Draws an upward arrow at a point"""

x = point.getX()
y = point.getY()
head = Polygon(point, Point(x+10, y+20), Point(x-10, y+20))
head.setFill("black")
head.draw(self.win)
arrow = Rectangle(Point(x-3,y+30), Point(x+2, y+20))
arrow.setFill("black")
arrow.draw(self.win)

def DisplayTimeLine(self, annuity, Type):


"""Displays a time line of the user's annuity and displays the price at
each increment of time"""

rec = Rectangle(Point(0,0),Point(500,500))
rec.setFill("white")
rec.setOutline("white")
rec.draw(self.win)
line = Line(Point(15, 250), Point(485, 250))
line.draw(self.win)

#Calculate the duration of the annuity


N = annuity.CalcN()
if N == '': #Perpetuities return an empty string for N because a
perpetuity has infitite duration
sorry = Text(Point(250,230), "The price of a perpetuity never
changes")
sorry.draw(self.win)
space = 0
N = 0
else:
#make sure N is rounded and divide it into 470 (the length of the
line)
N = round(N)
space = 470 / N

#use iteration to create dashes along the timeline


for i in range(N+1):
dash = Line(Point(15 + (space*i), 255), Point(15 + (space*i), 245))
dash.draw(self.win)
text = Text(Point(15 + (space*i), 270), i)
text.setSize(5)
text.draw(self.win)

#prompts the user


sentence = Text(Point(250, 50), "Click to see the price of your
investment grow.")
sentence.draw(self.win)

#create an empty list for the loop and calculate present value
pvalues = []
PV = annuity.CalcPV()
for i in range(N+1): #creates list of all present values at each
increment of time
presentvalue = PV * ((1+annuity.IRR)**i)
pvalues.append(presentvalue)

for i in pvalues:
#identify postion in list
pos = pvalues.index(i)

#Waits for user to click anywhere


while self.win.isOpen():

try:
click3 = self.win.getMouse()
except:
break

if 0 < click3.getX() < 500 and 0 < click3.getY() < 500:

#creates arrow
self.arrow(Point(15 + (space*pos), 300))
rec = Rectangle(Point((space*pos) - (space -5) , 300),
Point((space*pos)- (space-25), 330))
rec.draw(self.win) #cover up previous arrow with white
box
rec.setFill("white")
rec.setOutline("white")

#create the present value box and text


pvbox = Rectangle(Point(100, 120), Point(400, 200))
pvbox.draw(self.win)
pvbox.setFill("white")

price = Text(Point(250, 180), i)


price.draw(self.win)

#use position as the time


pos = str(pos)
label = Text(Point(250, 140), "Price at time " + pos + ":")
label.draw(self.win)
break

def DisplayEnd(self):
"""Displays a prompt to click to exit and closes the window when the
user clicks"""

#prompts the user


end = Text(Point(250, 400), "Click to exit")
end.draw(self.win)

#Waits until user clicks anywhere and closes graphics window


while self.win.isOpen():
try:
click4 = self.win.getMouse()
except:
break
if 0 < click4.getX() < 500 and 0 < click4.getY() < 500:
break
self.win.close()

class Annuity:
"""Calculates and returns values of a regular annuity"""

def __init__(self, presentvalue, futurevalue, duration, payment,


interestrate, firstpayment):
"""Initilizes Annuity class"""

self.PV = presentvalue
self.FV = futurevalue
self.N = duration
self.PMT = payment
self.IRR = interestrate
self.FP = firstpayment

#raise an exception if values are less than zero


lst = [presentvalue, futurevalue, duration, payment, interestrate]
for i in lst:
if i == '':
i = i
elif i <= 0:
raise ValueError('Values must be positive and non-zero')

def CalcN(self):
"""Returns the duration of the annuity"""
try:
if self.N != '': #if n has already been entered, return n
n = self.N
elif self.FV == '': #if there is no future value value, use the
present value to calculate
v = x(self.IRR)
n = (math.log(1 - ((self.PV*self.IRR)/self.PMT))) /
(math.log(v))
else:
n = (math.log(((self.FV * self.IRR)/self.PMT) + 1)) /
(math.log(1 + math.IRR))
return n

except:
raise UnboundLocalError("payment, interest, and present value or
future value is needed to calculate N")

def CalcPV(self):
"""Returns the present value of the annuity"""
try:
if self.PV != '':
PV = self.PV
elif self.FV != '':
PV = self.FV * (x(self.IRR) ** self.N)
else:
if self.FP == 'immediate':
PV = self.PMT * a_angle(self.IRR, self.N)
if self.FP == 'due':
PV = self.PMT * a_doubledot(self.IRR, self.N)
return PV
except:
raise UnboundLocalError("future value or payment, interest,
duration, and the nature of the first payment are needed to calculate PV")

def CalcFV(self):
"""Returns the future value of the annuity"""

try:
if self.FV != '':
FV = self.FV
elif self.PV != '':
FV = self.PV * ((1 + self.IRR)**self.N)
else:
if self.FP == 'immediate':
FV = self.PMT * s_angle(self.IRR, self.N)
if self.FP == 'due':
FV = self.PMT * s_doubledot(self.IRR, self.N)
return FV

except:
raise UnboundLocalError("present value or payment, interest,
duration, and the nature of the first payment are needed to calculate FV")

def CalcPMT(self):
"""Returns the payment amount of the annuity"""

try:
if self.PMT != '':
PMT = self.PMT
elif self.FV == '':
if self.FP == 'immediate':
PMT = self.PV / a_angle(self.IRR, self.N)
elif self.FP == 'due':
PMT = self.PV / a_doubledot(self.IRR, self.N)
else:
if self.FP == 'immediate':
PMT = self.FV / s_angle(self.IRR, self.N)
elif self.FP == 'due':
PMT = self.FV / s_doubledot(self.IRR, self.N)
return PMT

except:
raise UnboundLocalError("present value or future value, interest,
duration, and the nature of the first payment are needed to calculate PV")

def CalcIRR(self):
"""Returns the interest rate of the annuity"""

try:
if self.IRR != '':
i = self.IRR
else:
PV = self.CalcPV()
PMT = self.CalcPMT()
a = PV / PMT
IRR = (2*(self.N - a)) / (a * (self.N + 1))
return IRR

except:
raise UnboundLocalError("present value or future value, duration,
and the nature of the first payment are needed to calculate IRR")

def CalcTotalInterest(self):
"""Returns the total interest the investor would recieve at the end of
the annuity"""

try:
PV = self.CalcPV()
PMT = self.CalcPMT()
N = self.CalcN()
totalinterest = (PMT * N) - PV
return totalinterest

except:
raise UnboundLocalError("more values are needed to calculate Total
Interest")

class Perpetuity:
"""Calculates and returns values of a perpetuity"""

def __init__(self, presentvalue, payment, interestrate, firstpayment):


"""Initilizes Perpetuity class"""

self.PV = presentvalue
self.PMT = payment
self.IRR = interestrate
self.FP = firstpayment

#raise an exception if values are less than zero


lst = [presentvalue, payment, interestrate]
for i in lst:
if i == '':
i = i
elif i <= 0:
raise ValueError('Values must be positive and non-zero')

def CalcN(self):
"""Returns an empty string to indicate an infinite duration"""

return ''

def CalcPV(self):
"""Returns the present value of the perpetuity"""

try:
if self.PV != '':
PV = self.PV
else:
if self.FP == 'immediate':
PV = self.PMT / self.IRR
elif self.FP == 'due':
d = ConvertIRtoDR(self.IRR)
PV = self.PMT / d
return PV

except:
raise UnboundLocalError("payment, interest, and the nature of the
first payment are needed to calculate PV")

def CalcPMT(self):
"""Returns the payment amount of the perpetuity"""

try:
if self.PMT != '':
PMT = self.PMT
else:
if self.FP == 'immediate':
PMT = self.PV * self.IRR
if self.FP == 'due':
d = ConvertIRtoDR(self.IRR)
PMT = self.PV * d
return PMT

except:
raise UnboundLocalError("present value, interest, and the nature of
the first payment are needed to calculate PMT")

def CalcIRR(self):
"""Returns the interest rate of the perpetuity"""

try:
if self.IRR != '':
IRR = self.IRR
else:
if self.FP == 'immediate':
IRR = self.PMT / self.PV
if self.FP == 'due':
d = self.PMT / self.PV
IRR = d / (1-d)
return IRR

except:
raise UnboundLocalError("present value, payment, and the nature of
the first payment are needed to calculate IRR")

class Geometric:
"""Calculates and returns values of a geometric annuity"""

def __init__(self, presentvalue, futurevalue, payment, k, duration,


interestrate):
"""Initilizes Geometric class"""

self.PV = presentvalue
self.FV = futurevalue
self.PMT = payment
self.K = k
self.N = duration
self.IRR = interestrate

#raise an exception if values are less than zero


lst = [presentvalue, futurevalue, k, payment, duration, interestrate]
for i in lst:
if i == '':
i = i
elif i <= 0:
raise ValueError('Values must be positive and non-zero')

def CalcN(self):
"""Returns the duration of the geometric annuity"""

try:
if self.N != '':
n = self.N
else:
PV = self.CalcPV()
n = (math.log(1-((PV*(self.IRR-self.K)) / self.PMT))) /
(math.log((1 + self.K) / (1 + self.IRR)))
return n

except:
raise UnboundLocalError("present value or future value, duration,
payment, interest, and percent increase are needed to calculate N")

def CalcPV(self):
"""Returns the present value of the geometric annuity"""

try:
if self.PV != '':
PV = self.PV
elif self.FV != '':
PV = self.FV * (x(self.IRR) ** self.N)
else:
PV = self.PMT * ((1-(((1+self.K)/(1+self.IRR))**self.N)) /
(self.IRR - self.K))
return PV

except:
raise UnboundLocalError("payment and percent increase or future
value, interest, and duration are needed to calculate PV")

def CalcFV(self):
"""Returns the future value of the geometric annuity"""

try:
if self.FV != '':
FV = self.FV
elif self.PV != '':
FV = self.PV * ((1+self.IRR)**self.N)
else:
PV = self.CalcPV()
FV = PV * ((1+self.IRR)**self.N)
return FV

except:
raise UnboundLocalError("payment and percent increase or present
value, interest, and duration are needed to calculate FV")
def CalcPMT(self):
"""Returns the initial payment amount of the geometric annuity"""

try:
if self.PMT != '':
PMT = self.PMT
elif self.PV == '':
PV = self.CalcPV()
PMT = PV / ((1-(((1+self.K)/(1+self.IRR))**self.N)) / (self.IRR
- self.K))
return PMT

except:
raise UnboundLocalError("present value or future value, interest,
percent increase, and duration are needed to calculate PMT")

def CalcTotalInterest(self):
"""Returns the total interest the investor would recieve at the end of
the annuity"""

try:
total = 0
PMT = self.CalcPMT()
N = self.CalcN()
for i in range(self.N):
total = total + (PMT*((1+self.K)**i))
PV = self.CalcPV()
totalinterest = total - PV
return totalinterest

except:
raise UnboundLocalError("more values are needed to calculate Total
Interest")

class Arithmetic:
"""Calculates and returns values of a arithmetic annuity"""

def __init__(self, presentvalue, futurevalue, payment, Q, duration,


interestrate):
"""Initilizes Arithmetic class"""

self.PV = presentvalue
self.FV = futurevalue
self.PMT = payment
self.Q = Q
self.N = duration
self.IRR = interestrate

#raise an exception if values are less than zero


lst = [presentvalue, futurevalue, payment, Q, duration, interestrate]
for i in lst:
if i == '':
i = i
elif i <= 0:
raise ValueError('Values must be positive and non-zero')

def CalcN(self):
"""Returns the duration of the arithmetic annuity"""
try:
return self.N
except:
raise UnboundLocalError("duration cannot be calculated")

def CalcPV(self):
"""Returns the present value of the arithmetic annuity"""

try:
if self.PV != '':
PV = self.PV
elif self.FV != '':
PV = self.FV * (x(self.IRR)**self.N)
else:
PV = (self.PMT * a_angle(self.IRR, self.N)) + (self.Q *
((a_angle(self.IRR, self.N) - (self.N * (x(self.IRR)**self.N)))/self.IRR))
return PV

except:
raise UnboundLocalError("payment and payment change or future
value, interest, and duration are needed to calculate PV")

def CalcFV(self):
"""Returns the future value of the arithmetic annuity"""

try:
if self.FV != '':
FV = self.FV
elif self.PV != '':
FV = self.PV * ((1+self.IRR)**self.N)
else:
FV = (self.PMT * s_angle(self.IRR, self.N)) + (self.Q
*((s_angle(self.IRR, self.N) - self.N) / self.IRR))
return FV

except:
raise UnboundLocalError("payment and payment change or present
value, interest, and duration are needed to calculate FV")

def CalcPMT(self):
"""Returns the initial payment amount of the arithmetic annuity"""

try:
if self.PMT != '':
PMT = self.PMT
elif PV == '':
PMT = (self.FV - (self.Q *((s_angle(self.IRR, self.N) - self.N)
/ self.IRR))) / s_angle(self.IRR, self.N)
elif FV == '':
PMT = (self.PV - (self.Q * ((a_angle(self.IRR, self.N) -
(self.N * (x(self.IRR)**self.N)))/self.IRR))) / a_angle(self.IRR,self.N)
return PMT

except:
raise UnboundLocalError("present value or future value, payment
change, interest, and duration are needed to calculate PMT")

def CalcQ(self):
"""Returns the change in payment amount of the arithmetic annuity"""

try:
if self.Q != '':
Q = self.Q
elif PV == '':
Q = (self.FV - (self.PMT * s_angle(self.IRR, self.N))) /
((s_angle(self.IRR, self.N) - self.N) / self.IRR)
else:
Q = (self.PV - (self.PMT * a_angle(self.IRR, self.N))) /
((a_angle(self.IRR, self.N) - (self.N * (x(self.IRR)**self.N)))/self.IRR)
return FV

except:
raise UnboundLocalError("present value or future value, payment,
interest, and duration are needed to calculate Payment Change")

def CalcTotalInterest(self):
"""Returns the total interest the investor would recieve at the end of
the annuity"""

try:
total = 0
PMT = self.CalcPMT()
N = self.CalcN()
Q = self.CalcQ()
for i in range(self.N):
total = total + PMT + (i*Q)
PV = self.CalcPV()
totalinterest = total - PV
return totalinterest

except:
raise UnboundLocalError("more values are needed to calculate Total
Interest")

def main():
#Create window, identify calculator class, and display the first screen
win = GraphWin("Annuities",500,500)
calculator = Calculator(win)
calculator.DisplayType()

#Waits for user to click a type of annuity


while calculator.win.isOpen():

try:
click = calculator.win.getMouse()
except:
break
#Displays the right values and gets the right solve for based on what
was clicked
#indexes the values dictionary to use as the parameters for the
corresponding class
if 15 < click.getX() < 240 and 200 < click.getY() < 300:
Type = 'Annuity'
calculator.DisplayRegValues()
calculator.GetRegSolveFor()
values = calculator.values
annuity = Annuity(values['PV'], values['FV'], values['N'],
values['PMT'], values['IRR'], calculator.FP)

if 260 < click.getX() < 485 and 200 < click.getY() < 300:
Type = 'Perpetuity'
calculator.DisplayPerpValues()
calculator.GetPerpSolveFor()
values = calculator.values
annuity = Perpetuity(values['PV'], values['PMT'], values['IRR'],
calculator.FP)

if 15 < click.getX() < 240 and 330 < click.getY() < 480:
Type = 'Geometric'
calculator.DisplayGeoValues()
calculator.GetGeoSolveFor()
values = calculator.values
annuity = Geometric(values['PV'], values['FV'], values['PMT'],
values['K'], values['N'], values['IRR'])

if 260 < click.getX() < 485 and 330 < click.getY() < 480:
Type = 'Arithmetic'
calculator.DisplayArithValues()
calculator.GetArithSolveFor()
values = calculator.values
annuity = Arithmetic(values['PV'], values['FV'], values['PMT'],
values['Q'], values['N'], values['IRR'])

#Calculates a value based on what SolveFor is


if calculator.SolveFor == 'FV':
answer = annuity.CalcFV()
annuity.FV = answer
if calculator.SolveFor == 'PV':
answer = annuity.CalcPV()
annuity.PV = answer
if calculator.SolveFor == 'PMT':
answer = annuity.CalcPMT()
annuity.PMT = answer
if calculator.SolveFor == 'N':
answer = annuity.CalcN()
annuity.N = answer
if calculator.SolveFor == 'IRR':
answer = annuity.CalcIRR()
annuity.IRR = answer
if calculator.SolveFor == 'Q':
answer = annuity.CalcQ()
annuity.Q = answer
if calculator.SolveFor == 'IntAmt':
answer = annuity.CalcTotalInterest()
#Display the answer to the user
calculator.DisplayAnswer(answer, calculator.SolveFor)

#Waits for user to click again to display the timeline


try:
click2 = calculator.win.getMouse()
except:
break

if 0 < click2.getX() < 500 and 0 < click2.getY() < 500:


calculator.DisplayTimeLine(annuity, Type)
break

#Displays "click to end"


calculator.DisplayEnd()

main()

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy