Skip to content

Instantly share code, notes, and snippets.

@dylanjm
Created December 3, 2020 03:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dylanjm/76fce047adcc9a362c3bd646da1d36bf to your computer and use it in GitHub Desktop.
Save dylanjm/76fce047adcc9a362c3bd646da1d36bf to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import textwrap
from tabulate import tabulate
def amort(principal, rate, n):
return principal * (rate * ((1 + rate) ** n)) / ((1 + rate) ** n - 1)
def compute_schedule(bal, pmt, rate):
while bal > 0:
new_bal = bal - (pmt - (bal * rate))
period_interest = (bal * rate)
period_principal = pmt - (bal * rate)
if new_bal > 0:
yield (new_bal, period_interest, period_principal)
bal = new_bal
def amort_table(loan_amt, pmt, rate):
df = pd.DataFrame(
columns=['Amount', 'Interest', 'Principal', 'Balance'],
index = np.arange(1, 361, 1)
)
for x, (b, i, p) in enumerate(compute_schedule(loan_amt, pmt, rate)):
df.loc[x + 1] = pd.Series(
{
'Amount': round(pmt, 2),
'Interest': round(i, 2),
'Principal': round(p, 2),
'Balance': round(b, 2)
}
)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.bar(np.arange(1, 361, 1), df.Principal, 1, label="Principal")
ax.bar(np.arange(1, 361, 1), df.Interest, 1, bottom=df.Principal, label="Interest")
ax2 = ax.twinx()
ax2.plot(np.arange(1, 361, 1), df.Balance, color='red')
ax.legend(loc='upper right')
plt.show()
# print(df.to_markdown())
def dollar_fmt(var):
return f'${var:>12,.2f}'
def indent(txt, spaces=2):
return "\n".join(" "*spaces + ln for ln in txt.splitlines())
class color:
PURPLE = '\033[95m'
CYAN = '\033[96m'
DARKCYAN = '\033[36m'
BLUE = '\033[94m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
END = '\033[0m'
def main():
required_fha = 331_760.00
asking_price = 349_000.00
closing_costs_percent = 0.015
closing_costs = closing_costs_percent * asking_price
purchase = asking_price + closing_costs
pct_down = 0.05
down_pmt = purchase * pct_down
loan_amt = purchase - down_pmt
annual_rate = 0.0375
rate = annual_rate / 12
n = 30 * 12
if loan_amt - required_fha > 0:
loan_fha_str = color.RED + f'${loan_amt - required_fha:>12,.2f}' + color.END
else:
loan_fha_str = color.GREEN + f'${loan_amt - required_fha:>12,.2f}' + color.END
print('\n' + color.UNDERLINE + color.BLUE + color.BOLD + "Loan Terms:" + color.END)
inputs_table = [
['Asking Price:', dollar_fmt(asking_price)],
['Closing Costs:', dollar_fmt(closing_costs), f'@ {closing_costs_percent*100:.2f}% asking price'],
['Purchase Price:', dollar_fmt(purchase)],
['Down Payment:', f'${down_pmt:>12,.2f}', f'@ {pct_down*100:.2f}% purchase price'],
['Loan Amount:', f'${loan_amt:>12,.2f}'],
['FHA Maximum:', f'${required_fha:>12,.2f}', 'low-cost region maximum'],
['Δ FHA/Loan:', f'{loan_fha_str}', 'constrained: Δ < 0'],
['Period Rate:', f'{rate*100:.2f}%', f'@ {annual_rate*100:.2f}% fixed annual'],
['Periods:', n]
]
for row in inputs_table:
row[0] = color.BOLD + row[0] + color.END
print(indent(tabulate(inputs_table, colalign=('left', 'right', 'right'), tablefmt='plain')))
print('\n' + color.UNDERLINE + color.BLUE + color.BOLD + "Monthly Summary:" + color.END)
annual_pmi = loan_amt * 0.0082
monthly_pmi = annual_pmi / 12
annual_taxes = 1700.00
monthly_taxes = 1700.00 / 12
annual_insurance = 727.32
monthly_insurance = annual_insurance / 12
monthly_pmt = amort(loan_amt, rate, n)
monthly_total = monthly_pmt + monthly_taxes + monthly_pmi + monthly_insurance
pmt_table = [
['Monthly Payment:', f'${monthly_pmt:>10,.2f}'],
['Property Taxes:', f'${monthly_taxes:>10,.2f}', f'@ ${annual_taxes:>9,.2f} Annual'],
['Mortgage Insurance:', f'${monthly_pmi:>10,.2f}', f'@ ${annual_pmi:>9,.2f} Annual'],
['Home Insurance:', f'${monthly_insurance:>10,.2f}', f'@ ${annual_insurance*12:>9,.2f} Annual'],
['Total Monthly Payment:', f'${monthly_total:>10,.2f}']
]
for row in pmt_table:
row[0] = color.BOLD + row[0] + color.END
print(indent(tabulate(pmt_table, colalign=('left', 'right', 'right'), tablefmt='plain')))
gs_savings = 15_500
ally_savings = 1_200
car_money = 1_300
total_savings = gs_savings + ally_savings + car_money
inspections = 800
break_lease = 1_200
moving = 500
total_expenses = down_pmt + inspections + break_lease + moving
remaining_reserves = total_savings - total_expenses
if remaining_reserves < 0:
remaining_reserves_str = color.RED + f'${remaining_reserves:>12,.2f}' + color.END
else:
remaining_reserves_str = color.GREEN + f'${remaining_reserves:>12,.2f}' + color.END
print('\n' + color.UNDERLINE + color.BLUE + color.BOLD + "Expenses Summary:" + color.END)
upfront = [
['Total Savings:', f'${total_savings:>12,.2f}'],
['Total Expenses:', f'${(total_expenses)*-1:>12,.2f}'],
[' - Down Payment', f'${down_pmt*-1:>12,.2f}'],
[' - Inspections & Appraisal', f'${inspections*-1:>12,.2f}'],
[' - Break Lease', f'${break_lease*-1:>12,.2f}'],
[' - Moving', f'${moving*-1:>12,.2f}'],
['Remaining:', remaining_reserves_str]
]
for row in upfront:
row[0] = color.BOLD + row[0] + color.END
print(indent(tabulate(upfront, colalign=('left', 'right'), tablefmt='plain')))
print('\n' + color.UNDERLINE + color.BLUE + color.BOLD + "Financial Summary:" + color.END)
savings = [
['Goldman Sachs', f'$ {gs_savings:,.2f}'],
['Ally', f'$ {ally_savings:,.2f}'],
['Car Money', f'$ {car_money:,.2f}'],
['Total Saved', f'${gs_savings + ally_savings + car_money:,.2f}']
]
pay_rate = 6_228
annual_salary = pay_rate * 12
debt_ratio = (monthly_total / pay_rate) * 100
pay_rates = [
['Pay Rate:', f'${pay_rate:>10,.2f}'],
['Annual Salary:', f'${annual_salary:>10,.2f}'],
['Mortgage-Income Ratio:', f'{debt_ratio:,.2f}%']
]
for row in pay_rates:
row[0] = color.BOLD + row[0] + color.END
print(indent(tabulate(pay_rates, colalign=('left', 'right'), tablefmt='plain')))
# print(tabulate(savings, colalign=('left', 'right')))
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment