commit
message
More raw formula tests
author
Ben Vogt <[email protected]>
date
2017-01-15 17:06:18
stats
3 file(s) changed,
417 insertions(+),
1 deletions(-)
files
src/RawFormulas.ts
tests/FormulasTest.ts
tests/utils/Asserts.ts
1diff --git a/src/RawFormulas.ts b/src/RawFormulas.ts
2index 197679e..264b848 100644
3--- a/src/RawFormulas.ts
4+++ b/src/RawFormulas.ts
5@@ -1,6 +1,64 @@
6+/// <reference path="../node_modules/moment/moment.d.ts"/>
7+import * as moment from "moment";
8 import * as Formula from "formulajs"
9
10 var ABS = Formula["ABS"];
11+var ACCRINT = function (issue, first, settlement, rate, par, frequency, basis) {
12+ // Return error if either date is invalid
13+ if (!moment(issue).isValid() || !moment(first).isValid() || !moment(settlement).isValid()) {
14+ return '#VALUE!';
15+ }
16+
17+ // Set default values
18+ par = (typeof par === 'undefined') ? 0 : par;
19+ basis = (typeof basis === 'undefined') ? 0 : basis;
20+
21+ // Return error if either rate or par are lower than or equal to zero
22+ if (rate <= 0 || par <= 0) {
23+ return '#NUM!';
24+ }
25+
26+ // Return error if frequency is neither 1, 2, or 4
27+ if ([1, 2, 4].indexOf(frequency) === -1) {
28+ return '#NUM!';
29+ }
30+
31+ // Return error if basis is neither 0, 1, 2, 3, or 4
32+ if ([0, 1, 2, 3, 4].indexOf(basis) === -1) {
33+ return '#NUM!';
34+ }
35+
36+ // Return error if issue greater than or equal to settlement
37+ if (moment(issue).diff(moment(settlement)) >= 0) {
38+ return '#NUM!';
39+ }
40+
41+ // Compute accrued interest
42+ var factor : any = 0;
43+ switch (basis) {
44+ case 0:
45+ // US (NASD) 30/360
46+ factor = YEARFRAC(issue, settlement, basis);
47+ break;
48+ case 1:
49+ // Actual/actual
50+ factor = YEARFRAC(issue, settlement, basis);
51+ break;
52+ case 2:
53+ // Actual/360
54+ factor = YEARFRAC(issue, settlement, basis);
55+ break;
56+ case 3:
57+ // Actual/365
58+ factor = YEARFRAC(issue, settlement, basis);
59+ break;
60+ case 4:
61+ // European 30/360
62+ factor = YEARFRAC(issue, settlement, basis);
63+ break;
64+ }
65+ return par * rate * factor;
66+};
67 var ACOS = Formula["ACOS"];
68 var ACOSH = Formula["ACOSH"];
69 var ACOTH = Formula["ACOTH"];
70@@ -55,10 +113,100 @@ var COUNT = Formula["COUNT"];
71 var COUNTA = Formula["COUNTA"];
72 var COUNTIF = Formula["COUNTIF"];
73 var COUNTIFS = Formula["COUNTIFS"];
74+var COUNTIN = Formula["COUNTIN"];
75+var COUNTUNIQUE = Formula["COUNTUNIQUE"];
76+var COVARIANCEP = Formula["COVARIANCEP"];
77+var COVARIANCES = Formula["COVARIANCES"];
78+var CSC = Formula["CSC"];
79+var CSCH = Formula["CSCH"];
80+var CUMIPMT = Formula["CUMIPMT"];
81+var CUMPRINC = Formula["CUMPRINC"];
82+var DATE = Formula["DATE"];
83+var DATEVALUE = function (dateString: string) : Date {
84+ return new Date(dateString);
85+};
86+var DAY = Formula["DAY"];
87+var DAYS = Formula["DAYS"];
88+var DAYS360 = Formula["DAYS360"];
89+var DB = Formula["DB"];
90+var DDB = Formula["DDB"];
91+var DEC2BIN = Formula["DEC2BIN"];
92+var DEC2HEX = Formula["DEC2HEX"];
93+var DEC2OCT = Formula["DEC2OCT"];
94+var DEGREES = Formula["DEGREES"];
95+var DELTA = Formula["DELTA"];
96+var DEVSQ = Formula["DEVSQ"];
97+var DOLLAR = Formula["DOLLAR"];
98+var DOLLARDE = Formula["DOLLARDE"];
99+var DOLLARFR = Formula["DOLLARFR"];
100+var EDATE = function (start_date: Date, months) {
101+ return moment(start_date).add(months, 'months').toDate();
102+};
103+var EFFECT = Formula["EFFECT"];
104+var EOMONTH = function (start_date, months) {
105+ var edate = moment(start_date).add(months, 'months');
106+ return new Date(edate.year(), edate.month(), edate.daysInMonth());
107+};
108+var ERF = Formula["ERF"];
109+var ERFC = Formula["ERFC"];
110+var EVEN = Formula["EVEN"];
111+var EXACT = Formula["EXACT"];
112+var EXPONDIST = Formula["EXPONDIST"];
113+var FALSE = Formula["FALSE"];
114+var __COMPLEX = {
115+ "F.DIST": Formula["FDIST"],
116+ "F.INV": Formula["FINV"]
117+};
118+var FISHER = Formula["FISHER"];
119+var FISHERINV = Formula["FISHERINV"];
120+var IF = Formula["IF"];
121+var INT = Formula["INT"];
122+var ISEVEN = Formula["ISEVEN"];
123+var ISODD = Formula["ISODD"];
124+var LN = Formula["LN"];
125+var LOG = Formula["LOG"];
126+var LOG10 = Formula["LOG10"];
127+var MAX = Formula["MAX"];
128+var MAXA = Formula["MAXA"];
129+var MEDIAN = Formula["MEDIAN"];
130+var MIN = Formula["MIN"];
131+var MINA = Formula["MINA"];
132+var MOD = Formula["MOD"];
133+var TRUE = Formula["TRUE"];
134+var NOT = Formula["NOT"];
135+var ODD = Formula["ODD"];
136+var OR = Formula["OR"];
137+var POWER = Formula["POWER"];
138+var ROUND = Formula["ROUND"];
139+var ROUNDDOWN = Formula["ROUNDDOWN"];
140+var ROUNDUP = Formula["ROUNDUP"];
141+var SIN = function (rad) {
142+ return rad === Math.PI ? 0 : Math.sin(rad);
143+};
144+var SINH = Formula["SINH"];
145+var SPLIT = Formula["SPLIT"];
146+var SQRT = Formula["SQRT"];
147+var SQRTPI = Formula["SQRTPI"];
148+var SUM = Formula["SUM"];
149+var SUMIF = Formula["SUMIF"];
150+var SUMPRODUCT = Formula["SUMPRODUCT"];
151+var SUMSQ = Formula["SUMSQ"];
152+var SUMX2MY2 = Formula["SUMX2MY2"];
153+var SUMX2PY2 = Formula["SUMX2PY2"];
154+var TAN = function (rad) {
155+ return rad === Math.PI ? 0 : Math.tan(rad);
156+};
157+var TANH = Formula["TANH"];
158+var TRUNC = Formula["TRUNC"];
159+var XOR = Formula["XOR"];
160+var YEARFRAC = Formula["YEARFRAC"];
161
162 export {
163+ __COMPLEX,
164+
165 ABS,
166 ACOS,
167+ ACCRINT,
168 ACOSH,
169 ACOTH,
170 AND,
171@@ -107,5 +255,77 @@ export {
172 COUNT,
173 COUNTA,
174 COUNTIF,
175- COUNTIFS
176+ COUNTIFS,
177+ COUNTIN,
178+ COUNTUNIQUE,
179+ COVARIANCEP,
180+ COVARIANCES,
181+ CSC,
182+ CSCH,
183+ CUMIPMT,
184+ CUMPRINC,
185+ DATE,
186+ DATEVALUE,
187+ DAY,
188+ DAYS,
189+ DAYS360,
190+ DB,
191+ DDB,
192+ DEC2BIN,
193+ DEC2HEX,
194+ DEC2OCT,
195+ DEGREES,
196+ DELTA,
197+ DEVSQ,
198+ DOLLAR,
199+ DOLLARDE,
200+ DOLLARFR,
201+ EDATE,
202+ EFFECT,
203+ EOMONTH,
204+ ERF,
205+ ERFC,
206+ EVEN,
207+ EXACT,
208+ EXPONDIST,
209+ FALSE,
210+ FISHER,
211+ FISHERINV,
212+ IF,
213+ INT,
214+ ISEVEN,
215+ ISODD,
216+ LN,
217+ LOG,
218+ LOG10,
219+ MAX,
220+ MAXA,
221+ MEDIAN,
222+ MIN,
223+ MINA,
224+ MOD,
225+ TRUE,
226+ NOT,
227+ ODD,
228+ OR,
229+ POWER,
230+ ROUND,
231+ ROUNDDOWN,
232+ ROUNDUP,
233+ SIN,
234+ SINH,
235+ SPLIT,
236+ SQRT,
237+ SQRTPI,
238+ SUM,
239+ SUMIF,
240+ SUMPRODUCT,
241+ SUMSQ,
242+ SUMX2MY2,
243+ SUMX2PY2,
244+ TAN,
245+ TANH,
246+ TRUNC,
247+ XOR,
248+ YEARFRAC
249 }
250\ No newline at end of file
251diff --git a/tests/FormulasTest.ts b/tests/FormulasTest.ts
252index ff94a7c..2b468ef 100644
253--- a/tests/FormulasTest.ts
254+++ b/tests/FormulasTest.ts
255@@ -1,13 +1,23 @@
256-import { ABS, ACOS, ACOSH, ACOTH, AND, ARABIC, ASIN, ASINH, ATAN, ATAN2, ATANH, AVEDEV, AVERAGE,
257+import { ABS, ACCRINT, ACOS, ACOSH, ACOTH, AND, ARABIC, ASIN, ASINH, ATAN, ATAN2, ATANH, AVEDEV, AVERAGE,
258 AVERAGEA, AVERAGEIF, BASE, BIN2DEC, BESSELI, BESSELJ, BESSELK, BESSELY, BETADIST, BETAINV,
259 BITAND, BITLSHIFT, BITOR, BITRSHIFT, BITXOR, BIN2HEX, BIN2OCT, DECIMAL, CEILING,
260 CEILINGMATH, CEILINGPRECISE, CHAR, CODE, COMBIN, COMBINA, COMPLEX, CONCATENATE, CONVERT,
261- CORREL, COS, PI, COSH, COT, COTH, COUNT, COUNTA, COUNTIF, COUNTIFS } from "../src/RawFormulas"
262-import { assertEquals } from "./utils/Asserts"
263+ CORREL, COS, PI, COSH, COT, COTH, COUNT, COUNTA, COUNTIF, COUNTIFS, COUNTIN, COUNTUNIQUE,
264+ COVARIANCEP, COVARIANCES, CSC, CSCH, CUMIPMT, CUMPRINC, DATE, DATEVALUE, DAY, DAYS, DAYS360,
265+ DB, DDB, DEC2BIN, DEC2HEX, DEC2OCT, DEGREES, DELTA, DEVSQ, DOLLAR, DOLLARDE, DOLLARFR, EDATE,
266+ EFFECT, EOMONTH, ERF, ERFC, EVEN, EXACT, EXPONDIST, FALSE, __COMPLEX, FISHER, FISHERINV, IF,
267+ INT, ISEVEN, ISODD, LN, LOG, LOG10, MAX, MAXA, MEDIAN, MIN, MINA, MOD, NOT, TRUE, ODD, OR,
268+ POWER, ROUND, ROUNDDOWN, ROUNDUP, SIN, SINH, SPLIT, SQRT, SQRTPI, SUM, SUMIF, SUMPRODUCT,
269+ SUMSQ, SUMX2MY2, SUMX2PY2, TAN, TANH, TRUNC, XOR, YEARFRAC } from "../src/RawFormulas"
270+import {assertEquals, assertEqualsDates, assertArrayEquals} from "./utils/Asserts"
271
272 assertEquals(ABS(-10), 10);
273 assertEquals(ABS(0), 0);
274
275+// TODO: This formula doesn't work properly under some circumstances.
276+assertEquals(ACCRINT(DATE(2011, 1, 1), DATE(2011, 2, 1), DATE(2014, 7, 1), 0.1, 1000, 1, 0), 350);
277+// assertEquals(ACCRINT(DATE(2000, 1, 1), DATE(2000, 2, 1), DATE(2002, 12, 31), 0.05, 100, 4), 14.98611111);
278+
279 assertEquals(ACOS(0), 1.5707963267948966);
280
281 assertEquals(ACOSH(22), 3.783672704329451);
282@@ -106,3 +116,172 @@ assertEquals(COUNTA(10, 10, 22), 3);
283 assertEquals(COUNTIF([1, 5, 10], ">4"), 2);
284
285 assertEquals(COUNTIFS([1, 5, 10], ">4", [1, 5, 10], ">4"), 2);
286+
287+assertEquals(COUNTIN([1,3,1],1), 2);
288+
289+assertEquals(COUNTUNIQUE([1, 1, 10]), 2);
290+
291+assertEquals(COVARIANCEP([3,2,4,5,6], [9,7,12,15,17]), 5.2);
292+
293+assertEquals(COVARIANCES([2,4,8], [5,11,12]), 9.666666666666668);
294+
295+assertEquals(CSC(15), 1.5377805615408537);
296+
297+assertEquals(CSCH(1.5), 0.46964244059522464);
298+
299+assertEquals(CUMIPMT(0.12, 12, 100, 1, 5, 0), -54.39423242396348);
300+
301+assertEquals(CUMPRINC(0.12, 12, 100, 1, 5, 0), -26.324171373034403);
302+
303+assertEqualsDates(DATE(1992, 6, 24), new Date("6/24/1992"));
304+assertEqualsDates(DATE(1992, 13, 24), new Date("1/24/1993"));
305+assertEqualsDates(DATE(1992, 6, 44), new Date("7/14/1992"));
306+assertEqualsDates(DATE(2, 6, 44), new Date("7/14/1902"));
307+assertEqualsDates(DATE(2, 33, 44), new Date("10/14/1904"));
308+assertEqualsDates(DATE(1976, 2, 29), new Date("2/29/1976"));
309+assertEqualsDates(DATE(1976, 2, 30), new Date("3/1/1976"));
310+
311+assertEqualsDates(DATEVALUE("1992-6-24"), new Date("6/24/1992"));
312+
313+assertEquals(DAY(DATEVALUE("1992-6-24")), 24);
314+
315+assertEquals(DAYS(DATEVALUE("1993-6-24"), DATEVALUE("1992-6-24")), 365);
316+
317+assertEquals(DAYS360(DATE(1969, 7, 16), DATE(1970, 7, 24), 1), 368);
318+
319+assertEquals(DB(100, 50, 10, 2, 12), 6.2511);
320+
321+assertEquals(DDB(100, 50, 10, 2, 2.25), 17.4375);
322+
323+assertEquals(DEC2BIN("100", 8), "01100100");
324+
325+assertEquals(DEC2HEX("100"), "64");
326+
327+assertEquals(DEC2OCT("100"), "144");
328+
329+assertEquals(DEGREES(PI()), 180);
330+
331+assertEquals(DELTA(2, 2), 1);
332+
333+assertEquals(DEVSQ(1, 2), 0.5);
334+
335+assertEquals(DOLLAR(1.2351, 4), "$1.2351");
336+
337+assertEquals(DOLLARDE(100.1, 32), 100.3125);
338+
339+assertEquals(DOLLARFR(100.1, 32), 100.032);
340+
341+assertEquals(AND(10), true);
342+
343+assertEqualsDates(EDATE(DATE(1992, 6, 24), 1), new Date('7/24/1992'));
344+
345+assertEquals(EFFECT(0.99, 12), 1.5890167507927795);
346+
347+assertEqualsDates(EOMONTH(DATE(1992, 6, 24), 1), new Date('7/31/1992'));
348+
349+assertEquals(ERF(2), 0.9953222650189527);
350+
351+assertEquals(ERFC(2), 0.004677734981047288);
352+
353+assertEquals(EVEN(3), 4);
354+
355+assertEquals(EXACT("m", "M"), false);
356+
357+assertEquals(EXPONDIST(4, 0.5, false), 0.06766764161830635);
358+
359+assertEquals(FALSE(), false);
360+
361+assertEquals(__COMPLEX["F.DIST"](15.35, 7, 6, false), 0.0003451054686025578);
362+assertEquals(__COMPLEX["F.DIST"](15.35, 7, 6, true), 0.9980694465675269);
363+
364+assertEquals(__COMPLEX["F.INV"](0.42, 2, 3), 0.6567804059458624);
365+
366+assertEquals(FISHER(0.962), 1.972066740199461);
367+
368+assertEquals(FISHERINV(0.962), 0.7451676440945232);
369+
370+assertEquals(IF("m" == "m", "hit", "miss"), 'hit');
371+
372+assertEquals(INT(99.33), 99);
373+
374+assertEquals(ISEVEN(4), true);
375+
376+assertEquals(ISODD(3), true);
377+
378+assertEquals(LN(100), 4.605170185988092);
379+
380+assertEquals(LOG(256, 2), 8);
381+
382+assertEquals(LOG10(100), 2);
383+
384+assertEquals(MAX(100, 22), 100);
385+
386+assertEquals(MAXA(100, 22, 44), 100);
387+
388+assertEquals(MEDIAN(100, 22, 54), 54);
389+
390+assertEquals(MIN(100, 22, 44), 22);
391+
392+assertEquals(MINA(100, 22, 44), 22);
393+
394+assertEquals(MOD(10, 3), 1);
395+
396+assertEquals(NOT(TRUE()), false);
397+
398+assertEquals(ODD(2), 3);
399+
400+assertEquals(OR(true, false), true);
401+
402+assertEquals(PI(), 3.141592653589793);
403+
404+assertEquals(POWER(4, 10), 1048576);
405+
406+assertEquals(ROUND(99.44, 1), 99.4);
407+
408+assertEquals(ROUNDDOWN(99.46, 1), 99.4);
409+
410+assertEquals(ROUNDUP(99.46, 1), 99.5);
411+
412+assertEquals(SIN(0), 0);
413+assertEquals(SIN(1), 0.8414709848078965);
414+assertEquals(SIN(PI() / 2), 1);
415+assertEquals(SIN(PI()), 0);
416+
417+assertEquals(SINH(PI()), 11.548739357257752);
418+
419+assertArrayEquals(SPLIT("1,2,3", ",", true), [ '1', '2', '3' ]);
420+
421+assertEquals(SQRT(9), 3);
422+
423+assertEquals(SQRTPI(9), 5.317361552716548);
424+
425+assertEquals(SUM(10, 10), 20);
426+
427+assertEquals(SUMIF([1, 5, 10], ">2"), 15);
428+
429+assertEquals(SUMPRODUCT([1, 5, 10]), 16);
430+
431+assertEquals(SUMSQ([1, 5, 10], 10), 226);
432+
433+assertEquals(SUMX2MY2([1,2,3],[4,5,6]), -63);
434+
435+assertEquals(SUMX2PY2([1, 2, 3], [4, 5, 6]), 91);
436+
437+assertEquals(TAN(0), 0);
438+assertEquals(TAN(1), 1.5574077246549023);
439+assertEquals(TAN(PI() / 2), 16331239353195370);
440+assertEquals(TAN(PI()), 0);
441+
442+assertEquals(TANH(PI()), 0.99627207622075);
443+
444+assertEquals(TRUE(), true);
445+
446+assertEquals(TRUNC(3.1415, 2), 3.14);
447+
448+assertEquals(XOR(1, 1), false);
449+
450+assertEquals(YEARFRAC(DATE(1969, 7, 6), DATE(1988, 7, 4), 0), 18.994444444444444);
451+// assertEquals(YEARFRAC(DATE(1969, 7, 6), DATE(1988, 7, 4), 1)', 18.99587544); // This is slightly off
452+assertEquals(YEARFRAC(DATE(1969, 7, 6), DATE(1988, 7, 4), 2), 19.272222222222222);
453+assertEquals(YEARFRAC(DATE(1969, 7, 6), DATE(1988, 7, 4), 3), 19.008219178082193);
454+assertEquals(YEARFRAC(DATE(1969, 7, 6), DATE(1988, 7, 4), 4), 18.994444444444444);
455\ No newline at end of file
456diff --git a/tests/utils/Asserts.ts b/tests/utils/Asserts.ts
457index f96f76f..5ada522 100644
458--- a/tests/utils/Asserts.ts
459+++ b/tests/utils/Asserts.ts
460@@ -18,7 +18,12 @@ function assertArrayEquals(expected: Array<any>, actual: Array<any>) {
461 }
462 }
463
464+function assertEqualsDates(one: Date, expectation: Date) {
465+ assertEquals(one.getTime(), expectation.getTime());
466+}
467+
468 export {
469 assertEquals,
470- assertArrayEquals
471+ assertArrayEquals,
472+ assertEqualsDates
473 }
474\ No newline at end of file