Solved

Calculating apr using newton raphson (in php) - how to add upfront fee

Posted on 2013-12-30
10
1,183 Views
Last Modified: 2014-01-01
I am trying to calculate APR using Newton Raphson in PHP. I have modified the code from this question into php

http://stackoverflow.com/questions/3102476/calculating-annual-percentage-rate-need-some-help-with-inherited-code

However the formula in this question is based on an initial principal, recurring monthly payments and a total number of payments. I need my APR calculation to include an initial start up fee. This would be added to the first monthly payment meaning the monthly payments are no longer all the the same. I take it that this would alter the original formula and hence its derivative. I have no idea what to use now as the initial formula or how to modify this

Here is the php
$numPay = 12;
$payment = 875;
$amount = 10000;
$error = pow(10,-5);
$approx = 0.05/12; // let's start with a guess that the APR is 5% 
$prev_approx;

function f($x) {
    global $numPay;
    global $payment; 
    global $amount;
    global $error;



    return $amount * $x * (pow(1 + $x,$numPay)/(pow(1 + $x, $numPay) - 1)) - $payment;

}



function f_prime($x) {
    global $numPay;
    global $payment; 
    global $amount;
    global $error;

     return $amount * (pow(1 + $x,$numPay)/(-1 + pow(1 + $x,$numPay)) - $numPay * $x * pow(1 + $x,-1 + 2*$numPay)/pow(-1 + pow(1 + $x,$numPay),2) + $numPay * $x * pow(1 + $x,-1 + $numPay)/(-1 + pow(1 + $x,$numPay)));


}
echo f($approx) . "<br/>";

echo f_prime($approx) . "<br/>";
echo  "initial guess $approx" . "<br/>";

for ($k=0;$k<20; $k++) {
       $prev_approx = $approx;
       $approx = $prev_approx - (f($prev_approx)/f_prime($prev_approx));
       $diff = abs($approx-$prev_approx);
       echo "new guess $approx diff is $diff <br/>";
       if ($diff < $error) break;
}

$apr = round($approx * 12 * 10000 /100, 1); // this way we get APRs like 7.5% or 6.55%
echo "apr is $apr %";

Open in new window

0
Comment
Question by:andieje
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
10 Comments
 
LVL 35

Expert Comment

by:gr8gonzo
ID: 39747046
Why would an initial fee make a difference on other payments? If the fee doesn't have an impact on the principal balance, then the remaining payments should be exactly the same. You'd just take the first payment and add the fee to it?
0
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39747119
You might try using the other IRR script.  This is not 100% exact but it's iteratively pretty close to accurate with no error until the 5th decimal place.  Of course, if you're dealing with very large sums of money, you may want to raise the accuracy settings at the expense of compute time.

Since each of the payments is expressed separately, you can use this for multiple discounted cash flows.  Just add your loan origination fee (or whatever) to the initial payment or subtract it from the initial principal, plug in a balloon payment, whatever suits your business practices.

Note line 26.

This interest rate is within 0.00006 of the calculations on my HP12C.

<?php // RAY_temp_andieje_irr.php
error_reporting(E_ALL);

// COMPUTE (IRR) INTERNAL RATE OF RETURN - ITERATIVE METHOD, MONTHLY PAYMENTS

// SOME TEST DATA
$cashflow = array
( -10000   // INITIAL INVESTMENT
, 869.884 + 200
, 869.884
, 869.884
, 869.884
, 869.884
, 869.884
, 869.884
, 869.884
, 869.884
, 869.884
, 869.884
, 869.884
)
;

// TEST THE FUNCTION AND SHOW THE WORK PRODUCT
$net = array_sum($cashflow);
$irr = irr($cashflow, 7) / (1/12);
echo " CASH: ";print_r($cashflow);
echo " NET: $net";
echo " IRR: $irr";


// DETERMINE INTERNAL RATE OF RETURN FROM AN ARRAY OF ANNUAL PAYMENTS
function irr(array $cashflow, $accuracy=4)
{
    // DETERMINE IF GROSS CASHFLOW IS POSITIVE OR NEGATIVE
    $cash = round(array_sum($cashflow),$accuracy);
    if ($cash == 0.0) return 0.0;
    if ($cash >  0.0) $iterator =  pow(10,-$accuracy);
    if ($cash <  0.0) $iterator = -pow(10,-$accuracy);

    $interest = 0.0;
    $npv      = 1.0;
    $years    = count($cashflow) - 1;

    while ( (round(abs($npv),$accuracy) > 0.0) )
    {
        $interest = round($interest + $iterator,$accuracy);
        $year     = 0;
        $npv      = 0.0;

        while ($year <= $years)
        {
            $yearly = $cashflow[$year];
            // DENOMINATOR IS (1 + r)**t
            $denominator = pow((1+$interest), $year);
            $denominator = round($denominator,$accuracy);
            $npv = $npv + ( $yearly / $denominator );
            $year++;
        }
        if  (($iterator > 0.0) && ($npv < 0.0) ) break;
        if  (($iterator < 0.0) && ($npv > 0.0) ) break;
    }

    // RETURN WHOLE.FRACTIONAL PERCENT
    return round((($interest-$iterator) * 100.0),$accuracy);
}

Open in new window

0
 
LVL 31

Expert Comment

by:GwynforWeb
ID: 39747633
Newton Rhapson in not the preferred method  for APR calculations. The Method of Bisection is more stable and easier to code, albeit slower. But on such a small calculation speed is irrelevant.

Here is the basic code and f($x) is defined as in your code.

$x1=0;       //lower approx
$x2=1000;    //upper approx
while ( ($x2 - $x1 ) > 0.00001 ) {
    $xMid=($x1+ $x2)/2;  //new approx
    $F1 =  f($x1)
    $FMid =  f($xMid)

    if  ($FMid*$F1 > 0 )    //check for new interval containing root
      $x1 = $xMid;
    else
      $x2 = $xMid;
}

echo "apr is $xMid%";

Open in new window

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:andieje
ID: 39747946
I tried code for the bisection method but it doesn't give correct answer. It is off by about 50%. I don't know if this is because I need the EU method or formula for apr. A 10000k loan at 6% paid back over 12 months should give me apr of 9.5  for example
0
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39748169
... doesn't give correct answer. It is off by about 50%
I'm not able to find that kind of error.  And I can't see enough of the information to get from a 6% interest rate to a 9.5% APR.  Where are the other costs coming from?  I get 12 payments of 861 and a sum of payments of 10,328.

In general, an APR takes into account multiple discounted cash flows.  Among these cash flows are things like "points" (loan origination fees) that are charged by the lender.  The notion of APR came up in the United States because lenders began a practice of quoting the interest rate without mentioning the points.  This was obviously deceitful and laws were made to protect the borrowers by requiring the lender to state all of the charges in the form of an APR.  Lenders can still get around this with pre-payment penalties, etc., but at least the concept is out there and borrowers have a chance to educate themselves.
0
 

Author Comment

by:andieje
ID: 39748228
The calculator I am comparing it to is www.financecalcs.co.uk

I am looking at the loan calculator link. That gives a massive change in apr with arrangements fees. I was advised that the website is correct  for uk
0
 

Author Comment

by:andieje
ID: 39748234
That website is also where I get the monthly repayment amounts from
0
 
LVL 110

Accepted Solution

by:
Ray Paseur earned 500 total points
ID: 39748396
In the USA, arrangements fees are typically called points, but they have the same effect.

I went to this page: http://www.financecalcs.co.uk/smartcalcs/LoanCalculatorquote.php 

It has a code smell, in that it's not valid HTML markup.  But that may not matter.
http://validator.w3.org/check?uri=http%3A%2F%2Fwww.financecalcs.co.uk%2Fsmartcalcs%2FLoanCalculatorquote.php&charset=%28detect+automatically%29&doctype=Inline&group=0

I put in a 10,000 initial value, a 12 month term and a 6% interest rate.  The calculator came back with a monthly payment of 883.33 and a total interest charge of 599.96.  In the USA, this is not a 6% interest loan; it's an 10.9% interest loan.  We are not allowed to charge interest on the already-paid balance, and each payment retires some of the principal balance.  For this to be called a 6% loan in the USA, it would have to be a 12-month no-payments balloon note bearing simple interest.  Loans like that are very, very rare and almost non-existent in commercial lending.

I think you need legal and financial advice to determine the rules for your computations, and I'm not qualified to give that advice since all of my learned financial principles are to USA standards.  But if you can come back with the rules, I'll be glad to help you implement them in PHP code!
0
 

Author Comment

by:andieje
ID: 39749814
Hi ray. I think those types of loans are common in uk for buying a car . Not mortgages etc. Thanks fir your comments. Will close this question and return with more information
0
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39749821
Thanks for the points and Happy New Year 2014! ~Ray
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Password hashing is better than message digests or encryption, and you should be using it instead of message digests or encryption.  Find out why and how in this article, which supplements the original article on PHP Client Registration, Login, Logo…
Introduction This article is intended for those who are new to PHP error handling (https://www.experts-exchange.com/articles/11769/And-by-the-way-I-am-New-to-PHP.html).  It addresses one of the most common problems that plague beginning PHP develop…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…

749 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question