Advertisement
Guest User

Untitled

a guest
Feb 29th, 2020
298
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.12 KB | None | 0 0
  1. import pandas as pd
  2. import numpy as np
  3. import datetime as dt
  4. import matplotlib.pyplot as plt
  5. import matplotlib.ticker as mtick
  6. plt.style.use('fivethirtyeight')
  7.  
  8. def calc_payment_breakdown(period_rate, period, n_periods, principal):
  9.     ipmt = np.ipmt(period_rate, period, n_periods, principal)
  10.     ppmt = np.ppmt(period_rate, period, n_periods, principal)
  11.     return ipmt, ppmt
  12.  
  13. def gen_schedule(loan_amount, rate, start_date, length, pn=12):
  14.     n_periods = length
  15.     period_rate = rate / pn
  16.    
  17.     tpmt = np.pmt(period_rate, n_periods, loan_amount)
  18.     period_values = [(i, tpmt, *calc_payment_breakdown(period_rate, i, n_periods, loan_amount))
  19.                      for i in range(1, n_periods+1)]
  20.     ix = pd.date_range(start_date, periods=n_periods, freq='MS')
  21.    
  22.     cols = ['n', 'Payment', 'Interest', 'Principal']
  23.     df = pd.DataFrame(period_values, columns=cols, index=ix)
  24.     df['Balance'] = (loan_amount - (-1*df.Principal.cumsum()))
  25.     df['Equity'] = df['Principal'].abs().cumsum()
  26.    
  27.     return df
  28.  
  29. def calc_closing_costs(rate, credits, loan_amount=359572):
  30.     loan_costs = 2122
  31.     # other costs
  32.     taxes_fees = 120
  33.     # prepaids
  34.     prepaid_prop_tax = 4801
  35.     loan_amnt_15days = loan_amount / 360 * 15
  36.     # escrow
  37.     homeowners_insurance = 291
  38.     property_taxes = 3201
  39.    
  40.     rate_indepedent = (loan_costs +
  41.                        taxes_fees +
  42.                        prepaid_prop_tax +
  43.                        homeowners_insurance +
  44.                        property_taxes)
  45.     return rate_indepedent + loan_amnt_15days*rate + credits
  46.  
  47. def calc_comparison(current, new, closing=0):
  48.     merged = pd.merge(current, new, how='outer', left_index=True, right_index=True)
  49.    
  50.     cash_diff = (merged.Payment_x.abs().fillna(0).cumsum() -
  51.                  (merged.Payment_y.abs().fillna(0).cumsum() + closing))
  52.     principal_diff = (merged.Principal_x.abs().fillna(0).cumsum() -
  53.                       merged.Principal_y.abs().fillna(0).cumsum())
  54.     total_savings = cash_diff - principal_diff
  55.    
  56.     return cash_diff, principal_diff, total_savings
  57.  
  58. def calc_payments(current, new, term):
  59.     current_pmi = 182.16
  60.     total_escrow = 1125.86
  61.     escrow = total_escrow - current_pmi
  62.     new_pmi = {20: 54, 30: 93}
  63.    
  64.     current_payment = current.Payment.abs().mean() + total_escrow
  65.     new_payment = new.Payment.abs().mean() + escrow + new_pmi[term]
  66.    
  67.     return current_payment, new_payment
  68.  
  69. def plot_savings(term, rate, savings, axes):
  70.     ax1, ax2 = axes
  71.     label = f'{term} yr @ {rate}%'
  72.     ax1.scatter(savings.index, savings, marker='.', label=label)
  73.     ax1.legend(fontsize=12, markerscale=2)
  74.    
  75.     m = (savings.index ==  start_date) | ((savings.index.year <= 2030) & (savings.index.month == 4))
  76.     ax2.scatter(savings.index[m], savings[m], label=label)
  77.     ax2.legend(fontsize=12)
  78.    
  79.     for ax in (ax1, ax2):
  80.         ylbls = [f'${y/1000:0.0f}K' for y in ax.get_yticks()]
  81.         ax.set_yticklabels(ylbls)
  82.         ax.set_ylabel('Total Savings', fontsize=18)
  83.         ax.set_xlabel('Date', fontsize=18)
  84.  
  85. ## CONSTANTS
  86. base_schedule = gen_schedule(370500, 0.04625, '2018-05-01', 360)
  87. past_schedule = base_schedule.loc[:'2020-04-01']
  88. current_schedule = base_schedule.loc['2020-05-01':]
  89.  
  90. current_amount = past_schedule.Balance.values[-2]
  91.  
  92. # rate options
  93. options = [(3.125, 2701, 30),
  94.            (3.25, 162, 30),
  95.            (3.375, -1762, 30),
  96.            (3.125, 1571, 20),
  97.            (3.25, -762, 20),
  98.            (3.375, -2636, 20),
  99.           ]
  100. escrow_balance = 5788
  101. start_date = '2020-05-01'
  102.  
  103. ##########################################
  104. ## Closing Paid in Cash at Close
  105. ##########################################
  106.  
  107. f, (ax1, ax2) = plt.subplots(2, figsize=(12, 18))
  108. for (rate, points, term) in options:
  109.     rate /= 100
  110.    
  111.     closing = calc_closing_costs(rate, points)
  112.    
  113.     new_schedule = gen_schedule(current_amount, rate, start_date, term*12)
  114.     cash, equity, savings = calc_comparison(current_schedule, new_schedule, closing)
  115.     current_payment, new_payment = calc_payments(current_schedule, new_schedule, term)
  116.     payment_diff = current_payment - new_payment
  117.  
  118.     breakeven = savings.loc[savings > 0].head(1)
  119.    
  120.     rate *= 100
  121.     print(f'Rate {rate}%, Points ${points}, Term {term}')
  122.     print(f'\tClosing Due: ${closing:0.2f}, Less Escrow Balance: ${closing-escrow_balance:0.2f}')
  123.     print(f'\tRecoup Closing On: {breakeven.index[0].strftime("%Y-%m-%d")}, ${breakeven.values[0]:0.2f}')
  124.     print(f'\tMonthly Payments: Current ${current_payment:0.2f}, New ${new_payment:0.2f}, '
  125.           f'Difference:${payment_diff:0.2f}')
  126.     print()
  127.     plot_savings(term, rate, savings, (ax1, ax2))
  128.     f.suptitle('Refinance Rate Comparison\nClosing Costs Paid in Full at Close', fontsize=18, y=0.92)
  129.  
  130. ##########################################
  131. ## Closing Built in to Loan
  132. ##########################################
  133.  
  134. f, (ax1, ax2) = plt.subplots(2, figsize=(12, 18))
  135. for (rate, points, term) in options:
  136.     rate /= 100
  137.    
  138.     # cap addition to loan at $10K
  139.     closing = calc_closing_costs(rate, points)
  140.     if closing > 10000:
  141.         to_add = 10000
  142.     else:
  143.         to_add = closing
  144.     closing -= to_add
  145.    
  146.     new_schedule = gen_schedule(current_amount + to_add, rate, start_date, term*12)
  147.     cash, equity, savings = calc_comparison(current_schedule, new_schedule, closing)
  148.     current_payment, new_payment = calc_payments(current_schedule, new_schedule, term)
  149.     payment_diff = current_payment - new_payment
  150.  
  151.     breakeven = savings.loc[savings > 0].head(1)
  152.    
  153.     rate *= 100
  154.     print(f'Rate {rate}%, Points ${points}, Term {term}')
  155.     print(f'\tClosing Due: ${closing:0.2f}, Less Escrow Balance: ${closing-escrow_balance:0.2f}')
  156.     print(f'\tRecoup Closing On: {breakeven.index[0].strftime("%Y-%m-%d")}, ${breakeven.values[0]:0.2f}')
  157.     print(f'\tMonthly Payments: Current ${current_payment:0.2f}, New ${new_payment:0.2f}, '
  158.           f'Difference:${payment_diff:0.2f}')
  159.     print()
  160.     plot_savings(term, rate, savings, (ax1, ax2))
  161.     f.suptitle('Refinance Rate Comparison\nClosing Costs Added to Loan ($10K max)', fontsize=18, y=0.92)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement