0
$\begingroup$

For some reason calculating APR is very difficult. A lot of people ask, but not a lot of great answers. I'm working on a project, where I need to calculate APR. I have already calculated what the loan is, how much the user has to pay each month, and I have the amount of months. I found a formula online, but it doesn't make a lot of sense.

function calculateAPR(loan, repayments, months) {
    var p = 1;
    var tmp = 1;
    var a = p;
    var b = 0;
    while (Math.abs(tmp) > 0.0001) {
        p = (a - b) / 2 + b;
        tmp = (loan / repayments) - (1 - Math.pow(1 + p, -months)) / p;
        if (tmp > 0) {
            a = p;
        } else {
            b = p;
        }
    }
    var apr = Math.pow((1 + p), 12) - 1;
    return apr;
}

Math.pow()'s second argument is what you want to power by an amount. Basically 1+p^12 on the third last line. Math.abs() returns the absolute value (-10 becomes 10). If I input this:

loan = 80000
repayments = 7366
months = 12

I get an APR of 20.56%. That seems correct according to the site I got the formula from, but when I input the numbers into other websites, I get no where near the same result.

Can someone explain how this formula works? Why is there a loop? Is it because of compound interest? Is there a better formula? I'm looking for any kind of help, because I can't seem to find answers that solve this programmably. Thanks.

  • 0
    You could be interested by http://math.stackexchange.com/questions/1536653/approximating-the-compond-interest-for-a-loan2017-02-07
  • 0
    @ClaudeLeibovici I appreciate your comment! However, it looks like that person gave up (last line of his answer) :(2017-02-07
  • 0
    What makes you think that code is wrong? For the example you gave, which sites give answers other than the one you got from the code?2017-02-07
  • 0
    @MortenMoulder. This was a post of mine ! You can use the results for an estimate and start using Newton or whichever method you want.2017-02-07
  • 0
    @quasi I don't think the code is wrong. I just don't understand how it works and why there is a loop. Why I think it might be wrong, is because all the other calculators I tried, this one shows a different result each time.2017-02-07
  • 0
    @ClaudeLeibovici Can you explain what the numbers are? `r = 0.01` and `n = 180`?2017-02-07
  • 0
    @MortenMoulder: Can you give a link to an online APR calculator that gives an answer other than the one produced by the code for the example you posted?2017-02-07
  • 0
    @quasi You can try this one: http://www.calculatorsoup.com/calculators/financial/apr-calculator.php - I already know the loan, repayments (monthly), and the total amount of months.2017-02-07
  • 0
    @MortenMoulder: that website gives the _same_ answer as your program, using the following inputs: \begin{align*} \text{loan}&=80,000.00\\ \text{interest rate}&= 20.5406\\ \text{compounding}&= \text{annual}\\ \text{number of payments}&= 12\\ \text{payment frequency}&= \text{monthly}\\ \text{all fees}&= 0 \end{align*}2017-02-07
  • 0
    @MortenMoulder: You can lso use EXCEL: https://support.office.com/en-us/article/IRR-function-64925eaa-9988-495b-b290-3ad0c163c1bc2017-02-08
  • 0
    @quasi The interest rate is not $20.5406$ though? Where did you get that from?2017-02-08
  • 0
    @cgiovanardi No Excel.2017-02-08
  • 0
    @MortenMoulder: Why is that not the interest rate? An interest rate of 20.5406% is consistent with the input data.2017-02-08
  • 0
    @quasi Where did you get it from? I only know $loan = 80,000.00$, $number of payments = 12$ and $monthly repayments = 8,000.00$ - Based on those 3 numbers, how do you get $interest rate = 20.5406$?2017-02-09
  • 0
    @MortenMoulder: That rate comes from your posted formula, and it also matches the results from the online calculator for which you posted a link.2017-02-09
  • 0
    @quasi We agree that the formula I posted and the formula on that website are basically the same? Let's imagine I didn't have my formula, but I only had the website. How would you get the interest rate then?2017-02-09
  • 0
    @MortenMoulder: Look way back in the comments. I gave you the inputs for the website.2017-02-09
  • 0
    @quasi I don't think you understand. Based on these three numbers: $loan = 80000$, $number of months = 12$, and $repayments = 7366$ how do you get the interest rate just from that website I sent you? Forget the interest rate, because that is completely unknown.2017-02-10
  • 0
    That website doesn't calculate the interest rate. You have to enter the interest rate as _input_. It then calculates the monthly payment. But the site can be used to _verify_ that the results based on your code are correct. Look back in the comments -- I _specified_ the inputs I used to check the results from the code. The results _checked_.2017-02-10

1 Answers 1

1

The loop is designed to progressively narrow the interval in which the correct apr resides. At the outset, the program assumes (arbitrarily) that the correct monthly apr, $r$ say, is between $0$ and $1$ (i.e., between $0\text{%}$ and $100\text{%}$).

The variables $a,b$ denotes the bounds on $r$, where $b \le r \le a$.

As the program progresses, the values of $a$ and $b$ are adjusted, as follows . . .

The variable $p$ is set to the middle of the known range (i.e., $p = b + (a-b)/2$).

The value $p$ is then tested to see whether it's too low or too high.

If too low, $b$ is set to $p$, and $a$ is left as is.

If too high, $a$ is set to $p$, and $b$ is left as is.

After each pass through the loop, the value of $a - b$ is half its previous value.

When $a-b$ is less than $0.0001$ (an arbitrary tolerance), the loop terminates.

Then the value of $p$ at the end is the desired $r$, which is then adjusted from a monthly rate to an annual rate in the standard way.

  • 0
    Thanks a lot! So basically what it does, is continue calculating `tmp` until `tmp` is below 0.0001. I get all the code and how it works, I just don't understand why it has to be above 0.0001 and why we have to grab the middle of the known range.2017-02-07
  • 0
    The loop will never get the exact value of $r$, so the choice needs to be made as to when $p$ is "close enough" to the true $r$. When the $a-b < 0.0001$, the value of $p$ at that stage is no more than $0.0001$ away from the true value of $r$. Thus, the program is using $0.0001$ as an acceptable error tolerance.2017-02-07
  • 0
    Oh, okay! So if I decrease the $0.0001$ (like to $0.00001$), it will compute more times but get a more precise APR?2017-02-07
  • 0
    When the bounding interval is $[b,a]$, the next interval will be either $[b,p]$ or $[p,a]$, Choosing $p$ as the midpoint of $[a,b]$ guarantees that the length of the new interval will be half that of the old interval.2017-02-07
  • 0
    Yes, a smaller tolerance will increase the accuracy at the expense of greater computation time. But be careful -- if the error tolerance is set too low, floating point calculations will produce errors which will dominate the error tolerance, making the apparently more accurate result an illusion.2017-02-07
  • 0
    Right, that makes sense. So the whole `tmp = (loan / repayments) - (1 - Math.pow(1 + p, -months)) / p` line, what exactly does that do? Does it follow some kind of formula? It doesn't look like anything I have seen before.2017-02-07
  • 0
    Multiply both sides by the (constant) repayment, regard the LHS as effectively zero, and solve for loan. That will give the standard meaning.2017-02-07
  • 0
    I have no clue what you just said. When do we multiply both sides? What's LHS?2017-02-07
  • 0
    LHS means "left hand side" (of the equation). In this case, the equation is tmp $= \;...$. If you multiply both sides by repayment, the new LHS is repayment $\times$ tmp. Since tmp is close to zero, and repayment is a fixed constant, the new LHS is also close to zero. If you _replace_ the new LHS by zero, and then solve for loan, you get the usual formula connecting the quantities loan, repayment, number of periods, apr.2017-02-07
  • 0
    Oh okay, it all starts to make more sense now. I wouldn't exactly say I understnad this fully, but I'm starting to understand the overall of it. Thanks a lot :)2017-02-07