How to Calculate Annual Percentage Rates (APR)

In this article I want to discuss Annual Percentage Rates (APR) and how you calculate them including some sample code. APR is a term you will see on several different lending products including loans, overdrafts, credit cards and mortgages. It is a legal requirement to show the APR on products where you borrow money, (certainly in the UK). The APR is meant to make it easier to make fairer comparisons of different products. To make things even more confusing there are 2 types of APR, Personal APR and Typical APR.

How to calculate Annual Percentage Rate (APR)

How to calculate Annual Percentage Rate (APR)

The APR is essentially how much your borrowing will cost over the period of an average year, over the term of your debt. It takes into account interest charged as well as any additional fees (such as arrangement fees, or annual fees) you’ll have to pay. It also considers the frequency with which interest is charged on your borrowing, as this as an impact on how much you will pay as well.

Personal APR

As mentioned above, there are 2 types of APR, Personal and Typical. The personal APR is quite straight forward as this is the percentage you will actually pay in your own circumstance. For a product like a mortgage this will generally be the same as the APR that is advertised as with a mortgage you are either accepted at that rate or not as the rate doesn’t change along with your risk profile, which may happen with a loan or credit card where you may be subject to risk based pricing.

When you take a loan or credit card though you should check the personal APR as this may be different to the rate advertised.

Typical / Representative APR

The typical (representative) APR is the rate of interest you will pay on some forms of borrowing like a credit card or loan. In order that these products can be compared prior to you applying for them (as you will never know what rate you are going to pay until you are accepted), they are required to display a “Representative APR” in any advertising material.

The typical APR is an advertised APR that a minimum percentage of customers (who are accepted) will pay. Under the current EU rules this minimum percentage is at 51%. The APR may also differ depending on the size of the loan. So for example a loan between £1000 and £3999 may be charged at 15% APR where a loan from £4000 to £6999 may be charged at 10%. Your personal APR may differ to this Typical APR based on your credit rating.

Short Term Loans

APR is all well and good but it starts to trip up for loans which are paid over very short payment terms and are charged based on fees instead of interest. This is why when you see adverts for payday loans they show a typical APR of anything from 200%-4000% based on how long the loan is for, and these loans can be as short as 7 days.

Naturally, no one will ever pay 4000% on one of these loans that just would not be fair; these loans are designed to be short term, as in a week to a month, not paid over a year.

The APR equation not only multiplies the actual period of interest up to a year’s duration, but also compounds it, assuming interest-on-interest many times over. The result is a grossly distorted number that bears no relation to the actual interest involved. This, I find, makes it quite confusing to a customer. But the rules are the rules. So in a nutshell, as the length of the loan decreases, the actual APR goes up.

Calculating APR

The process for calculating an APR, in the UK certainly, is regulated by the Financial Conduct Authority (the replacement for the FSA). So, I would like to introduce the FCA MCOB 10.3 Formula for calculating APR.

Formula for calculating an FCA approved APR

Formula for calculating an FCA approved APR

YOWSERS, MATHS!! Run Away!! For anyone not comfortable with formulas that can be a little intimidating but what I want to do is go over an implementation of this formula written in C#. I would like to say I wrote this bit of code myself, but it was actually developed by a developer on my team, Graham, and it is quite a nice solution.

.NET Implementation of the FCA APR Calculator

.NET Implementation of the FCA APR Calculator

Before we get to the bit that does all the work we have a few supporting classes/objects.

using System;
using System.Collections.Generic;
using System.Linq;

namespace Finance
{
    internal class Instalment
    {
        public double Amount { get; set; }
        public double DaysAfterFirstAdvance { get; set; }

        internal double Calculate(double APR)
        {
            double divisor = Math.Pow(1 + APR, DaysToYears);
            var sum = Amount / divisor;
            return sum;
        }

        private double DaysToYears
        {
            get
            {
                return DaysAfterFirstAdvance / 365.25d;
            }
        }
    }
}

This Instalment class represents a payment or advance on your loan including an amount and the number of days after your first payment advance.

using System;
using System.Collections.Generic;
using System.Linq;

namespace Finance
{
    public enum InstalmentFrequency
    {
        Daily = 0,
        Weekly = 1,
        Fortnightly = 2,
        FourWeekly = 3,
        Monthly = 4,
        Quarterly = 5,
        Annually = 6
    }
}

This InstalmentFrequency enumeration represents an instalment frequency.  That is the frequency that you are going to make payments on your loan. In a lot of traditional loans this would be a monthly instalment.

using System;
using System.Collections.Generic;
using System.Linq;

namespace Finance
{
    public enum InstalmentType
    {
        Payment = 0,
        Advance = 1
    }
}

InstalmentType represents the type of instalment that this is. Advance means this is money being paid out on the loan and Payment is a payment being made to pay down your loan.

using System;
using System.Collections.Generic;
using System.Linq;

namespace Finance
{
    public class APRCalculator
    {
        public APRCalculator(double firstAdvance)
            : this(firstAdvance, new List<Instalment>(), new List<Instalment>())
        {
        }

        internal APRCalculator(double firstAdvance, List<Instalment> advances, List<Instalment> payments)
        {
            _Advances = advances;
            _Payments = payments;
            _Advances.Add(new Instalment() { Amount = firstAdvance, DaysAfterFirstAdvance = 0 });
        }

        public double SinglePaymentCalculation(double payment, int DaysAfterAdvance)
        {
            return Math.Round((Math.Pow(_Advances[0].Amount / payment, (-365.25 / DaysAfterAdvance)) - 1) * 100, 1, MidpointRounding.AwayFromZero);
        }

        public double Calculate(double guess = 0)
        {
            double rateToTry = guess / 100;
            double difference = 1;
            double amountToAdd = 0.0001d;

            while (difference != 0)
            {
                double advances = _Advances.Sum(a => a.Calculate(rateToTry));
                double payments = _Payments.Sum(p => p.Calculate(rateToTry));

                difference = payments - advances;

                if (difference <= 0.0000001 && difference >= -0.0000001)
                {
                    break;
                }

                if (difference > 0)
                {
                    amountToAdd = amountToAdd * 2;
                    rateToTry = rateToTry + amountToAdd;
                }

                else
                {
                    amountToAdd = amountToAdd / 2;
                    rateToTry = rateToTry - amountToAdd;
                }
            }

            return Math.Round(rateToTry * 100, 1, MidpointRounding.AwayFromZero);
        }

        public void AddInstalment(double amount, double daysAfterFirstAdvance, InstalmentType instalmentType = InstalmentType.Payment)
        {
            var instalment = new Instalment() { Amount = amount, DaysAfterFirstAdvance = daysAfterFirstAdvance };
            switch (instalmentType)
            {
                case InstalmentType.Payment:
                    _Payments.Add(instalment);
                    break;
                case InstalmentType.Advance:
                    _Advances.Add(instalment);
                    break;
            }
        }

        private static double getDaysBewteenInstalments(InstalmentFrequency instalmentFrequency)
        {
            switch (instalmentFrequency)
            {
                case InstalmentFrequency.Daily:
                    return 1;
                case InstalmentFrequency.Weekly:
                    return 7;
                case InstalmentFrequency.Fortnightly:
                    return 14;
                case InstalmentFrequency.FourWeekly:
                    return 28;
                case InstalmentFrequency.Monthly:
                    return 365.25 / 12;
                case InstalmentFrequency.Quarterly:
                    return 365.25 / 4;
                case InstalmentFrequency.Annually:
                    return 365.25;
            }
            return 1;
        }

        public void AddRegularInstalments(double amount, int numberOfInstalments, InstalmentFrequency instalmentFrequency, double daysAfterFirstAdvancefirstInstalment = 0)
        {
            double daysBetweenInstalments = getDaysBewteenInstalments(instalmentFrequency);
            if (daysAfterFirstAdvancefirstInstalment == 0)
            {
                daysAfterFirstAdvancefirstInstalment = daysBetweenInstalments;
            }
            for (int i = 0; i < numberOfInstalments; i++)
            {
                _Payments.Add(new Instalment() { Amount = amount, DaysAfterFirstAdvance = daysAfterFirstAdvancefirstInstalment + (daysBetweenInstalments * i) });
            }
        }

        private readonly List<Instalment> _Advances;
        private readonly List<Instalment> _Payments;
    }
}

This APRCalculator class is quite long. I won’t go through it line by line, but I will cover the basic usage and then show some different test cases taken from our unit tests to show how it works.

This class is very easy to use, but I will reinforce the usage through some worked examples in a bit. The method contains 4 public methods.

    • APRCalculator Constructor – The constructor takes in an amount for the initial payment advance.
    • SinglePaymentCalculationThis method is the simple calculation usable when there is only one advance and one payment. The payment is the total amount to pay in a single instalment. The DaysAfterAdvance parameter is the number of days between the advance and the payment. The APR returned is to one decimal place (The FCA Standard) in an easy to read format so an APR of 37.20% will return as 37.2.
    • Calculate – Once you have added any payments and additional advances you call this method. As this is an iterative method, adding a guess slightly below what you think the actual APR will be will speed up the process. If it returns the same amount then the guess is either exactly right or too high. The APR returned is to one decimal place (The FCA Standard) in an easy to read format so an APR of 37.20% will return as 37.2.
    • AddInstalmentThe AddInstalment() method is used to add an instalment to the loan. An instalment can either be an additional advance or a payment.  The amount parameter is how much is being advanced or paid on the day given. The daysAfterFirstAdvance parameter is the number of days after the first advance based on the first advance day being day zero. The InstalmentType parameter identifies whether this is an advance or a payment against the loan.
    • AddRegularInstalmentsThe AddRegularInstalments() method is used if you want to add multiple payments of the same amount at regular intervals. The amount parameter is the amount of the regular payment. The numberOfInstalments parameter is the total number of instalments required. The instalmentFrequency parameter is an enumeration of the most regularly used payment frequencies. It bases the split on a 365.25 day year. The daysAfterFirstAdvancefirstInstalment parameter is the number of days before the first payment. It defaults to 0 which will set the first payment the same number of days as the frequency sets.

Examples of Usage

Now that we have gone over the public interface to the APR Calculator, let’s look at a few examples of its usage. These are taken from our unit tests. Some of these examples are test cases provided by the Consumer Finance Association.

One Advance with One Payment for One Year Returns One Percent

var calculator = new APRCalculator(100);

calculator.AddInstalment(101, 365);

var apr = calculator.Calculate();

Assert.AreEqual(1.0d, apr);

Here we have a loan where there is advance of £100 and one instalment for £101 where the payment is made 365 days after the first advance. This gives an APR of 1%

One Advance with One Payment of Same Returns Zero

var calculator = new APRCalculator(100);

calculator.AddInstalment(100, 1);

var apr = calculator.Calculate();

Assert.AreEqual(0.0d, apr);

Here we have a cash advance of £100 and a payment of £100 paid the day after the cash advance. This gives an APR of 0%

Advance £100 with One £125 Payment after 31 Days

var calculator = new APRCalculator(100);

var apr = calculator.SinglePaymentCalculation(125, 31);

Assert.AreEqual(1286.2d, apr);

Here we have an initial advance of £100, and we add a payment instalment of £125 paid after 31 days. This gives an APR or 1286.2%

CFA Bank Overdraft Example

var calculator = new APRCalculator(200);

calculator.AddInstalment(350, 365.25 / 12);

var apr = calculator.Calculate();

Assert.AreEqual(82400.5d, apr);

Here we have an initial advance of £200 and a payment of 350 made one month later. This comes out at an APR of 82400.5%. This is a sobering example before you decide to use an unauthorised overdraft on your bank account.

CFA Example of a Personal Loan

var calculator = new APRCalculator(10000);

calculator.AddRegularInstalments(222.44, 60, InstalmentFrequency.Monthly);

var apr = calculator.Calculate();

Assert.AreEqual(12.7d, apr);

In this example we have an initial advance of £10,000. We then have 60 monthly instalments (5 year loan) set up for £222.44 each. This gives an APR of 12.7%. This is most likely what people are used to seeing.

CFA example of a Short Term Loan

var calculator = new APRCalculator(200);

calculator.AddInstalment(250, 365.25/12);

var apr = calculator.Calculate();

Assert.AreEqual(1355.2d, apr);

This is the final example I will walk through, but this is for a short term loan. Here the initial advance is £200 and the payment is for £250 paid one month after the advance. For most short term loans, they deal with one off fees and not interest. So in this case the fee is £50 (25%). As the payment term is one month after the initial advance, this makes the APR 1355.2%. This is why I said earlier that the APR for this type of loan is a bit misleading.

I won’t walk through any more specific examples, but the table below shows some other examples.

APR Calculation Examples

APR Calculation Examples

That concludes this article on APR. I hope you have found it useful. I have first tried to explain in laymen terms what APR is all about and then show a sample implementation of the Financial Conduct Authorities official APR Calculation. The code in this article was written by my colleague Graham who also proof read this article for me.

For anyone reading this article in a country other than the UK, it would be interesting to hear if there are any differences in how you have to calculate APR’s.

Participate with Coding in the Trenches on Facebook

Participate with Coding in the Trenches on Facebook by Click the button above.

This entry was posted in Coding, Finance and tagged , . Bookmark the permalink.

4 Responses to How to Calculate Annual Percentage Rates (APR)

  1. Guy says:

    Very useful article. I have a slight confusion over one thing and I’d be interested to know your thoughts.
    I came across your article after doing this myself. I was trying to understand the values in the formula. In the FCA formula (shown in the little extract above) the bottom two items in the ‘where’ part don’t actually seem to appear in the equations. The two values referred to as tK and tK’, looking at your code it looks like these are actually used as the powers in the equation. Can you clarify ?

    • Graham says:

      You are quite right. For some reason the t is missing from the graphic which has been taken directly from the source page.

  2. Guy says:

    Thanks for the reply, did you find a definition of ‘relevant date’ which seems also a bit vague. I’m also curious about your successive approximation algorithm. I note you mention that starting with a guess just below the correct answer will make it works fast. How did you arrive at halving or doubling the ‘amountToAdd’ depending on whether your ‘rateToTry’ is too high or too low ? Most simple successive approximations work by moving in ever decreasing steps.

    • Graham says:

      ‘Relevant date’ is the date of the first advance or day zero as it is sometimes called.
      The code will work without the guess being added by starting at zero, if it was to use the ‘ever decreasing steps’ method what would be default first value of movement? If the guess passed in was actually above the correct answer and it used the ‘ever decreasing steps’ method it would never end. The ‘halving or doubling method’ covers both these scenarios.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s