commit
message
[NPER] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-06-29 00:36:52
stats
8 file(s) changed,
112 insertions(+),
6 deletions(-)
files
DOCS.md
TODO.md
dist/Formulas/AllFormulas.js
dist/Formulas/Financial.js
src/Formulas/AllFormulas.ts
src/Formulas/Financial.ts
tests/Formulas/FinancialTest.ts
tests/SheetFormulaTest.ts
1diff --git a/DOCS.md b/DOCS.md
2index 3f5aa20..8783f4d 100644
3--- a/DOCS.md
4+++ b/DOCS.md
5@@ -469,6 +469,19 @@
6 @returns {number}
7 @constructor TODO: This function can return results that are prone to floating point precision errors.
8 ```
9+
10+### NPER
11+
12+```
13+ Returns the number of payment for an investment. Number is based on constant-amount payments made periodically and a constant interest rate.
14+@param rate - The interest rate.
15+@param payment - The amount of each payment.
16+@param present - THe current value.
17+@param future - [OPTIONAL] - The future value remaining after the final payment has been made.
18+@param type [OPTIONAL 0 by default] - 1 indicates payments are due at the beginning of each period. 0 indicates payments are due at the end of each period.
19+@returns {number}
20+@constructor
21+```
22 ## Info
23
24
25diff --git a/TODO.md b/TODO.md
26index c8e65a1..bdd2605 100644
27--- a/TODO.md
28+++ b/TODO.md
29@@ -144,7 +144,6 @@ For example 64 tbs to a qt.
30 * IRR
31 * MIRR
32 * NOMINAL
33-* NPER
34 * PPMT - Similar to PMT, which is already written.
35 * PRICE
36 * PRICEDISC
37diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
38index f4836ab..dac8243 100644
39--- a/dist/Formulas/AllFormulas.js
40+++ b/dist/Formulas/AllFormulas.js
41@@ -113,6 +113,7 @@ exports.EFFECT = Financial_1.EFFECT;
42 exports.SYD = Financial_1.SYD;
43 exports.SLN = Financial_1.SLN;
44 exports.NPV = Financial_1.NPV;
45+exports.NPER = Financial_1.NPER;
46 var Statistical_1 = require("./Statistical");
47 exports.AVERAGE = Statistical_1.AVERAGE;
48 exports.AVERAGEA = Statistical_1.AVERAGEA;
49diff --git a/dist/Formulas/Financial.js b/dist/Formulas/Financial.js
50index 34699bb..8ed7be2 100644
51--- a/dist/Formulas/Financial.js
52+++ b/dist/Formulas/Financial.js
53@@ -494,3 +494,35 @@ var NPV = function (rate) {
54 return value;
55 };
56 exports.NPV = NPV;
57+/**
58+ * Returns the number of payment for an investment. Number is based on constant-amount payments made periodically and a
59+ * constant interest rate.
60+ * @param rate - The interest rate.
61+ * @param payment - The amount of each payment.
62+ * @param present - THe current value.
63+ * @param future - [OPTIONAL] - The future value remaining after the final payment has been made.
64+ * @param type [OPTIONAL 0 by default] - 1 indicates payments are due at the beginning of each period. 0 indicates
65+ * payments are due at the end of each period.
66+ * @returns {number}
67+ * @constructor
68+ */
69+var NPER = function (rate, payment, present, future, type) {
70+ ArgsChecker_1.ArgsChecker.checkLengthWithin(arguments, 3, 5, "NPER");
71+ rate = TypeConverter_1.TypeConverter.firstValueAsNumber(rate);
72+ payment = TypeConverter_1.TypeConverter.firstValueAsNumber(payment);
73+ present = TypeConverter_1.TypeConverter.firstValueAsNumber(present);
74+ type = (typeof type === 'undefined') ? 0 : TypeConverter_1.TypeConverter.firstValueAsNumber(type);
75+ future = (typeof future === 'undefined') ? 0 : TypeConverter_1.TypeConverter.firstValueAsNumber(future);
76+ var num = payment * (1 + rate * type) - future * rate;
77+ var den = (present * rate + payment * (1 + rate * type));
78+ if (den === 0) {
79+ throw new Errors_1.DivZeroError("Evaluation of function NPER cause a divide by zero error.");
80+ }
81+ var div = Math.log(1 + rate);
82+ var logNumDen = Math.log(num / den);
83+ if (isNaN(logNumDen)) {
84+ throw new Errors_1.NumError("Parameters given function NPER are not possible.");
85+ }
86+ return logNumDen / div;
87+};
88+exports.NPER = NPER;
89diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
90index 35b048d..e8fac3f 100644
91--- a/src/Formulas/AllFormulas.ts
92+++ b/src/Formulas/AllFormulas.ts
93@@ -116,7 +116,8 @@ import {
94 EFFECT,
95 SYD,
96 SLN,
97- NPV
98+ NPV,
99+ NPER
100 } from "./Financial";
101 import {
102 AVERAGE,
103@@ -371,5 +372,6 @@ export {
104 FORECAST,
105 SYD,
106 SLN,
107- NPV
108+ NPV,
109+ NPER
110 }
111\ No newline at end of file
112diff --git a/src/Formulas/Financial.ts b/src/Formulas/Financial.ts
113index 448f1c4..7f00899 100644
114--- a/src/Formulas/Financial.ts
115+++ b/src/Formulas/Financial.ts
116@@ -503,6 +503,38 @@ var NPV = function (rate, ...values) {
117 return value;
118 };
119
120+/**
121+ * Returns the number of payment for an investment. Number is based on constant-amount payments made periodically and a
122+ * constant interest rate.
123+ * @param rate - The interest rate.
124+ * @param payment - The amount of each payment.
125+ * @param present - THe current value.
126+ * @param future - [OPTIONAL] - The future value remaining after the final payment has been made.
127+ * @param type [OPTIONAL 0 by default] - 1 indicates payments are due at the beginning of each period. 0 indicates
128+ * payments are due at the end of each period.
129+ * @returns {number}
130+ * @constructor
131+ */
132+var NPER = function (rate, payment, present, future?, type?) {
133+ ArgsChecker.checkLengthWithin(arguments, 3, 5, "NPER");
134+ rate = TypeConverter.firstValueAsNumber(rate);
135+ payment = TypeConverter.firstValueAsNumber(payment);
136+ present = TypeConverter.firstValueAsNumber(present);
137+ type = (typeof type === 'undefined') ? 0 : TypeConverter.firstValueAsNumber(type);
138+ future = (typeof future === 'undefined') ? 0 : TypeConverter.firstValueAsNumber(future);
139+ var num = payment * (1 + rate * type) - future * rate;
140+ var den = (present * rate + payment * (1 + rate * type));
141+ if (den === 0) {
142+ throw new DivZeroError("Evaluation of function NPER cause a divide by zero error.");
143+ }
144+ var div = Math.log(1 + rate);
145+ var logNumDen = Math.log(num / den);
146+ if (isNaN(logNumDen)) {
147+ throw new NumError("Parameters given function NPER are not possible.");
148+ }
149+ return logNumDen / div;
150+};
151+
152
153 export {
154 ACCRINT,
155@@ -517,5 +549,6 @@ export {
156 PMT,
157 SYD,
158 SLN,
159- NPV
160+ NPV,
161+ NPER
162 }
163\ No newline at end of file
164diff --git a/tests/Formulas/FinancialTest.ts b/tests/Formulas/FinancialTest.ts
165index 222f1a9..0ea0987 100644
166--- a/tests/Formulas/FinancialTest.ts
167+++ b/tests/Formulas/FinancialTest.ts
168@@ -11,7 +11,8 @@ import {
169 PMT,
170 SYD,
171 SLN,
172- NPV
173+ NPV,
174+ NPER
175 } from "../../src/Formulas/Financial";
176 import {
177 DATE
178@@ -321,3 +322,24 @@ test("NPV", function() {
179 NPV.apply(this, [10, 10, 20, "str"]);
180 }, ERRORS.VALUE_ERROR);
181 });
182+
183+
184+test("NPER", function() {
185+ assertEquals(NPER(0.04, 100, 4000, 0, 0), -24.362418941571317);
186+ assertEquals(NPER(0.04, 100, 4000), -24.362418941571317);
187+ assertEquals(NPER(0.02, 100, 4000, 0, 0), -29.68225660720854);
188+ assertEquals(NPER(0.01, 100, 4000, 0, 0), -33.815180780052486);
189+ assertEquals(NPER(0.04, -50, 1000, 20, 0), 41.44012515117696);
190+ assertEquals(NPER(-0.04, -50, 1000, 20, 0), 14.79388878297825);
191+ assertEquals(NPER(0.04, -50, 1000, 2000, 1), 61.13849239372526);
192+ assertEquals(NPER(0.04, -50, 1000, 2000, 0), 65.39782556827234);
193+ catchAndAssertEquals(function() {
194+ NPER(0.04, 50, 1000, 2000, 0);
195+ }, ERRORS.NUM_ERROR);
196+ catchAndAssertEquals(function() {
197+ NPER.apply(this, [0.04, 100]);
198+ }, ERRORS.NA_ERROR);
199+ catchAndAssertEquals(function() {
200+ NPER.apply(this, [0.04, -50, 1000, 2000, 0, 22]);
201+ }, ERRORS.NA_ERROR);
202+});
203diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
204index 3fb0a7c..3810e5a 100644
205--- a/tests/SheetFormulaTest.ts
206+++ b/tests/SheetFormulaTest.ts
207@@ -731,6 +731,9 @@ test("Sheet SLN", function(){
208 assertFormulaEquals('=SLN(100, 22, 10)', 7.80);
209 });
210
211+test("Sheet NPER", function(){
212+ assertFormulaEquals('=NPER(0.04, 100, 4000, 0, 0)', -24.362418941571317);
213+});
214
215 test("Sheet *", function(){
216 assertFormulaEquals('= 10 * 10', 100);