From 68a477cb7b177b48d8091a9375e93def8816915a Mon Sep 17 00:00:00 2001 From: Song Chuansheng Date: Tue, 4 Dec 2018 15:13:31 +0800 Subject: [PATCH 1/4] add rate / calculate rate of interest per period --- finance.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/finance.js b/finance.js index f31c8fd..0ad0bd2 100755 --- a/finance.js +++ b/finance.js @@ -201,6 +201,37 @@ Finance.prototype.IAR = function(investmentReturn, inflationRate){ return 100 * (((1 + investmentReturn) / (1 + inflationRate)) - 1); } +/** + * Caculate the rate of interest per period. + * @param numOfPayments + * @param pmt Loan Payment + * @param pv Present Value + * @param fv Future Value + * @param when begin for 1, end for 0 + */ +Finance.prototype.RATE = function(numOfPayments, pmt, pv, fv, when) { + + var guess = 0.1; + var limit = 100; //loop limit + var guess_last; + + do { + guess_last = guess; + guess = guess_last - guess_diff(guess_last, numOfPayments, pmt, pv, fv, when); + limit--; + }while(guess_last.toFixed(5) != guess.toFixed(5) && limit > 0); + + return guess; + + function guess_diff(guess, nper, pmt, pv, fv, when) { + t1 = (guess+1)**nper; + t2 = (guess+1)**(nper-1); + return ((fv + t1*pv + pmt*(t1 - 1)*(guess*when + 1)/guess) / + (nper*t2*pv - pmt*(t1 - 1)*(guess*when + 1)/(guess**2) + nper*pmt*t2*(guess*when + 1)/guess + + pmt*(t1 - 1)*when/guess)); + } +} + // XIRR - IRR for irregular intervals Finance.prototype.XIRR = function(cfs, dts, guess) { if (cfs.length != dts.length) throw new Error('Number of cash flows and dates should match'); From f9f654a5f76946261b0a6a0adf32819971588a5d Mon Sep 17 00:00:00 2001 From: Song Chuansheng Date: Tue, 4 Dec 2018 15:30:52 +0800 Subject: [PATCH 2/4] RATE definition --- finance.d.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/finance.d.ts b/finance.d.ts index 52c6a7f..4fe859b 100644 --- a/finance.d.ts +++ b/finance.d.ts @@ -138,6 +138,16 @@ export class Finance { */ public PMT(fractionalRate: number, numOfPayments: number, principal: number): number; + /** + * Caculate the rate of interest per period. + * @param numOfPayments + * @param pmt Loan Payment + * @param pv Present Value + * @param fv Future Value + * @param when begin for 1, end for 0 + */ + public RATE(numOfPayments: number, pmt: number, pv: number, fv: number, when: number): number; + /** * Inflation-adjusted Return (IAR) * Measure the return taking into account the time period's inflation rate From 93fe8c7576426484bc087f789dc985223e45a917 Mon Sep 17 00:00:00 2001 From: Song Chuansheng Date: Tue, 4 Dec 2018 15:36:55 +0800 Subject: [PATCH 3/4] add RATE test --- test/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/index.js b/test/index.js index 67cd382..6e5c33c 100755 --- a/test/index.js +++ b/test/index.js @@ -120,6 +120,10 @@ describe('FinanceJS', function() { cal.IAR(0.08, 0.03).should.equal(4.854368932038833); }); + it('should compute RATE', function() { + Number(cal.RATE(12, -933.33, 10000, 0, 0).toFixed(5)).should.equal(0.01788); + }); + it('should compute XIRR', function() { cal.XIRR([-1000, -100, 1200],[new Date(2015, 11, 1 ), new Date(2016, 7, 1 ), new Date(2016, 7, 19 )],0 ).should.equal(14.11); }); From 6c5ee9cee87d6e1e9017750569ea6977ebb9cf53 Mon Sep 17 00:00:00 2001 From: Song Chuansheng Date: Tue, 4 Dec 2018 16:24:34 +0800 Subject: [PATCH 4/4] use Math.pow instead of ** --- finance.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/finance.js b/finance.js index 0ad0bd2..c7fc8a7 100755 --- a/finance.js +++ b/finance.js @@ -224,10 +224,10 @@ Finance.prototype.RATE = function(numOfPayments, pmt, pv, fv, when) { return guess; function guess_diff(guess, nper, pmt, pv, fv, when) { - t1 = (guess+1)**nper; - t2 = (guess+1)**(nper-1); + t1 = Math.pow((guess+1), nper); + t2 = Math.pow((guess+1), nper-1); return ((fv + t1*pv + pmt*(t1 - 1)*(guess*when + 1)/guess) / - (nper*t2*pv - pmt*(t1 - 1)*(guess*when + 1)/(guess**2) + nper*pmt*t2*(guess*when + 1)/guess + + (nper*t2*pv - pmt*(t1 - 1)*(guess*when + 1)/Math.pow(guess,2) + nper*pmt*t2*(guess*when + 1)/guess + pmt*(t1 - 1)*when/guess)); } }