spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[Financial] adding PMT formula and tests
author
Ben Vogt <[email protected]>
date
2017-05-13 21:32:09
stats
3 file(s) changed, 60 insertions(+), 13 deletions(-)
files
src/Formulas/Financial.ts
src/Utilities/ArgsChecker.ts
tests/Formulas/FinancialTest.ts
  1diff --git a/src/Formulas/Financial.ts b/src/Formulas/Financial.ts
  2index 1c2f28c..c78b892 100644
  3--- a/src/Formulas/Financial.ts
  4+++ b/src/Formulas/Financial.ts
  5@@ -219,21 +219,39 @@ var EFFECT = function (...values) : number {
  6   return Math.pow(1 + rate / periods, periods) - 1;
  7 };
  8 
  9-// TODO: Convert to real formula PMT.
 10-function pmt(rate, periods, present, future, type) {
 11+
 12+/**
 13+ * Calculates the periodic payment for an annuity investment based on constant-amount periodic payments and a constant
 14+ * interest rate.
 15+ * @param rate - The interest rate.
 16+ * @param periods - The number of payments to be made.
 17+ * @param presentValue - The current value of the annuity.
 18+ * @param futureValue [ OPTIONAL ] - The future value remaining after the final payment has been made.
 19+ * @param endOrBeginning [ OPTIONAL - 0 by default ] - Whether payments are due at the end (0) or beginning (1) of each
 20+ * period.
 21+ * @returns {number}
 22+ * @constructor
 23+ */
 24+var PMT = function (rate, periods, presentValue, futureValue?, endOrBeginning?) : number {
 25+  ArgsChecker.checkLengthWithin(arguments, 3, 5, "PMT");
 26+  rate = TypeConverter.firstValueAsNumber(rate);
 27+  periods = TypeConverter.firstValueAsNumber(periods);
 28+  presentValue = TypeConverter.firstValueAsNumber(presentValue);
 29+  futureValue = futureValue ? TypeConverter.firstValueAsNumber(futureValue) : 0;
 30+  endOrBeginning = endOrBeginning ? TypeConverter.firstValueAsNumber(endOrBeginning) : 0;
 31   var result;
 32   if (rate === 0) {
 33-    result = (present + future) / periods;
 34+    result = (presentValue + futureValue) / periods;
 35   } else {
 36     var term = Math.pow(1 + rate, periods);
 37-    if (type) {
 38-      result = (future * rate / (term - 1) + present * rate / (1 - 1 / term)) / (1 + rate);
 39+    if (endOrBeginning) {
 40+      result = (futureValue * rate / (term - 1) + presentValue * rate / (1 - 1 / term)) / (1 + rate);
 41     } else {
 42-      result = future * rate / (term - 1) + present * rate / (1 - 1 / term);
 43+      result = futureValue * rate / (term - 1) + presentValue * rate / (1 - 1 / term);
 44     }
 45   }
 46   return -result;
 47-}
 48+};
 49 
 50 // TODO: Convert to real formula FV
 51 function fv(rate, periods, payment, value, type) {
 52@@ -283,7 +301,7 @@ var CUMPRINC = function (...values) : number {
 53   }
 54   var type = TypeConverter.firstValueAsBoolean(values[5]);
 55 
 56-  var payment = pmt(rate, periods, value, 0, type);
 57+  var payment = PMT(rate, periods, value, 0, type);
 58   var principal = 0;
 59   if (start === 1) {
 60     if (type) {
 61@@ -335,7 +353,7 @@ var CUMIPMT = function (...values) : number {
 62   }
 63   var type = TypeConverter.firstValueAsBoolean(values[5]);
 64 
 65-  var payment = pmt(rate, periods, value, 0, type);
 66+  var payment = PMT(rate, periods, value, 0, type);
 67   var interest = 0;
 68   if (start === 1) {
 69     if (!type) {
 70@@ -422,5 +440,6 @@ export {
 71   DOLLAR,
 72   DOLLARDE,
 73   DOLLARFR,
 74-  EFFECT
 75+  EFFECT,
 76+  PMT
 77 }
 78\ No newline at end of file
 79diff --git a/src/Utilities/ArgsChecker.ts b/src/Utilities/ArgsChecker.ts
 80index cc85633..5c40cb3 100644
 81--- a/src/Utilities/ArgsChecker.ts
 82+++ b/src/Utilities/ArgsChecker.ts
 83@@ -44,8 +44,8 @@ class ArgsChecker {
 84   static checkLengthWithin(args: any, low: number, high: number, caller?: string) {
 85     if (args.length > high || args.length < low) {
 86       var functionName = caller !== undefined ? " to " + caller : "";
 87-      throw new NAError("Wrong number of arguments" + functionName + ". Expected between" + low
 88-        + "and " + high + " arguments, but got " + args.length + " arguments.");
 89+      throw new NAError("Wrong number of arguments" + functionName + ". Expected between " + low
 90+        + " and " + high + " arguments, but got " + args.length + " arguments.");
 91     }
 92   }
 93 }
 94diff --git a/tests/Formulas/FinancialTest.ts b/tests/Formulas/FinancialTest.ts
 95index e9b6e41..06ca457 100644
 96--- a/tests/Formulas/FinancialTest.ts
 97+++ b/tests/Formulas/FinancialTest.ts
 98@@ -7,7 +7,8 @@ import {
 99   DOLLAR,
100   DOLLARDE,
101   DOLLARFR,
102-  EFFECT
103+  EFFECT,
104+  PMT
105 } from "../../src/Formulas/Financial";
106 import {
107   DATE
108@@ -244,3 +245,27 @@ test("EFFECT", function(){
109     EFFECT(0.99, []);
110   }, ERRORS.REF_ERROR);
111 });
112+
113+
114+test("PMT", function() {
115+  assertEquals(PMT(0.05/12, 30*12, 100000), -536.8216230121382);
116+  assertEquals(PMT(0.05/12, 30*12, 100000, 10000), -548.8371186466853);
117+  assertEquals(PMT(0.05/12, 30*12, 100000, 10000, 0), -548.8371186466853);
118+  assertEquals(PMT(0.05/12, 30*12, 100000, 10000, false), -548.8371186466853);
119+  assertEquals(PMT(0.05/12, 30*12, 100000, 10000, 1), -546.559786204168);
120+  assertEquals(PMT(0.05/12, 30*12, 100000, 10000, 100), -546.559786204168);
121+  assertEquals(PMT([0.05/12, []], [30*12], ["100000"]), -536.8216230121382);
122+  assertEquals(PMT(-0.0001, 30*12, 100000, 10000, 1), -301.1033887993179);
123+  assertEquals(PMT(-0.0001, 1, 100000, 10000, 1), -110001.000100094);
124+  assertEquals(PMT(-0.0001, 1, 0, 10000, 1), -10001.0001000111);
125+  assertEquals(PMT(-0.0001, 1, 0, 0, 1), 0);
126+  catchAndAssertEquals(function() {
127+    PMT.apply(this, [[[0.05/12]], [], ["100000"]]);
128+  }, ERRORS.REF_ERROR);
129+  catchAndAssertEquals(function() {
130+    PMT.apply(this);
131+  }, ERRORS.NA_ERROR);
132+  catchAndAssertEquals(function() {
133+    PMT.apply(this, [0.05/12, 30*12, 100000, 10000, 1, "nope"]);
134+  }, ERRORS.NA_ERROR);
135+});
136\ No newline at end of file