@travishorn/financejs 1.0.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,13 +30,13 @@ npm install @travishorn/financejs
30
30
  import { pmt, rate, irr } from "@travishorn/financejs";
31
31
 
32
32
  const payment = pmt(0.0525, 5, -10000);
33
- // 2325.7331680465
33
+ // 2325.733168046526
34
34
 
35
35
  const periodicRate = rate(60, 500, -25000);
36
- // 0.00618341316125388
36
+ // 0.006183413161254404
37
37
 
38
38
  const internalRate = irr([-1500, 500, 500, 500, 500]);
39
- // 0.125898324962364
39
+ // 0.12589832495374934
40
40
  ```
41
41
 
42
42
  ## Excel-style conventions
@@ -53,76 +53,140 @@ const internalRate = irr([-1500, 500, 500, 500, 500]);
53
53
 
54
54
  ### Input Variables
55
55
 
56
- | Variable | Description |
57
- | -------- | ------------------------------------------------------------------------------------- |
58
- | `pv` | Present value |
59
- | `fv` | Future value |
60
- | `pmt` | Payment |
61
- | `nper` | Total number of periods |
62
- | `per` | A specific period |
63
- | `rate` | Rate for the period(s) |
64
- | `type` | When payments are due. `0` = end of period/arrears. `1` = beginning of period/advance |
65
- | `guess` | A guess at the rate |
66
- | `values` | A set of periodic cash flows |
56
+ | Variable | Description |
57
+ | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
58
+ | `cost` | The initial cost of the asset. |
59
+ | `dates` | A schedule of payment dates that corresponds to the cash flow payments. The first payment date indicates the beginning of the schedule of payments. All other dates must be later than this date, but they may occur in any order. |
60
+ | `effectRate` | The effective interest rate. |
61
+ | `endPeriod` | The last period in the calculation. |
62
+ | `factor` | The rate at which the balance declines. |
63
+ | `financeRate` | The interest rate you pay on the money used in the cash flows. |
64
+ | `fv` | The future value or a cash balance you want to attain after the last payment is made. If `fv` is omitted, it is assumed to be `0` (the future value of a loan, for example, is 0). For example, if you want to save $50,000 to pay for a special project in 18 years, then $50,000 is the future value. You could then make a conservative guess at an interest rate and determine how much you must save each month. |
65
+ | `guess` | A number that you guess is close to the result. In most cases you do not need to provide `guess` for the calculation to succeeed. If a RangeError is thrown, or if the result is not close to what you expected, try again with a different value for `guess`. |
66
+ | `life` | The number of periods over which the asset is depreciated (sometimes called the useful life of the asset). |
67
+ | `month` | The number of months in the first year. |
68
+ | `nominalRate` | The nominal interest rate. |
69
+ | `nper` | The total number of payment periods in an annuity. For example, if you get a four-year car loan and make monthly payments, your loan has 4 \* 12 (or 48) periods. You would enter `48` for `per`. |
70
+ | `npery` | The number of compounding periods per year. |
71
+ | `per` | The period for which you want to find the interest and must be in the range `1` to `nper`. |
72
+ | `period` | The period for which you want to calculate the depreciation. Period must use the same units as `life`. |
73
+ | `pmt` | The payment made each period and cannot change over the life of the annuity. Typically, `pmt` includes principal and interest but no other fees or taxes. For example, the monthly payments on a $10,000, four-year car loan at 12 percent are $263.33. You would enter `-263.33` as the `pmt`. |
74
+ | `pv` | The present value, or the lump-sum amount that a series of future payments is worth right now. |
75
+ | `rate` | The interest rate per period. For example, if you obtain an automobile loan at a 10 percent annual interest rate and make monthly payments, your interest rate per month is 10% / 12, or 0.83%. You would enter `0.10 / 12` or `0.0083`, into the formula as the rate. |
76
+ | `reinvestRate` | The interest rate you receive on the cash flows as you reinvest them. |
77
+ | `salvage` | The value at the end of the depreciation (sometimes called the salvage value of the asset). |
78
+ | `startPeriod` | The first period in the calculation. Payment periods are numbered beginning with 1. |
79
+ | `type` | The number `0` or `1` and indicates when payments are due. Set `type` equal to `0` or omitted if payments are due at the end of the period. Set `type` equal to `1` if payments are due at the beginning of the period. |
80
+ | `values` | Array of cash flows, where each entry represents a payment (negative) or income (positive) at a regular interval. |
81
+
82
+ ### `cumipmt(rate, nper, pv, startPeriod, endPeriod, type)`
83
+
84
+ Calculates the the cumulative interest paid on a loan between a start period and
85
+ an end period.
86
+
87
+ ### `cumprinc(rate, nper, pv, startPeriod, endPeriod, type)`
88
+
89
+ Calculates the cumulative principal paid on a loan between a start period and an
90
+ end period.
91
+
92
+ ### `db(cost, salvage, life, period, month = 12)`
93
+
94
+ Calculates the depreciation of an asset for a specified period using the
95
+ fixed-declining balance method.
96
+
97
+ ### `ddb(cost, salvage, life, period, factor = 2)`
98
+
99
+ Calculates the depreciation of an asset for a specified period using the
100
+ double-declining balance method or some other method you specify.
101
+
102
+ ### `effect(nominalRate, npery)`
103
+
104
+ Calculates the effective annual interest rate, given the nominal annual interest
105
+ rate and the number of compounding periods per year.
67
106
 
68
- ### `pv(rate, nper, pmt, fv = 0, type = 0)`
107
+ ### `fv(rate, nper, pmt, pv, type = 0)`
69
108
 
70
- Returns the present value of an investment, or the total amount that a series of
71
- future payments is worth now.
109
+ Calculates the future value of an investment based on a constant interest rate.
110
+ You can use FV with either periodic, constant payments, or a single lump sum
111
+ payment.
72
112
 
73
- ### `fv(rate, nper, pmt, pv, type = 0)`
113
+ ### `ipmt(rate, per, nper, pv, fv = 0, type = 0)`
74
114
 
75
- Returns the future value of an investment based on periodic, equal, payments and
76
- a constant interest rate.
115
+ Returns the interest payment for a given period for an investment based on
116
+ periodic, constant payments and a constant interest rate.
77
117
 
78
- ### `pmt(rate, nper, pv, fv = 0, type = 0)`
118
+ ### `irr(values, guess = 0.1)`
79
119
 
80
- Calculates the payment for a loan based on a constant stream of equal payments
81
- and a constant interest rate.
120
+ Calculates the internal rate of return for a series of cash flows represented by
121
+ the numbers in `values`. These cash flows do not have to be even, as they would
122
+ be for an annuity. However, the cash flows must occur at regular intervals, such
123
+ as monthly or annually. The internal rate of return is the interest rate
124
+ received for an investment consisting of payments (negative values) and income
125
+ (positive values) that occur at regular periods.
126
+
127
+ ### `mirr(values, financeRate, reinvestRate)`
128
+
129
+ Calculates the modified internal rate of return for a series of periodic cash
130
+ flows. Considers both the cost of the investment and the interest received on
131
+ reinvestment of cash.
132
+
133
+ ### `nominal(effectRate, npery)`
134
+
135
+ Calculates the nominal annual interest rate, given the effective rate and the
136
+ number of compounding periods per year.
82
137
 
83
138
  ### `nper(rate, pmt, pv, fv = 0, type = 0)`
84
139
 
85
- Number of periods.
140
+ Calculates the number of periods for an investment based on periodic, constant
141
+ payments and a constant interest rate.
86
142
 
87
- ### `ipmt(rate, per, nper, pv, fv = 0, type = 0)`
143
+ ### `npv(rate, ...values)`
88
144
 
89
- Returns the calculated interest portion of a payment for a specific period based
90
- on a constant stream of equal payments and a constant interest rate.
145
+ Calculates the net present value of an investment by using a discount rate and a
146
+ series of future payments (negative values) and income (positive values).
147
+
148
+ ### `pmt(rate, nper, pv, fv = 0, type = 0)`
149
+
150
+ Calculates the payment for a loan based on constant payments and a constant
151
+ interest rate.
91
152
 
92
153
  ### `ppmt(rate, per, nper, pv, fv = 0, type = 0)`
93
154
 
94
- Returns the calculated principal portion of a payment for a specific period
95
- based on a constant stream of equal payments and a constant interest rate.
155
+ Calculates the payment on the principal for a given period for an investment
156
+ based on periodic, constant payments and a constant interest rate.
157
+
158
+ ### `pv(rate, nper, pmt, fv = 0, type = 0)`
159
+
160
+ Calculates the present value of a loan or an investment, based on a constant
161
+ interest rate. You can use PV with either periodic, constant payments (such as a
162
+ mortgage or other loan), or a future value that's your investment goal.
96
163
 
97
164
  ### `rate(nper, pmt, pv, fv = 0, type = 0, guess = 0.1)`
98
165
 
99
- Returns the interest rate per period for a loan or investment (iterative solve).
166
+ Calculates the interest rate per period of an annuity. The rate is calculated by
167
+ iteration and can have zero or more solutions. If the successive results of this
168
+ function do not converge to within 0.0000001 after 128 iterations, a RangeError
169
+ is thrown.
100
170
 
101
- ### `npv(rate, ...values)`
171
+ ### `sln(cost, salvage, life)`
102
172
 
103
- Returns the net present value of an investment based on a constant rate of
104
- return and a series of future payments/investments (as negative values) and
105
- income/return (as positive values).
173
+ Calculates the straight-line depreciation of an asset for one period.
106
174
 
107
- ### `irr(values, guess = 0.1)`
175
+ ### `syd(cost, salvage, life, per)`
108
176
 
109
- Returns the internal rate of return for a series of cash flows.
177
+ Calculates the sum-of-years' digits depreciation of an asset for a specified
178
+ period.
110
179
 
111
- A couple of items to note about this formula:
180
+ ### `xirr(values, dates, guess = 0.1)`
112
181
 
113
- - The variable values must be input as an array.
114
- - There must be at least one negative and one positive value as part of the cash flow.
115
- - Cash flows are assumed to be due in the same order they are arranged in the Array.
182
+ Calculates the internal rate of return for a schedule of cash flows that is
183
+ not necessarily periodic. To calculate the internal rate of return for a
184
+ series of periodic cash flows, use the `irr()` function.
116
185
 
117
- Example usage:
186
+ ### `xnpv(rate, values, dates)`
118
187
 
119
- ```javascript
120
- returnIRR() {
121
- const values = [-1500, 500, 500, 500, 500];
122
- return Math.round(irr(values) * 100 ) / 100 * 100;
123
- }
124
- // returns 12.59
125
- ```
188
+ Calculates the net present value for a schedule of cash flows that is not
189
+ necessarily periodic.
126
190
 
127
191
  ## Error behavior
128
192
 
@@ -172,6 +236,20 @@ npm run format
172
236
  This rewrite is intended to match Excel-style formulas closely (tests validate
173
237
  to 8 decimal places), while using a modern JavaScript module API.
174
238
 
239
+ ## Roadmap
240
+
241
+ I want to add more [Excel financial
242
+ functions](https://support.microsoft.com/en-us/office/financial-functions-reference-5658d81e-6035-4f24-89c1-fbf124c2b1d8)
243
+ to the project. Since there are over 50 functions, I'll break them into "tiers."
244
+
245
+ - **Tier 1:** ✓pmt, ✓pv, ✓fv, ✓npv, ✓irr, ✓rate, ✓nper, ✓xnpv, ✓xirr
246
+ - **Tier 2:** ✓ipmt, ✓ppmt, ✓cumipmt, ✓cumprinc, ✓sln, ✓db, ✓ddb, ✓effect,
247
+ ✓nominal, ✓syd, ✓mirr
248
+ - **Tier 3:** rri, pduration, vdb, fvschedule, dollarde, dollarfr, ispmt
249
+ - **Tier 4:** yield, price, duration, mduration, disc, intrate, received,
250
+ pricedisc, pricemat, yielddisc, yieldmat
251
+ - **Tier 5:** all others
252
+
175
253
  ## License
176
254
 
177
255
  The MIT License
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travishorn/financejs",
3
- "version": "1.0.0",
3
+ "version": "1.10.0",
4
4
  "description": "Modern JavaScript time value of money and cash-flow financial formulas with Excel-style behavior.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,10 +20,11 @@
20
20
  "access": "public"
21
21
  },
22
22
  "scripts": {
23
- "test": "vitest --run",
24
- "lint": "eslint .",
23
+ "format": "prettier --write .",
24
+ "lint:format": "prettier --check .",
25
25
  "lint:types": "tsc --noEmit",
26
- "format": "prettier --write ."
26
+ "lint": "eslint .",
27
+ "test": "vitest --run"
27
28
  },
28
29
  "keywords": [
29
30
  "finance",
package/src/cumipmt.js ADDED
@@ -0,0 +1,58 @@
1
+ import { ipmt } from "./ipmt.js";
2
+
3
+ /**
4
+ * Calculates the cumulative interest paid on a loan between a start period and
5
+ * and end period.
6
+ *
7
+ * Remarks:
8
+ * - Make sure that you are consistent about the units you use for specifying
9
+ * `rate` and `nper`. If you make monthly payments on a four-year loan at an
10
+ * annual interest rate of 12 percent, use `0.12 / 12` for `rate` and `4 * 12`
11
+ * for `nper`. If you make annual payments on the same loan, use `0.12` for
12
+ * `rate` and `4` for `nper`.
13
+ * - If `rate` <= `0`, `nper` <= `0`, or `pv` <= `0`, this function throws a
14
+ * RangeError.
15
+ * - If `startPeriod` < `1`, `endPeriod` < `1`, or `startPeriod` >
16
+ * `endPeriod`, this function throws a RangeError.
17
+ *
18
+ * @param {number} rate - The interest rate.
19
+ * @param {number} nper - The total number of payment periods.
20
+ * @param {number} pv - The present value.
21
+ * @param {number} startPeriod - The first period in the calculation. Payment
22
+ * periods are numbered beginning with 1.
23
+ * @param {number} endPeriod - The last period in the calculation.
24
+ * @param {0|1} type - The timing of the payment. `0` (zero) = payment at
25
+ * the end of the period. `1` = payment at the beginning of the period.
26
+ * @returns {number} The cumulative interest paid
27
+ *
28
+ * @example
29
+ * cumipmt(0.09 / 12, 30 * 12, 125000, 13, 24, 0); // -11135.23213075
30
+ */
31
+ export function cumipmt(rate, nper, pv, startPeriod, endPeriod, type) {
32
+ // Input validation
33
+ if (rate <= 0 || nper <= 0 || pv <= 0) {
34
+ throw new RangeError("rate, nper, and pv must be > 0");
35
+ }
36
+
37
+ if (
38
+ startPeriod < 1 ||
39
+ endPeriod < 1 ||
40
+ startPeriod > endPeriod ||
41
+ startPeriod > nper ||
42
+ endPeriod > nper
43
+ ) {
44
+ throw new RangeError("Invalid startPeriod or endPeriod");
45
+ }
46
+
47
+ if (type !== 0 && type !== 1) {
48
+ throw new RangeError("type must be 0 or 1");
49
+ }
50
+
51
+ let cumInterest = 0;
52
+
53
+ for (let per = startPeriod; per <= endPeriod; per++) {
54
+ cumInterest += ipmt(rate, per, nper, pv, 0, type);
55
+ }
56
+
57
+ return cumInterest;
58
+ }
@@ -0,0 +1,62 @@
1
+ import { pmt } from "./pmt.js";
2
+ import { ipmt } from "./ipmt.js";
3
+
4
+ /**
5
+ * Calculates the cumulative principal paid on a loan between a start period and
6
+ * an end period.
7
+ *
8
+ * Remarks:
9
+ * - Make sure that you are consistent about the units you use for specifying
10
+ * `rate` and `nper`. If you make monthly payments on a four-year loan at an
11
+ * annual interest rate of 12 percent, use `0.12 / 12` for `rate` and `4 * 12`
12
+ * for `nper`. If you make annual payments on the same loan, use `0.12` for
13
+ * `rate` and `4` for `nper`.
14
+ * - If `rate` <= `0`, `nper` <= `0`, or `pv` <= `0`, this function throws a
15
+ * RangeError.
16
+ * - If `startPeriod` < `1`, `endPeriod` < `1`, or `startPeriod` > `endPeriod`,
17
+ * this function throws a RangeError.
18
+ *
19
+ * @param {number} rate - The interest rate.
20
+ * @param {number} nper - The total number of payment periods.
21
+ * @param {number} pv - The present value.
22
+ * @param {number} startPeriod - The first period in the calculation. Payment
23
+ * periods are numbered beginning with 1.
24
+ * @param {number} endPeriod - The last period in the calculation.
25
+ * @param {0|1} type - The timing of the payment. `0` (zero) = payment at the
26
+ * end of the period. `1` = payment at the beginning of the period.
27
+ * @returns {number} The cumulative interest paid
28
+ *
29
+ * @example
30
+ * cumprinc(0.09 / 12, 30 * 12, 125000, 13, 24, 0); // -934.10712342
31
+ */
32
+ export function cumprinc(rate, nper, pv, startPeriod, endPeriod, type) {
33
+ // Input validation
34
+ if (rate <= 0 || nper <= 0 || pv <= 0) {
35
+ throw new RangeError("rate, nper, and pv must be > 0");
36
+ }
37
+
38
+ if (
39
+ startPeriod < 1 ||
40
+ endPeriod < 1 ||
41
+ startPeriod > endPeriod ||
42
+ startPeriod > nper ||
43
+ endPeriod > nper
44
+ ) {
45
+ throw new RangeError("Invalid startPeriod or endPeriod");
46
+ }
47
+
48
+ if (type !== 0 && type !== 1) {
49
+ throw new RangeError("type must be 0 or 1");
50
+ }
51
+
52
+ let cumPrincipal = 0;
53
+
54
+ for (let per = startPeriod; per <= endPeriod; per++) {
55
+ // Principal = payment - interest for this period
56
+ const payment = pmt(rate, nper, pv, 0, type);
57
+ const interest = ipmt(rate, per, nper, pv, 0, type);
58
+ cumPrincipal += payment - interest;
59
+ }
60
+
61
+ return cumPrincipal;
62
+ }
package/src/db.js ADDED
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Calculates the depreciation of an asset for a specified period using the
3
+ * fixed-declining balance method.
4
+ *
5
+ * Remarks:
6
+ * - The fixed-declining balance method computes depreciation at a fixed rate.
7
+ * Uses the following formulas to calculate depreciation for a period: `(cost
8
+ * - total depreciation from prior periods) * rate`, where `rate = 1 -
9
+ * ((salvage / cost) ^ (1 / life))`, rounded to three decimal places.
10
+ * - Depreciation for the first and last periods is a special case. For the
11
+ * first period, this function uses this formula: `cost * rate * month / 12`
12
+ * - For the last period, DB uses this formula: `((cost - total depreciation
13
+ * from prior periods) * rate * (12 - month)) / 12`
14
+ *
15
+ * @param {number} cost - The initial cost of the asset.
16
+ * @param {number} salvage - The value at the end of the depreciation (sometimes
17
+ * called the salvage value of the asset).
18
+ * @param {number} life - The number of periods over which the asset is
19
+ * depreciated (sometimes called the useful life of the asset).
20
+ * @param {number} period - The period for which you want to calculate the
21
+ * depreciation. Period must use the same units as `life`.
22
+ * @param {number} [month=12] - The number of months in the first year. If month
23
+ * is omitted, it is assumed to be `12`.
24
+ * @returns {number} the depreciation
25
+ *
26
+ * @example
27
+ * db(1000000, 100000, 6, 1, 7); // 186083.33333333
28
+ */
29
+ export function db(cost, salvage, life, period, month = 12) {
30
+ // Calculate the fixed rate, rounded to 3 decimal places
31
+ const rate = +(1 - Math.pow(salvage / cost, 1 / life)).toFixed(3);
32
+
33
+ if (period === 1) {
34
+ // First period: prorated by month
35
+ return (cost * rate * month) / 12;
36
+ }
37
+
38
+ // Calculate value after first period (prorated)
39
+ let value = cost - (cost * rate * month) / 12;
40
+
41
+ // For periods > 2, apply normal declining balance for each period
42
+ for (let p = 2; p < period; p++) {
43
+ value -= value * rate;
44
+ }
45
+
46
+ // Determine if this is the last period (partial year)
47
+ // The last period is when the sum of months in all periods reaches 12*life
48
+ // For the test case, period 7 is the last period (since month=7, life=6)
49
+ const totalMonths = (period - 1) * 12 + month;
50
+ const isLastPeriod = totalMonths > life * 12;
51
+
52
+ let dep;
53
+ if (isLastPeriod) {
54
+ // Last period: prorate by (12 - month)
55
+ dep = (value * rate * (12 - month)) / 12;
56
+ } else {
57
+ dep = value * rate;
58
+ }
59
+ return dep;
60
+ }
package/src/ddb.js ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Calculates the depreciation of an asset for a specified period using the
3
+ * double-declining balance method or some other method you specify.
4
+ *
5
+ * Remarks:
6
+ * - The double-declining balance method computes depreciation at an accelerated
7
+ * rate. Depreciation is highest in the first period and decreases in
8
+ * successive periods. This function uses the following formula to calculate
9
+ * depreciation for a period: `Min( (cost - total depreciation from prior
10
+ * periods) * (factor/life), (cost - salvage - total depreciation from prior
11
+ * periods) )`
12
+ * - Change `factor` if you do not want to use the double-declining balance
13
+ * method.
14
+ *
15
+ * @param {number} cost - The initial cost of the asset.
16
+ * @param {number} salvage - The value at the end of the depreciation (sometimes
17
+ * called the salvage value of the asset). This value can be `0`.
18
+ * @param {number} life - The number of periods over which the asset is
19
+ * depreciated (sometimes called the useful life of the asset).
20
+ * @param {number} period - The period for which you want to calculate the
21
+ * depreciation. Period must use the same units as `life`.
22
+ * @param {number} [factor=2] - The rate at which the balance declines. If
23
+ * `factor` is omitted, it is assumed to be `2` (the double-declining balance
24
+ * method).
25
+ * @returns {number} the depreciation
26
+ * @throws {RangeError} When `period` is outside the valid range.
27
+ *
28
+ * @example
29
+ * ddb(2400, 300, 10 * 365, 1); // 1.31506849
30
+ */
31
+ export function ddb(cost, salvage, life, period, factor = 2) {
32
+ let accDep = 0;
33
+ let value = cost;
34
+
35
+ for (let p = 1; p <= period; p++) {
36
+ // Calculate depreciation for this period
37
+ let dep = Math.min(value * (factor / life), cost - salvage - accDep);
38
+
39
+ if (p === period) {
40
+ return dep;
41
+ }
42
+
43
+ accDep += dep;
44
+ value -= dep;
45
+ }
46
+
47
+ // Period is out of range
48
+ throw new RangeError("Invalid period");
49
+ }
package/src/effect.js ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Calculates the effective annual interest rate, given the nominal annual
3
+ * interest rate and the number of compounding periods per year.
4
+ *
5
+ * Remarks:
6
+ * - `npery` is truncated to an integer.
7
+ * - If either argument is nonnumeric, an error is thrown.
8
+ * - If `nominalRate` <= `0` or if `npery` < `1`, an error is thrown.
9
+ * - Rate is calculated as follows: `(1 + nominalRate / npery)^npery - 1`
10
+ * - This function is related to `nominal()` through `effectiveRate = (1 +
11
+ * (nominalRate / npery)) * npery - 1`.
12
+ *
13
+ * @param {number} nominalRate - The nominal interest rate.
14
+ * @param {number} npery - The number of compounding periods per year.
15
+ * @returns {number} the effective annual interest rate
16
+ *
17
+ * @example
18
+ * effect(0.0525, 4); // 0.05354267
19
+ */
20
+ export function effect(nominalRate, npery) {
21
+ if (
22
+ typeof nominalRate !== "number" ||
23
+ typeof npery !== "number" ||
24
+ isNaN(nominalRate) ||
25
+ isNaN(npery)
26
+ ) {
27
+ throw new TypeError("Both arguments must be numbers");
28
+ }
29
+
30
+ if (nominalRate <= 0) {
31
+ throw new RangeError("nominalRate must be > 0");
32
+ }
33
+
34
+ npery = Math.trunc(npery);
35
+
36
+ if (npery < 1) {
37
+ throw new RangeError("npery must be >= 1");
38
+ }
39
+
40
+ return Math.pow(1 + nominalRate / npery, npery) - 1;
41
+ }
package/src/fv.js CHANGED
@@ -1,24 +1,47 @@
1
+ import { normalizeZero } from "./normalizeZero.js";
2
+
1
3
  /**
2
- * Calculates the future value of an investment or loan.
4
+ * Calculates the future value of an investment based on a constant interest
5
+ * rate. You can use FV with either periodic, constant payments, or a single
6
+ * lump sum payment.
7
+ *
8
+ * Remarks:
9
+ * - Be consistent with units for `rate` and `nper`. For example, for monthly
10
+ * payments on a four-year loan at 12% annual interest, use `12%/12` for
11
+ * `rate` and `4*12` for `nper`. For annual payments, use `12%` for `rate` and
12
+ * `4` for `nper`.
13
+ * - Cash paid out (for example, deposits to savings) is represented by negative
14
+ * numbers; cash received is represented by positive numbers.
3
15
  *
4
16
  * @param {number} rate - The interest rate per period.
5
- * @param {number} nper - The total number of payment periods.
6
- * @param {number} pmt - The payment made each period.
7
- * @param {number} pv - The present value.
8
- * @param {0|1} [type=0] - Payment timing: 0 = end of period, 1 = beginning of period.
17
+ * @param {number} nper - The total number of payment periods in an annuity.
18
+ * @param {number} [pmt=0] - The payment made each period; it cannot change over
19
+ * the life of the annuity. Typically, pmt contains principal and interest but
20
+ * no other fees or taxes. If `pmt` is omitted, you must include the `pv`
21
+ * argument.
22
+ * @param {number} [pv=0] - The present value, or the lump-sum amount that a
23
+ * series of future payments is worth right now. If `pv` is omitted, it is
24
+ * assumed to be `0` (zero), and you must include the `pmt` argument.
25
+ * @param {0|1} [type=0] - The number `0` or `1` and indicates when payments are
26
+ * due. If `type` is omitted, it is assumed to be `0`. Set `type` equal to `0`
27
+ * if payments are due at the end of the period. Set `type` equal to `1` if
28
+ * payments are due at the beginning of the period.
9
29
  * @returns {number} The future value.
30
+ *
31
+ * @example
32
+ * fv(0.06 / 12, 10, -200, -500, 1); // 2581.40
10
33
  */
11
- export function fv(rate, nper, pmt, pv, type = 0) {
34
+ export function fv(rate, nper, pmt = 0, pv = 0, type = 0) {
12
35
  if (rate === 0) {
13
- return -pv - pmt * nper;
36
+ return normalizeZero(-pv - pmt * nper);
14
37
  } else {
15
38
  const paymentTimingFactor = type !== 0 ? 1 + rate : 1;
16
39
  const interestFactor = 1 + rate;
17
40
  const compoundFactor = Math.pow(interestFactor, nper);
18
41
 
19
- return (
42
+ return normalizeZero(
20
43
  -pv * compoundFactor -
21
- (pmt / rate) * paymentTimingFactor * (compoundFactor - 1)
44
+ (pmt / rate) * paymentTimingFactor * (compoundFactor - 1),
22
45
  );
23
46
  }
24
47
  }
package/src/index.js CHANGED
@@ -1,9 +1,20 @@
1
- export { pv } from "./pv.js";
2
- export { nper } from "./nper.js";
3
- export { pmt } from "./pmt.js";
1
+ export { cumipmt } from "./cumipmt.js";
2
+ export { cumprinc } from "./cumprinc.js";
3
+ export { db } from "./db.js";
4
+ export { ddb } from "./ddb.js";
5
+ export { effect } from "./effect.js";
4
6
  export { fv } from "./fv.js";
5
7
  export { ipmt } from "./ipmt.js";
6
- export { ppmt } from "./ppmt.js";
7
- export { npv } from "./npv.js";
8
8
  export { irr } from "./irr.js";
9
+ export { mirr } from "./mirr.js";
10
+ export { nominal } from "./nominal.js";
11
+ export { nper } from "./nper.js";
12
+ export { npv } from "./npv.js";
13
+ export { pmt } from "./pmt.js";
14
+ export { ppmt } from "./ppmt.js";
15
+ export { pv } from "./pv.js";
9
16
  export { rate } from "./rate.js";
17
+ export { sln } from "./sln.js";
18
+ export { syd } from "./syd.js";
19
+ export { xirr } from "./xirr.js";
20
+ export { xnpv } from "./xnpv.js";