Created
April 2, 2020 13:34
-
-
Save yig/6eb1c3170e6e2e05df810fca8e47f3ca to your computer and use it in GitHub Desktop.
Two useful functions for calculating lifetime mortgage payments
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## 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