From e3220e822bb2cfbb80291259b05d63770409bdc6 Mon Sep 17 00:00:00 2001 From: Matthew McDermott Date: Sat, 19 Mar 2016 10:45:09 -0700 Subject: [PATCH 1/3] Adding two new, fast methods for IRR. --- finance.js | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/finance.js b/finance.js index f186b07..0931f9c 100755 --- a/finance.js +++ b/finance.js @@ -48,6 +48,52 @@ Finance.prototype.IRR = function(cfs) { return Math.round(bestGuess * 100) / 100; }; +function seekZero(fn) { + var x = 0; + while (fn(x) > 0) { + x += 1; + } + while (fn(x) < 0) { + x -= 0.01 + } + return x + 0.01; +} + +function seekZeroD(fn, d) { + var x = 0; + var y = fn(x); + while (Math.abs(y) > 0.0001) { + x -= y/d(x) + y = fn(x); + } + return x; +} + +// Internal Rate of Return (IRR) +Finance.prototype.IRRFast = function(cfs) { + + var args = arguments; + function npv(rate) { + var rrate = (1 + rate/100); + var npv = args[0]; + for (var i = 1; i < args.length; i++) { + npv += (args[i] / Math.pow(rrate, i)); + } + return npv; + } + + function npvp(rate) { + var rrate = (1+rate/100); + var npvp = 0 + for (var i = 1; i < args.length; i++) { + npvp -= (args[i]/Math.pow(rrate, i+1))*(1/100) + } + return npvp + } + + return seekZeroD(npv, npvp); +}; + // Payback Period (PP) Finance.prototype.PP = function(numOfPeriods, cfs) { // for even cash flows From db6ff9f2585a45bd8600b3d66227b8a0ed7b181b Mon Sep 17 00:00:00 2001 From: Matthew McDermott Date: Sun, 20 Mar 2016 11:05:37 -0700 Subject: [PATCH 2/3] This version takes ~0.2 seconds for 50k iterations, vs. ~15 seconds with the old version. --- finance.js | 48 ++++-------------------------------------------- testFast.js | 9 +++++++++ 2 files changed, 13 insertions(+), 44 deletions(-) create mode 100644 testFast.js diff --git a/finance.js b/finance.js index 0931f9c..1cb6a27 100755 --- a/finance.js +++ b/finance.js @@ -28,28 +28,9 @@ Finance.prototype.NPV = function (rate) { return Math.round(npv * 100) / 100; }; -// Internal Rate of Return (IRR) -Finance.prototype.IRR = function(cfs) { - var bestGuess, currentNPV; - var checkNPV = function(rate, arguments){ - var npv = arguments[0]; - // base case - for (var i = 1; i < arguments.length; i++) { - npv +=(arguments[i] / Math.pow((1 + rate/100), i)); - } - currentNPV = Math.round(npv * 100) / 100; - if (currentNPV <= 0) { - bestGuess = rate; - return; - } - checkNPV(rate + 0.01, arguments); - }; - checkNPV(0.01, arguments); - return Math.round(bestGuess * 100) / 100; -}; - +// seekZero seeks the zero point of the function fn(x), accurate to within x \pm 0.01. fn(x) must be decreasing with x. function seekZero(fn) { - var x = 0; + var x = 1; while (fn(x) > 0) { x += 1; } @@ -59,19 +40,8 @@ function seekZero(fn) { return x + 0.01; } -function seekZeroD(fn, d) { - var x = 0; - var y = fn(x); - while (Math.abs(y) > 0.0001) { - x -= y/d(x) - y = fn(x); - } - return x; -} - // Internal Rate of Return (IRR) -Finance.prototype.IRRFast = function(cfs) { - +Finance.prototype.IRR = function(cfs) { var args = arguments; function npv(rate) { var rrate = (1 + rate/100); @@ -81,17 +51,7 @@ Finance.prototype.IRRFast = function(cfs) { } return npv; } - - function npvp(rate) { - var rrate = (1+rate/100); - var npvp = 0 - for (var i = 1; i < args.length; i++) { - npvp -= (args[i]/Math.pow(rrate, i+1))*(1/100) - } - return npvp - } - - return seekZeroD(npv, npvp); + return Math.round(seekZero(npv) * 100) / 100; }; // Payback Period (PP) diff --git a/testFast.js b/testFast.js new file mode 100644 index 0000000..9eeaa2b --- /dev/null +++ b/testFast.js @@ -0,0 +1,9 @@ +var Finance = require('./finance.js') + +var finance = new Finance(); + +for (var i = 0; i < 50000; i++) { + finance.IRR(-500000, 200000, 300000, 200000) +} + +console.log(finance.IRR(-500000, 200000, 300000, 200000)) From 96aeb8d597527f96663024c7c3a4a0744002a744 Mon Sep 17 00:00:00 2001 From: Matthew McDermott Date: Sun, 20 Mar 2016 11:05:47 -0700 Subject: [PATCH 3/3] Removing test code. --- testFast.js | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 testFast.js diff --git a/testFast.js b/testFast.js deleted file mode 100644 index 9eeaa2b..0000000 --- a/testFast.js +++ /dev/null @@ -1,9 +0,0 @@ -var Finance = require('./finance.js') - -var finance = new Finance(); - -for (var i = 0; i < 50000; i++) { - finance.IRR(-500000, 200000, 300000, 200000) -} - -console.log(finance.IRR(-500000, 200000, 300000, 200000))