This is a mortgage calculator I made. I took the user’s mortgage cost, time, rate, and interest to determine the rate (monthly or yearly) payment. It also prints the final info nicely including duration, total payment, total interest, total principal, and rate payment. It asks the user if they want an Amortization Table and prints one if they do. If the user pays monthly, it will total everything after each year and print it each time. It will also let the user specify what month they start, and include each month in your time period so they know what month they are in. I have already written posts about the project if you want to read about my project, the technical information, and the program being run.

Here is a file containing the source code and how to use it.

Source Code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
"""
Author: Tanner Lebo
Name: Mortgage Amortization Calculator
Date Created: 12/3/19
Date Modified: 12/3/19

Print instructions on how to write the program. Get input from the user on loan cost, loan duration, interest, and rate(yearly or monthly).
The user won’t be able to input negative numbers or zero. The user must choose one of the options for duration and rate. Thhe program will ask
if they would like to see the table. If so, it will print the table. If not, it will end and then ask if they want to go through the program
again. The program will output their principal, total loan cost (principal + interest), and each time period’s cost based on the rate.

[x] Print final info nicely including duration, total payment, total interest, total principal,
and rate payment. (+2 pts)

[x] Asks user if they want an Amortization Table and print one if they do. (+2 pts) Include
Time Period, money to principal and interest (+2 pts), rate payment (+1 pt), and the
remaining balance (+1 pt). (Up to +6 pts)

[x] If the user pays monthly, total everything after each year and print it each time.
Requires #2. (+3 pts)

[x] If the user pays monthly, let user specify what month they start, and include
each month in your time period so they know what month they are in.
Requires #2 and #3. (+2 pts)

"""

from toolbox import get_number
from toolbox import get_integer
from toolbox import get_yes_no
from prettytable import PrettyTable
from time import sleep

def main():
    print_instructions()
    doAnother = True
    while doAnother:
        duration, amount, interest, rate, period = get_info()
        ratePayment, periodInterest, numberOfPayments, interestRate = calculate_data(duration, amount, interest, rate)
        print_table(period, ratePayment, amount, periodInterest, numberOfPayments, interestRate, rate)
        give_results(rate, ratePayment, numberOfPayments, amount, duration)
        doAnother = get_yes_no("Would you like to get a new table with entering different numbers? y/n ")
    cleanup()

def print_instructions():
    """Prints intstructions for the user"""
    print("===================================================================")
    print()
    print("                 Mortgage Amortization Calculator")
    print()
    print("===================================================================")
    print()
    print("Welcome to the Mortgage Amortization Calculator. This program will")
    print("ask for basic info like loan duration, loan amount, interest,  and")
    print("rate. It will then calculate total loan cost, interest, and the")
    print("cost for each pay period. You can also elect to have the program")
    print("display the table for you, showing how the principal, interest, and")
    print("balance changes each time. After that, you will have the chance to")
    print("enter different numbers if you'd like.")
    print()
    print("===================================================================")

This is the introduction to my program. It outlines the extra features I added. It provides an intro paragraph detailing what the program is about. It imports all the things needed for one to use the program. This shows my main, which shows everything I wrote in the program. Each procedure will go more in depth later. Finally, it shows the first part of my program. This prints instructions for the user so they know how to use my program when they run it.

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
def get_info():
    duration = get_duration()
    amount = get_loan_amount()
    interest = get_interest()
    rate, period = get_rate()
    return duration, amount, interest, rate, period

def get_duration():
    """Gets a duration of the loan from the user"""
    print()
    print("Please indicate the length of your mortgage (in years) by typing the number.")
    duration = get_integer("Loan Duration: ")
    while duration <= 0:
        duration = get_integer("You can't use anything less than 1 as a duration. Try again: ")
    duration = float(duration)
    return duration
    
def get_loan_amount():
    """Gets the total price of the loan"""
    print()
    print("Please indicate the money amount of the mortgage.")
    amount = get_integer("Loan Amount: $")
    while amount <= 0:
        amount = get_integer("You can't use anything less than 1 as the amount. Try again: $")
    amount = float(amount)
    return amount

def get_interest():
    """Gets the interest on the loan"""
    print()
    print("Please indicate the bank's yearly interest charged on the loan by just typing the number.")
    interest = get_number("Interest (percentage): ")
    while interest < 0 or interest >= 50:
        interest = get_number("Your interest must be between 0 and 50. Try again: ")
    interest = float(interest)
    return interest
    
def get_rate():
    """Gets the rate that the user will pay off the loan"""
    print()
    print("""At what rate will you be paying off this loan?
1) Monthly
2) Yearly""")
    print()
    answer = input("Loan Rate (pick an option by typing 1 or 2): ")
    while answer not in ["1", "2"]:
        answer = input("Please answer with 1 or 2: ")
    if answer == "1":
        rate = "Monthly"
        period = "Month"
    if answer == "2":
        rate = "Yearly"
        period = "Year"
    return rate, period

def calculate_data(duration, amount, interest, rate):
    """Calculates the interest rate with respect to the payments per year"""
    interest = interest/100
    if rate == "Monthly":
        paymentsPerYear = 12
    elif rate == "Yearly":
        paymentsPerYear = 1
    numberOfPayments = paymentsPerYear*duration
    interestRate = interest/paymentsPerYear
    ratePayment = calculate_payment(amount, interestRate, numberOfPayments)
    periodInterest = calculate_period_interest(interestRate, amount)
    return ratePayment, periodInterest, numberOfPayments, interestRate

def calculate_payment(amount, interestRate, numberOfPayments):
    """Calculates the monthly or yearly payment"""
    discountFactor = (((1 + interestRate)**numberOfPayments) - 1) / (interestRate*((1 + interestRate)**numberOfPayments))
    ratePayment = (amount/discountFactor)
    return ratePayment

def calculate_period_interest(interestRate, amount):
    """Calculates the starting interest for the first payment"""
    periodInterest = (interestRate) * amount
    return periodInterest

This part of my source code gets inputs from the user and calculates the basic data. It contains procedures that get inputs, such as duration, amount, rate, and interest. Once it gets this information, it uses it to calculate data. The first thing it calculates is the monthly or yearly payment, which is by itself a procedure. The other thing. it calculates its period interest, which is just the starting amount of the payment that goes to interest.

 

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
def print_table(period, ratePayment, amount, periodInterest, numberOfPayments, interestRate, rate):
    """Asks if the user wants to see the table and prints it if they do"""
    print()
    table = input("Would you like to see the Mortgage Amortization Table? y/n ")
    table.lower()
    if table == "y" or table == "yes":    
        create_table(period, ratePayment, amount, periodInterest, numberOfPayments, interestRate, rate)
        
def get_month():
    """If user chooses monthly payment, this figures out which month they start in by asking"""
    print()
    monthList = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
    month = input("What month will you pay your first payment on the mortgage? (Please enter the number that corresponds with the month) ")
    while month not in ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]:
        month = input("Please enter the number that corresponds with the month: ")
    month = float(month)
    month = month - 1
    monthIndex = int(month)
    return monthList, monthIndex
        
def create_table(period, ratePayment, amount, periodInterest, numberOfPayments, interestRate, rate):
    """Creates a mortgage amortization table based on monthly or yearly payments"""
    #
    # Gets the month from the user if they choose monthly
    #
    if rate == "Monthly":
        monthList, monthIndex = get_month()
    #
    # Engages the pretty Table module
    #
    x = PrettyTable()
    #
    # Creates headers for the table
    #
    x.field_names = [f"Year", f"{rate} Payment", "Money to Principal", "Money to Interest", "Remaining Balance"]
    principal = ratePayment-periodInterest
    remainingBalance = amount-principal
    number = 1
    if rate == "Monthly":
        totalRatePayment = 0
        totalPeriodInterest = 0
        totalPrincipal =  0
        #
        # This prints table for however long their duration it was.
        #
        for outerCounter in range(1, int(((numberOfPayments/12)+1))):
            totalRatePayment = 0
            totalPeriodInterest = 0
            totalPrincipal =  0
            #
            # This creates a table for every year, and totals everything at the end of one year.
            #
            for innerCounter in range(1, 13):
                #
                # This adds a row under the header.
                #
                x.add_row([f"{monthList[monthIndex]}", f"{money(ratePayment)}", f"{money(principal)}", f"{money(periodInterest)}", f"{money(remainingBalance)}"])
                periodInterest = interestRate * remainingBalance
                principal = ratePayment-periodInterest
                remainingBalance = remainingBalance-principal
                totalRatePayment += ratePayment
                totalPeriodInterest += periodInterest
                totalPrincipal += principal
                monthIndex += 1
                #
                # This starts the month cycle over if it gets to December.
                #
                if monthIndex == 12:
                    monthIndex = 0
                number += 1
            x.add_row([f"Totals", f"{money(totalRatePayment)}", f"{money(totalPrincipal)}", f"{money(totalPeriodInterest)}", f"{money(remainingBalance+principal)}"])
            print(x)
            #
            # This deletes all the rows so it moves on to the next year with new information.
            #
            counter = 0
            while counter < 13:
                x.del_row(0)
                counter += 1
    elif rate == "Yearly":
        for counter in range(1, int(numberOfPayments+1)):
            x.add_row([f"{period} {number}", f"{money(ratePayment)}", f"{money(principal)}", f"{money(periodInterest)}", f"{money(remainingBalance)}"])
            periodInterest = interestRate * remainingBalance
            principal = ratePayment-periodInterest
            remainingBalance = remainingBalance-principal
            number += 1
        print(x)
            
def give_results(rate, ratePayment, numberOfPayments, amount, duration):
    """Gives final information"""
    totalPayment, totalInterest = calculate_results(ratePayment, numberOfPayments, amount, duration)
    print_results(rate, duration, ratePayment, amount, totalInterest, totalPayment)

def calculate_results(ratePayment, numberOfPayments, amount, duration):
    "Calculates total payment and total interest paid on it"""
    totalPayment = ratePayment*numberOfPayments
    totalInterest = totalPayment-amount
    return totalPayment, totalInterest

def print_results(rate, duration, ratePayment, amount, totalInterest, totalPayment):
    """prints all the final iniformation"""
    #
    # This doesn't print the info until they indicate so.
    #
    enter = input("Press the enter key when you are ready to see your final information:")
    while enter != "":
        enter = input("Press press the enter key to indicate you are ready to see your final information.")
    print()
    print(f"Time Period: {int(duration)} Years")
    print()
    sleep(1)
    print(f"{rate} Payment: {money(ratePayment)}")
    print()
    sleep(1)
    print(f"Principal: {money(amount)}")
    print()
    sleep(1)
    print(f"Total Interest: {money(totalInterest)}")
    print()
    sleep(1)
    print(f"Total Payment: {money(totalPayment)}")
    sleep(1)
    

def cleanup():
    """ends the program"""
    sleep(1)
    print()
    print("Good luck paying off your mortgage!")
    print()
    print("*end*")
        



def money(number):
    """turns any number into a string that represents money"""
    number = float(number)
    number = round(number, 2)
    #
    # record if it's negative to use later
    #
    if number < 0:
        negative = True
    else:
        negative = False
    number = abs(number)
    #
    # here are the decimal point possibilities:
    # 3    : no decimal point
    # 3.   : naked decimal point
    # 3.1  : one decimal point
    # 3.14 : two decimal points
    #
    number = str(number)
    if len(number) > 1:
        #
        # 3.123 if there is a decimal in the 3rd to last spot
        #      then don't do anything
        #
        if number[-3] == ".":
            pass
        #
        # 3.1 if there is a decimal in the next to last spot
        #     then add one more decimal
        #
        elif number[-2] == ".":
            number = number + "0"
        #
        # 3.  If there is a decimal im the last spot then add
        #     one more zero.
        #
        elif number[-1] == ".":
            number = number + "00"
        else:
            number = number + ".00"
    else:
        number = number + ".00"
    number = "$" + number
    if negative:
        number = "("+number+")"
    return number

main()

The final part of my source code is the table. First, it asks if the user wants a table. If not, it’ll just print the basic information for the user. If so, it will print the table. I have two different tables for if it is yearly or monthly payments. If it is yearly, it is a more basic procedure that will just print the interest, principal, yearly payment, and remaining balance for the whole duration. If monthly, there’s another procedure. It asks and figures out what month you start the mortgage. This is so the user can see during what month they pay what. The other thing monthly does is show totals. After every year of payments, it will total everything and show you how much you paid total, and how much went to principal and interest. Finally, at the end, it prints the basic information again for you at the end, and shows how much money you paid total. Then it asks if you want to do it again. There’s another procedure at the end called “money”. This procedure just converts numbers to money with a dollar sign, so that it looks nicer.

 

 

Leave a comment

Your email address will not be published. Required fields are marked *