[ { "name": "\u00a31,000 repaid with \u00a31,100 a year later is 10.0%", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 12, "amount": { "minor": 110000, "currency": "GBP" } } ], 12 ], "expect": { "basisPoints": 1000, "display": "10.0%", "preciseBasisPoints": 1000 } }, { "name": "\u00a31,000 repaid with \u00a31,210 two years later is 10.0%", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 24, "amount": { "minor": 121000, "currency": "GBP" } } ], 12 ], "expect": { "basisPoints": 1000, "display": "10.0%", "preciseBasisPoints": 1000 } }, { "name": "the same in whole years", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 1, "amount": { "minor": 105000, "currency": "GBP" } } ], 1 ], "expect": { "basisPoints": 500, "display": "5.0%", "preciseBasisPoints": 500 } }, { "name": "\u00a31,000 over 12 monthly payments of \u00a388.85", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 1, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 2, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 3, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 4, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 5, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 6, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 7, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 8, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 9, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 10, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 11, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 12, "amount": { "minor": 8885, "currency": "GBP" } } ], 12 ], "expect": { "basisPoints": 1270, "display": "12.7%", "preciseBasisPoints": 1269 } }, { "name": "an arrangement fee paid at drawdown raises the APR", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 0, "amount": { "minor": 5000, "currency": "GBP" } }, { "period": 1, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 2, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 3, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 4, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 5, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 6, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 7, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 8, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 9, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 10, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 11, "amount": { "minor": 8885, "currency": "GBP" } }, { "period": 12, "amount": { "minor": 8885, "currency": "GBP" } } ], 12 ], "expect": { "basisPoints": 2420, "display": "24.2%", "preciseBasisPoints": 2419 } }, { "name": "a \u00a325,000 car loan: 60 payments of \u00a3460.30", "args": [ [ { "period": 0, "amount": { "minor": 2500000, "currency": "GBP" } } ], [ { "period": 1, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 2, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 3, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 4, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 5, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 6, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 7, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 8, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 9, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 10, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 11, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 12, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 13, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 14, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 15, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 16, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 17, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 18, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 19, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 20, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 21, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 22, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 23, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 24, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 25, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 26, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 27, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 28, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 29, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 30, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 31, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 32, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 33, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 34, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 35, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 36, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 37, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 38, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 39, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 40, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 41, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 42, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 43, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 44, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 45, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 46, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 47, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 48, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 49, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 50, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 51, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 52, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 53, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 54, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 55, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 56, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 57, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 58, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 59, "amount": { "minor": 46030, "currency": "GBP" } }, { "period": 60, "amount": { "minor": 46030, "currency": "GBP" } } ], 12 ], "expect": { "basisPoints": 410, "display": "4.1%", "preciseBasisPoints": 406 } }, { "name": "a payday loan: \u00a3100, \u00a3124 back after 30 days", "args": [ [ { "period": 0, "amount": { "minor": 10000, "currency": "GBP" } } ], [ { "period": 30, "amount": { "minor": 12400, "currency": "GBP" } } ], 365 ], "expect": { "basisPoints": 126970, "display": "1269.7%", "preciseBasisPoints": 126972 } }, { "name": "weekly: \u00a3500 repaid by 26 payments of \u00a321", "args": [ [ { "period": 0, "amount": { "minor": 50000, "currency": "GBP" } } ], [ { "period": 1, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 2, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 3, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 4, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 5, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 6, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 7, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 8, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 9, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 10, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 11, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 12, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 13, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 14, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 15, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 16, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 17, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 18, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 19, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 20, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 21, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 22, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 23, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 24, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 25, "amount": { "minor": 2100, "currency": "GBP" } }, { "period": 26, "amount": { "minor": 2100, "currency": "GBP" } } ], 52 ], "expect": { "basisPoints": 4100, "display": "41.0%", "preciseBasisPoints": 4102 } }, { "name": "two drawdowns a month apart", "args": [ [ { "period": 0, "amount": { "minor": 50000, "currency": "GBP" } }, { "period": 1, "amount": { "minor": 50000, "currency": "GBP" } } ], [ { "period": 2, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 3, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 4, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 5, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 6, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 7, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 8, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 9, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 10, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 11, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 12, "amount": { "minor": 10000, "currency": "GBP" } } ], 12 ], "expect": { "basisPoints": 1950, "display": "19.5%", "preciseBasisPoints": 1947 } }, { "name": "interest-free credit is 0.0%", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 1, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 2, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 3, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 4, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 5, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 6, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 7, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 8, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 9, "amount": { "minor": 10000, "currency": "GBP" } }, { "period": 10, "amount": { "minor": 10000, "currency": "GBP" } } ], 12 ], "expect": { "basisPoints": 0, "display": "0.0%", "preciseBasisPoints": 0 } }, { "name": "exactly 12.65% rounds up to 12.7%: the figure at the second decimal place is 5", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 1, "amount": { "minor": 112650, "currency": "GBP" } } ], 1 ], "expect": { "basisPoints": 1270, "display": "12.7%", "preciseBasisPoints": 1265 } }, { "name": "exactly 12.64% stays 12.6%", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 1, "amount": { "minor": 112640, "currency": "GBP" } } ], 1 ], "expect": { "basisPoints": 1260, "display": "12.6%", "preciseBasisPoints": 1264 } }, { "name": "quarterly repayments", "args": [ [ { "period": 0, "amount": { "minor": 400000, "currency": "GBP" } } ], [ { "period": 1, "amount": { "minor": 110000, "currency": "GBP" } }, { "period": 2, "amount": { "minor": 110000, "currency": "GBP" } }, { "period": 3, "amount": { "minor": 110000, "currency": "GBP" } }, { "period": 4, "amount": { "minor": 110000, "currency": "GBP" } } ], 4 ], "expect": { "basisPoints": 1660, "display": "16.6%", "preciseBasisPoints": 1665 } }, { "name": "eleven level payments and a larger final one", "args": [ [ { "period": 0, "amount": { "minor": 120000, "currency": "GBP" } } ], [ { "period": 1, "amount": { "minor": 12000, "currency": "GBP" } }, { "period": 2, "amount": { "minor": 12000, "currency": "GBP" } }, { "period": 3, "amount": { "minor": 12000, "currency": "GBP" } }, { "period": 4, "amount": { "minor": 12000, "currency": "GBP" } }, { "period": 5, "amount": { "minor": 12000, "currency": "GBP" } }, { "period": 6, "amount": { "minor": 12000, "currency": "GBP" } }, { "period": 7, "amount": { "minor": 12000, "currency": "GBP" } }, { "period": 8, "amount": { "minor": 12000, "currency": "GBP" } }, { "period": 9, "amount": { "minor": 12000, "currency": "GBP" } }, { "period": 10, "amount": { "minor": 12000, "currency": "GBP" } }, { "period": 11, "amount": { "minor": 12000, "currency": "GBP" } }, { "period": 12, "amount": { "minor": 23170, "currency": "GBP" } } ], 12 ], "expect": { "basisPoints": 5910, "display": "59.1%", "preciseBasisPoints": 5910 } }, { "name": "no advances", "args": [ [], [ { "period": 1, "amount": { "minor": 100, "currency": "GBP" } } ], 12 ], "expectError": "advances must not be empty" }, { "name": "no repayments", "args": [ [ { "period": 0, "amount": { "minor": 100, "currency": "GBP" } } ], [], 12 ], "expectError": "repayments must not be empty" }, { "name": "repayments below the credit would be a negative APR", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 12, "amount": { "minor": 90000, "currency": "GBP" } } ], 12 ], "expectError": "the APR would be negative" }, { "name": "the first drawdown must be at period 0", "args": [ [ { "period": 1, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 12, "amount": { "minor": 110000, "currency": "GBP" } } ], 12 ], "expectError": "the earliest advance must be at period 0" }, { "name": "a drawdown after a repayment makes the APR not unique", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } }, { "period": 6, "amount": { "minor": 50000, "currency": "GBP" } } ], [ { "period": 3, "amount": { "minor": 60000, "currency": "GBP" } }, { "period": 12, "amount": { "minor": 110000, "currency": "GBP" } } ], 12 ], "expectError": "the APR would not be unique" }, { "name": "a period unit that is not a CONC year fraction", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 12, "amount": { "minor": 110000, "currency": "GBP" } } ], 24 ], "expectError": "periodsPerYear must be 1, 2, 4, 12, 52 or 365" }, { "name": "a zero amount is refused", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 12, "amount": { "minor": 0, "currency": "GBP" } } ], 12 ], "expectError": "every amount must be greater than zero" }, { "name": "mixed currencies are refused", "args": [ [ { "period": 0, "amount": { "minor": 100000, "currency": "GBP" } } ], [ { "period": 12, "amount": { "minor": 110000, "currency": "EUR" } } ], 12 ], "expectError": "currency mismatch" } ]