Skip to content

Instantly share code, notes, and snippets.

@jlinoff
Last active March 9, 2021 14:45
Show Gist options
  • Save jlinoff/1b9957e313be8fad70b5eb99b814c950 to your computer and use it in GitHub Desktop.
Save jlinoff/1b9957e313be8fad70b5eb99b814c950 to your computer and use it in GitHub Desktop.
Simple PMI calculator that accepts the loan amount, interest and term in years.
#!/usr/bin/env python2.7
'''
Simple PMI calculator for monthly payments.
Enter the loan amount, the annual interest rate and the number
of years.
'''
import sys
def pmi(amt, interest, term, ppyr=12):
'''
Create an amortization schedule based on the term
of the loan.
@param amt The total amount of the loan.
@param interest The interest rate.
@param term Term of the loan.
'''
# CITATION: https://www.mtgprofessor.com/formulas.htm
# CITATION: https://en.wikipedia.org/wiki/Amortization_calculator
# pylint: disable=too-many-locals
famt = float(amt)
fint = float(interest)
term = int(term)
pir = fint / float(ppyr) # periodic interest rate
pay = famt * (pir + (pir / (((1. + pir) ** term) - 1.)))
total_paid = pay * term
interest_paid = total_paid - famt
fmt = ' {:>2} {:>4} {:>12} {:>12} {:>12} {:>12} {:>12}'
def currency(val):
'''
Convert to currency.
'''
return '${:,.2f}'.format(val)
# pylint: disable=superfluous-parens
print('')
print('Amount: {:>12}'.format(currency(famt)))
print('Interest: {:12,.2f} {:.2f}%'.format(fint, 100. * fint))
print('Term: {:12,}'.format(term))
print('PerInt: {:12,.4f} {:.2f}%'.format(pir, 100. * pir))
print('Payment: {:>12}'.format(currency(pay)))
print('Total: {:>12}'.format(currency(total_paid)))
print('TotalInt: {:>12}'.format(currency(interest_paid)))
print('')
print(fmt.format('Yr',
'Per',
'Principal',
'Payment',
'PrincPaid',
'IntPaid',
'AccTotal'))
# pylint: enable=superfluous-parens
prev_total_paid_off = 0
acc_payments = pay
for i in range(1, term+1):
num = ((1. + pir) ** i) - 1
div = ((1. + pir) ** term) - 1
pri = famt * (1. - (num / div)) # principal remaining
total_paid_off = famt - pri
paid_off_this_period = total_paid_off - prev_total_paid_off
interest_paid = pay - paid_off_this_period
# pylint: disable=superfluous-parens
print(fmt.format(((i+11)//12),
i,
currency(pri),
currency(pay),
currency(paid_off_this_period),
currency(interest_paid),
currency(acc_payments)))
# pylint: enable=superfluous-parens
prev_total_paid_off = total_paid_off
acc_payments += pay
# pylint: enable=too-many-locals
def main():
'''
Main
'''
def get_val(prompt, i):
'''
Get a value.
'''
if len(sys.argv) > i:
return sys.argv[i]
val = raw_input(prompt)
try:
float(val)
except ValueError:
sys.stderr.write('ERROR: Not a valid number for "{}".\n'.format(prompt))
sys.exit(1)
amount = get_val('Loan amount? ', 1)
interest = get_val('Interest rate? ', 2)
term = int(get_val('Number of years? ', 3))
pmi(amount, interest, term*12)
if __name__ == '__main__':
main()
@jlinoff
Copy link
Author

jlinoff commented Nov 22, 2017

Updated to work with python-3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment