Skip to content

Instantly share code, notes, and snippets.

@yig
Created April 2, 2020 13:34
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 yig/6eb1c3170e6e2e05df810fca8e47f3ca to your computer and use it in GitHub Desktop.
Save yig/6eb1c3170e6e2e05df810fca8e47f3ca to your computer and use it in GitHub Desktop.
Two useful functions for calculating lifetime mortgage payments
## Author: Yotam Gingold <yotam@yotamgingold.com>
## License: Public domain, CC0: https://creativecommons.org/share-your-work/public-domain/cc0/
## URL: https://gist.github.com/yig/6eb1c3170e6e2e05df810fca8e47f3ca
"""
You can calculate your monthly payment for a loan for X years with interest rate Y%. For example:
> monthly_payment_for_termination_in_X_years( years = 30, principal = 300_000, interest_rate_per_year = 3.75/100 )
$1389.35
At the end of your loan, how much will you have paid?
> $1389.35/month * 30 years * 12 months/year
= $500,166
But you could also pay more per month. Let's say you are willing to spend a fixed budget of $2182 on your mortgage each year. Then we can ask how long it would take to pay off the loan:
> years_to_payoff_loan_given_payment_amount( principal = 300_000, interest_rate_per_year = 3.75/100, payment_amount = 2182 )
15.00 years
So by paying $2182/month, you've turned your 30-year loan into a 15-year loan with a higher interest rate. How much will you pay in total over the lifetime of the loan?
> $2182/month * 15 years * 12 months/year
= $392,760
You saved $500,166 - $392,760 = $107,406.
Let's refinance. We'll refinance for a 15 year loan with a better interest rate: 3.65%. Your required monthly payments would be:
> monthly_payment_for_termination_in_X_years( years = 15, principal = 300_000, interest_rate_per_year = 3.65/100 )
$2166.81
At the end of this 15-year loan, you will have paid:
> $2166.81/month * 15 years * 12 months/year
$390,025.80
Refinancing saved you $2,734.20 over a 15-year period.
But you were willing to pay $2182/month. How long would it take you to pay off the refinanced loan at the lower interest rate?
> years_to_payoff_loan_given_payment_amount( principal = 300_000, interest_rate_per_year = 3.65/100, payment_amount = 2182 )
14.86 years
If you pay that, over the lifetime of the loan you will have paid:
> $2182/month * 14.86 years * 12 months/year
$389,094.24
So if your budget allows you to pay $2182/month, you will save $3,665.76 by refinancing over a 15-year period.
If your budget is fixed, the only thing that matters is the interest rate. In this case, it saved you $21/month.
"""
from __future__ import print_function, division
def monthly_payment_for_termination_in_X_years( years, principal, interest_rate_per_year ):
'''
Given:
years: The number of years to pay off the loan in (e.g. 30 for a 30 year loan)
principal: The loan amount
interest_rate_per_year: The amount of interest paid per year (e.g. 3.875/100 for a loan whose interest rate is 3.875)
Returns:
Monthly payment so that the loan is paid off after `months` months.
'''
## Formula from: https://medium.com/towards-artificial-intelligence/mortgage-calculator-python-code-94d976d25a27
months = years*12
interest_rate_per_month = interest_rate_per_year/12
R = 1 + interest_rate_per_month
return principal * R**months * ( 1 - R ) / ( 1 - R**months )
def years_to_payoff_loan_given_payment_amount( principal, interest_rate_per_year, payment_amount, pay_until_balance = 0 ):
'''
Given:
principal: The loan amount
interest_rate_per_year: The amount of interest paid per year (e.g. 3.875/100 for a loan whose interest rate is 3.875)
payment_amount: The amount paid per month
Returns:
The number of years the loan will be paid off in (e.g. 30 for a 30 year loan paid at the rate returned by monthly_payment_for_termination_in_X_years())
'''
## Formula from: https://medium.com/towards-artificial-intelligence/mortgage-calculator-python-code-94d976d25a27
interest_rate_per_month = interest_rate_per_year/12
R = 1 + interest_rate_per_month
P0 = principal
X = payment_amount
B = pay_until_balance
'''
P_m = P0 R^m - X ( 1 - R^m ) / ( 1 - R )
where
P0 is the initial loan amount `principal`
P_m is the remaining balance after m months
X is the monthly payment amount
We want to solve for m given X, R, P0.
In other words, find m such that P_m = 0.
P_m = 0 = P0 R^m - X ( 1 - R^m ) / ( 1 - R )
<=>
0 = P0 R^m - X / ( 1 - R ) + X R^m / ( 1 - R )
<=>
X / (1-R) = R^m ( P0 + X / ( 1 - R ) )
<=>
X / ( (1-R) * ( P0 + X/(1-R) ) ) = R^m
<=>
log( X / ( (1-R) * ( P0 + X/(1-R) ) ) ) = m log R
<=>
m = log( X / ( (1-R) * ( P0 + X/(1-R) ) ) ) / log R
'''
from math import log
# months = log( X / ( (1-R) * ( P0 + X/(1-R) ) ) ) / log(R)
'''
The derivation is similar if we want to find m such that P_m = B.
P_m = B = P0 R^m - X ( 1 - R^m ) / ( 1 - R )
<=>
B = P0 R^m - X / ( 1 - R ) + X R^m / ( 1 - R )
<=>
B + X / (1-R) = R^m ( P0 + X / ( 1 - R ) )
<=>
( B + X/(1-R) ) / ( P0 + X/(1-R) ) = R^m
<=>
log( B + X/(1-R) ) / ( P0 + X/(1-R) ) = m log R
<=>
m = log( B + X/(1-R) ) / ( P0 + X/(1-R) ) / log R
'''
months = log( ( B + X/(1-R) ) / ( P0 + X/(1-R) ) ) / log(R)
return months/12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment