Skip to content

Instantly share code, notes, and snippets.

@grantmcdermott
Last active July 14, 2020 17:33
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 grantmcdermott/58c9f7f34d286e1512a8637b58d92256 to your computer and use it in GitHub Desktop.
Save grantmcdermott/58c9f7f34d286e1512a8637b58d92256 to your computer and use it in GitHub Desktop.
Compare 15- vs 30-yr refi
#' Compare expected returns of 15- vs 30-year home refi.
#'
#' This very simple function assumes you split your disposable income between
#' mortgage repayments and stock investments. The goal is to compare ROI at the end
#' of 30 years, assuming you initially have a choice between 15- and 30-year fixed rate
#' mortgage.
#'
#' @details Under the 15-year scenario, we assume that you pay the monthly premium
#' until the loan is fully repaid (i.e. after 15 years) and then immediately switch
#' over to investing the exact same amount for another 15 years. Under the 30-year
#' scenario, you are assumed to invest the difference between the 15-year and 30-year
#' monthly repayments over the full lifetime of the 30-year loan.
#' To keep things simple, we ignore things like uncertainty, risk premia, tax
#' considerations (e.g. deductions on mortgage interest), early repayments leverage,
#' cash flow discounting, etc.
#'
#' @param p Principle. How much is your mortgage loan/refi? Defaults to $250k.
#' @param i15 Interest rate (APR) on 15-year fixed mortage. Expected to be entered
#' in percentage terms (i.e. 2.5 rather than 0.025) and defaults to 2.5%.
#' @param i30 Interest rate (APR) on 30-year fixed mortgage. Expected to be entered
#' in percentage terms (i.e. 3 rather than 0.03) and defaults to 3%.
#' @param r Expected annual market return. Defaults to 7.5% (S&P average from last
#' 30 years).
#' @param madj Adjusted monthly investment (based on 30-vs-15 yr spread). Default
#' value of 1 assumes you fully invest difference between 30- and 15-year monthly
#' premiums. For example, if the implied monthly repayment for the 15-year
#' mortgage is $2,000 versus $1,400 for the 30-year, then you are assumed to
#' invest the full $600 difference every month. If, say, madj=0.5 then the
#' function assumes you only invest half of that (i.e. $300).
#' @return A data frame comparing investment value under the 15-year vs 30-year
#' scenarios. Contains eight columns: principle amount (p); interest rates on
#' the 15- and 30-year loans (i15 and i30); market return rate (r); implied
#' monthly premiums on the 15- and 30-year loans (m15 and m30); and the final
#' net investment value at the end of two scenarios (roi15 and roi30), i.e.
#' after subracting the total loan payments.
#' @examples
#' ## Default values:
#' refi()
#' ## Next try higher principle, lower 30-year and mkt rates, and only invest half
#' ## of the implied diff between 15 and 30-yr monthly premiums.
#' refi(p=3e6, i30=2.9, r=6, madj=0.5)
#' ## Sensitivity analysis examples
#' library(purrr)
#' ## sensitivity to change market return
#' map_df(4:10, function(r) refi(r=r))
#' ## sensitivity to random combinations of market return and adjusted monthly
#' ## investment
#' pmap_dfr(list(r=runif(10, 3, 10), madj=runif(10, 0.1, 1)),
#' function(r, madj) refi(r=r, madj = madj))
refi = function(p=250000, i15=2.5, i30=3.0, r=7.5, madj=1) {
## mortage annuity calc (i.e. monthly premium)
annuity = function(p, i, y) {
i = i / 100 / 12
n = y * 12
a = p * (i + i/((1+i)^n - 1))
return(a)
}
## investment calc
investment = function(m, r, y) {
r = r / 100
n = 12
t = y
fv = m * (((1 + r/n)^(n*t) - 1) / (r/n)) * (1+r/n)
return(fv)
}
## plug in the numbers
m30 = annuity(p, i30, 30)
m15 = annuity(p, i15, 15)
roi30 = investment(madj*(m15-m30), r, 30) - 30*12*m30
roi15 = investment(m15-(1-madj)*(m15-m30), r, 15) - 15*12*m15
data.frame(p, i15, i30, r, m15, m30, roi15, roi30)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment