Python: smarter way to calculate loan payments

23,173

Solution 1

This is a basically a mortgage repayment calculation.

Assuming that start is greater than end, and that interest is between 0 and 1 (i.e. 0.1 for 10% interest)

First consider the part of the payment you want to pay off.

Principal = start - end

The monthly payment is given by:

pay_a = (interest / 12) / (1 - (1+interest/12) ^ (-months))) * Principal

You then need to consider the extra interest. Which is just equal to the remaining principal times the monthly interest

pay_b = interest / 12 * end

So the total payment is

payment = (interest / 12) * (1 / (1 - (1+interest/12) ^ (-months))) * Principal + end)

On the example you gave of

Start: 100000
End:  50000
Months: 70
Interest: 8% 
pay_a = 896.20
pay_b = 333.33
Payment = 1229.54

When I tested these values in Excel, after 70 payments the remaing loan was 50,000. This is assuming you pay the interest on the notional before the payment is made each month.

Solution 2

Perhaps the easiest way to think about this is to split the loan in two parts, one part which is to be repaid in full and another part where you don't pay off anything. You have already computed the monthly fee for the first part.

Share:
23,173
googletorp
Author by

googletorp

I'm a senior Drupal developer, working as a consultant for Reveal IT. Over the past year I've spent a lot of time on Drupal and Drupal Commerce, created a lot of different sites with it and enjoyed it all the way. I maintain or co-maintain a host of modules on drupal.org and have contributed to a lot of other modules. Recently I've started contributing to Drupal core, making me in the top 5% of most contributions. When I'm not doing work or Drupal related stuff, I usually spend time with my beautiful wife and amazing son, play soccer, make grandiose cakes or some other fun stuff.

Updated on May 22, 2020

Comments

  • googletorp
    googletorp almost 4 years

    How to calculate the monthly fee on a loan?

    Given is:

    • a: an amount to loan.
    • b: the loan period (number of months).
    • c: the interest rate p.a. (interests is calculated and added every month, 1/12 of the interest is added. So if the interest is on 12%, 1% interest is added every month).
    • d: the amount of money owed after the end of the period.

    This problem is a bit different than the usual since, the goal is not to have the loan payed after the loan period has ended, but to still owe an amount that is given. I have been able to find an algorithm so solve the problem if I wanted to pay the entire amount, but it will of course not work for this problem where the goal is to end up owing a given amount rather than not owing anything.

    I managed to make a solution to this problem by starting with an guess and then keep on improving that guess until it was close enough. I wondered however, if there is a better way to simply calculate this, rather than just guessing.

    Edit: Here's how I'm doing it now.

    def find_payment(start, end, months, interest):
        difference = start
        guess = int(start / months * interest)
        while True:
            total = start
            for month in range(1, months + 1):
                ascribe = total * interest / 12
                total = total + ascribe - guess
            difference = total - end
            # See if the guess was good enough.
            if abs(difference) > start * 0.001:
                if difference < 0:
                    if abs(difference) < guess:
                        print "payment is %s" % guess
                        return evolution(start, guess, interest, months)
                    else:
                        mod = int(abs(difference) / start * guess)
                        if mod == 0:
                            mod = 1
                        guess -= mod
                else:
                    mod = int(difference / start * guess)
                    if mod == 0:
                        mod = 1
                    guess += mod
            else:
                print "payment is %s" % guess
                return evolution(start, guess, interest, months)
    

    evolution is just a function that displays how the loan would look like payment for payment and interest for interest, summing up total amount of interest paid etc.

    An example would be if I wanted to find out the monthly payments for a loan starting with $100k and ending at $50k with an interest of 8% and a duration of 70 months, calling

    >>> find_payment(100000, 50000, 70, 0.08)
    payment is 1363
    

    In the above case I would end up owing 49935, and I went through the loop 5 times. The amount of times needed to go through the loop depends on how close I want to get to the amount and it varies a bit.

  • Alex Martelli
    Alex Martelli over 14 years
    +1, exactly! Simplest accounting equivalence in the books, really.
  • googletorp
    googletorp over 14 years
    Clever to split the loan into two parts, didn't think of that.
  • Toby Speight
    Toby Speight over 6 years
    Welcome to Stack Overflow! Thank you for this code snippet, which may provide some immediate help. A proper explanation would greatly improve its educational value by showing why this is a good solution to the problem, and would make it more useful to future readers with similar, but not identical, questions. Please edit your answer to add explanation, and give an indication of what limitations and assumptions apply.