Sunday, June 27, 2010

student loans: my trick on how to pay them off faster

regarding my loans, i saved roughly $250 within a 12-month span. you can too.

short version:
i wrote a little java program that uses simulated annealing to find the near-optimal solution of how to distribute your monthly loan payment amongst your various loans every month, while minimizing the amount of accrued interest.


the above .zip file contains 3
files:
for example, run it from a command prompt:
>> java InterestOptimizerTest input.txt


long version:

if you have many loans which total a lot of money, you may be waisting 100s of dollars merely by incorrectly paying the wrong amounts towards each loan. the point of this writing is to help you save money.

obviously, one can save/waste a lot of money depending on when and how much they pay off their loans. this isn't about that. say you have 6 loans and $1,000 you wish to pay towards them. this writing is about how to apply your $1,000 towards the 6 individual loans in the best possible way so that you aren't wasting money. interest is a killer. below, i mention my approaches towards minimizing the interest, and i provide my actual student loans as an example:

upon graduating from ucla last year, my student loans totaled roughly $78,000. it's been 13 months since i've graduated, and i've gotten them down to $27,000. here are my 6 outstanding loans:

loan name, balance, APR, minimum monthly payment
-------------------------
sallie mae 1, $13472.75, 2.58%, $201.03
sallie mae 2, $1544.54, 7.25%, $214.74
sallie mae 3, $5032.22, 6.8%, $221.29
doe 1, $521.06, 8.5%, $52.61
doe 2, $2378.14, 6.8%, $59.50
ecsi, $4495.36, 5.0%, $60.46

for the rest of this article, let's be consistent and say that i pay $2,000 each month.


idea #1 - naive approach based on distribution of annual interest:
this is what i had been doing the whole time. when i had to start paying back my school loans, i didn't give it much thought as to how i would determine how much to spend towards each. i just quickly thought, 'i'll just pay some amount that is proportional to how damaging the interest is.' i now regret not thinking about it more.

the amount i was paying towards each loan was merely determined by its contribution towards my total annual interest across all loans:

loan i's payment := $2,000 * (loan i's yearly interest / total yearly interest across all loans)



idea #2 - brainstorming + linear/non-linear programming:
after filing my taxes, i noticed i paid a lot towards loan interest this past year. so, while brushing my teeth in the morning, i thought to myself that my current method (idea #1) is probably much worse than what i imagined. how can i find the optimal solution? first thing that popped into my mind was to search the solution space by using a genetic algorithm, but by the time i finished brushing my teeth, i had convinced myself that the sheer thought of such was complete overkill, laughable, and non-optimal, and clearly not the best approach.

throughout the day, i thought about other approaches:

linear/non-linear programming:
the idea of using linear programming came to mind. the format would be:

minimize C^T * x || sum(x) = b, where
  • C is a vector of known coefficients that represent the interest for each loan
  • x is a vector we are solving for, which represents how much to spend on each loan
  • b represents how much we are willing to spend in a given month (i.e., $2,000)
in other words, we want an equation for our total interest across a given time period (1 month), and we want to minimize it. but unfortunately, we can't really form a linear equation for it. for example, the interest for one loan would be:

loan i's interest = (loan_i's_original_balance - how_much_to_pay_towards_loan_i) * (1 + APR/365.25)^30

we are minimizing the sum of this value across all loans.

that exponent makes it non-linear. moreover, i'm not sure how to solve it using non-linear programming either, as we no longer have a clean coefficient. we don't have an Ax = b; we have f(x) = b

maybe there's some way to use the simplex algorithm for this, but i wasn't interested in finding out. seems messy.



idea #3 - simulated annealing:

well, when all else fails, use simulated annealing, right? haha. simulated annealing is a pretty simple, common AI approach that seeks to find an optimal solution within a large search space.

i implemented it in a little java program.

basically, it:
  • initially assigns random payment amounts towards each loan, while meeting the constraints of the minimum and maximum payment for each loan.
  • it then calculates the total monthly interest across all loans.
  • then, for however many epochs i care to run my algorithm, it will:

    • randomly decide to increase or decrease a to-be-selected loan,
    • then the loan it chooses to adjust is probabilistically chosen, based on each loan's contribution towards the total amount of interest across all loans.
    • the amount that it perturbs the loans is randomly chosen, too.
    • if the new payment amounts yield a lower interest, let's save these payments as the current state and continue
    • if the new payment amounts yield a higher interest, let's probabilistically save these payments as the current state and continue (this is to help avoid local minimums)
    • saves the best payment distribution that we encounter
the only tricky part was ensuring that the perturbing of the payment amounts still satisfied all of the constraints across every loan. a lot of error-checking tedium.

the program will display how much to pay towards each loan for every month, and it'll produce a summary that tells you how much you paid total, and how much went towards interest.

you can also experiment with choosing different monthly payment amounts and see how much it affects your lifetime interest amount. for example, my program showed me that:
  • paying $2k/mo will take 13 months; i'll accrue ~$500 of interest.
OR
  • paying only $1k/mo will take 26 months; i'll accrue ~$1,000 of interest
so, if i take a bullet of paying a measly extra $500 in lifetime interest, i'll gain the
freedom of having $1k extra of non-loan money each month for the next 26 months! it's definitely worth it.



solution:

the above .zip file contains 3
files:
for example, run it from a command prompt:
>> java InterestOptimizerTest input.txt




future work:
my current solution attempts to minimize the accrued interest, but it only does so over each upcoming month. basically, it works in a month-to-month basis until all loans are gone, which is not guaranteed to be the optimal, global solution, since it's not looking at the bigger picture across the lifetime of all the loans. the optimal solution would need to apply random amounts to all loans across every month of its lifetime, then make shifts both (1) between the various loans and (2) from month-to-month. this would give it a global picture to search within.

i suspect the improvement would be relatively negligible. in my case, i'm guessing that it would save me no more than $20. so, i don't plan to add this improvement. it's not worth it, but yea, i recognize it as an area of improvement.

ideas?
if anyone has any ideas for a faster or more optimal solution, please let me know. i'm curious to hear suggestions.

1 comment:

  1. i've said it many times and will say it many more times in the future... you rock, dude. (1) I'm gonna try out the program, I'll let ya know how it works out for me. (2) the Canon SD1400 is working amazingly for me. It has accompanied me on several day hikes (and random events) in the area, and it made a trip with me to Yosemite. Amazing performance.

    ReplyDelete