Skip to content

Instantly share code, notes, and snippets.

@jerivas
Last active April 26, 2017 18:11
Show Gist options
  • Save jerivas/bbce6110f2ae534bd876f02539da75a7 to your computer and use it in GitHub Desktop.
Save jerivas/bbce6110f2ae534bd876f02539da75a7 to your computer and use it in GitHub Desktop.
Loan calculator
def mortgage_calculator(form_data):
"""
Takes a single object `form_data` and returns all calculations in a `results` object.
Notes:
- The `Decimal` class simply takes any number or string and casts it into a decimal
value for calculations. See https://docs.python.org/2/library/decimal.html
- When you see '%.2f' that's simply forcing a value to be displayed with two
decimal places, i.e. 15.4504 comes out as 15.45.
"""
import math
from decimal import Decimal
results = {}
# Clean up POST data if required
if 'principal' in form_data:
form_data['principal'] = form_data['principal'].replace(',', '').replace('$', '')
if 'annual_interest_rate' in form_data:
form_data['annual_interest_rate'] = form_data['annual_interest_rate'].replace('%', '')
if 'payment_amount' in form_data:
form_data['payment_amount'] = (form_data['payment_amount'].replace(',', '').replace('$', ''))
if 'additional_payment' in form_data:
form_data['additional_payment'] = (form_data['additional_payment'].replace(',', '').replace('$', ''))
# Perform calculations
calc_type = form_data['calc_type']
principal = form_data['principal']
loan_years = form_data['loan_duration']
if loan_years == 0:
loan_years = 1
show_amort = form_data['show_amort']
no_payments = loan_years * 12
air = form_data['annual_interest_rate'] * Decimal('.01')
mir = air / 12 # E5
pow = math.pow(mir + 1, no_payments) # E6
additional_payment = form_data['additional_payment']
p_tax = form_data['property_tax']
h_ins = form_data['hazard_insurance']
m_ins = form_data['mortgage_insurance']
hoa_fees = form_data['hoa_fees']
other = form_data['other']
payment = round(mir * (principal * Decimal(pow / (pow - 1))), 2)
# Amortization schedule
amort = []
balance = principal
payment = Decimal(payment)
if additional_payment:
payment = payment + additional_payment
if p_tax:
p_tax = Decimal(p_tax)
else:
p_tax = 0
if h_ins:
h_ins = Decimal(h_ins)
else:
h_ins = 0
if m_ins:
m_ins = Decimal(m_ins)
else:
m_ins = 0
if hoa_fees:
hoa_fees = Decimal(hoa_fees)
else:
hoa_fees = 0
if other:
other = Decimal(other)
else:
other = 0
fees = Decimal(round(p_tax + h_ins + m_ins + hoa_fees + other, 2))
# Type "I" calculations
# Returns early and prevents the rest of the function from running
if calc_type == 'I':
interest_only_payment = principal * air / 12
total_payment = interest_only_payment + fees
results['interest_only_payment'] = '%.2f' % interest_only_payment
results['fees'] = fees
results['total_payment'] = '%.2f' % total_payment
return results
# Other calculations
pmt_no = 0
total_interest = 0
total_principal = 0
while (balance > 0):
pmt_no += 1
i_part = Decimal(round(balance * mir, 2))
total_interest += i_part
if balance < payment:
p_part = balance
else:
p_part = Decimal(payment - i_part)
total_principal += p_part
balance = balance - p_part
if pmt_no == no_payments:
p_part += balance
balance = 0
amort.append({'pmt_no': pmt_no,
'i_part': '%.2f' % i_part,
'p_part': '%.2f' % p_part,
'cum_prin': '%.2f' % total_principal,
'cum_int': '%.2f' % total_interest,
'balance': '%.2f' % balance})
results['show_amort'] = show_amort
results['amort'] = amort
results['fees'] = fees
results['loan_payment'] = '%.2f' % payment
results['total_payment'] = '%.2f' % (payment + fees)
results['number_payments'] = pmt_no
results['total_interest'] = round(total_interest, 2)
return results
<form action="" class="calc-form" method="post">
<label for="id_calc_type">Calculate...</label>
<select id="id_calc_type" name="calc_type">
<option value="PI">
Principal and Interest
</option>
<option value="I">
Interest Only
</option>
</select>
<label for="id_principal">Loan Amount:</label>
<input id="id_principal" name="principal" type="text">
<label for="id_loan_duration">Loan Term (in years):</label>
<input id="id_loan_duration" name="loan_duration" type="text">
<label for="id_annual_interest_rate">Annual Interest Rate:</label>
<input id="id_annual_interest_rate" name="annual_interest_rate" type="text">
<label for="id_additional_payment">(Optional) Additional Monthly Principal Payment:</label>
<input id="id_additional_payment" name="additional_payment" type="text">
<span class="helptext">(optional) See how your amortization schedule would change by accelerating payments.</span>
<label for="id_show_amort">Show Amortization Schedule:</label>
<input id="id_show_amort" name="show_amort" type="checkbox">
<label for="id_property_tax">Monthly Property Tax:</label>
<input class="fees" id="id_property_tax" name="property_tax" type="text" value="0">
<label for="id_hazard_insurance">Monthly Hazard Insurace:</label>
<input class="fees" id="id_hazard_insurance" name="hazard_insurance" type="text" value="0">
<label for="id_mortgage_insurance">Monthly Mortgage Insurance:</label>
<input class="fees" id="id_mortgage_insurance" name="mortgage_insurance" type="text" value="0">
<label for="id_hoa_fees">Monthly HOA Dues:</label>
<input class="fees" id="id_hoa_fees" name="hoa_fees" type="text" value="0">
<label for="id_other">Other:</label>
<input class="fees" id="id_other" name="other" type="text" value="0">
</form>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment