Last active
May 31, 2020 13:56
-
-
Save MichaelChirico/9bad2525da2f932e8ef9a78b15c95c14 to your computer and use it in GitHub Desktop.
A simple simulation of loan repayments
This file contains hidden or 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
| P0 = c(...) # initial principal | |
| R = c(...) # annualized interest | |
| r = (1+R)^(1/12)-1 # monthly interest | |
| np = length(P0) | |
| X = ... # monthly willingness-to-pay | |
| BB = 1e7 # repetitions | |
| # slightly more principled... find how many months it takes if | |
| # all loans are combined at the highest interest rate | |
| # PP = sum(P0); rr = max(r) | |
| # optim(20, method='Brent', lower=0, upper=600, | |
| # function(t) (PP*(1+r)^t - X*t)^2) | |
| JJ = 50L # max payments [could be more general than just guessing...] | |
| sequence = vector('list', BB) | |
| for (ii in seq_along(sequence)) { | |
| P = P0 | |
| pmts = matrix(0, nrow = JJ, ncol = np) # defaults to 0, useful for once one is paid off | |
| jj = 1L | |
| while (jj <= JJ && any(to_pay <- P > 0)) { | |
| # random search --> uniform random guess of payments | |
| p = runif(sum(to_pay)) # random payments; normalize to sum to X next | |
| pmts[jj, to_pay] = X*p/sum(p) | |
| P = (1+r)*(P - pmts[jj, ]) | |
| while (any(neg_idx <- P < 0) && any(pos_idx <- P > 0)) { # overpayment loop... not 100% sure it's finite | |
| distr = sum(abs(P[neg_idx]))/sum(pos_idx) | |
| P[pos_idx] = P[pos_idx] - distr | |
| P[neg_idx] = 0 | |
| } | |
| jj = jj + 1L | |
| } | |
| sequence[[ii]] = pmts[1:(jj-1L), ] | |
| } | |
| table(vapply(sequence, nrow, 1L)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment