@travishorn/financejs 1.18.0 → 1.19.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 +1 -1
- package/package.json +1 -1
- package/src/coupdaybs.js +64 -0
- package/src/coupdays.js +69 -0
- package/src/coupdaysnc.js +63 -0
- package/src/index.js +3 -0
- package/src/price.js +6 -1
- package/src/util.js +1 -1
- package/src/yield_.js +6 -1
package/README.md
CHANGED
|
@@ -113,7 +113,7 @@ Tiers 1-3 are complete.
|
|
|
113
113
|
- **Tier 3:** ✓rri, ✓pduration, ✓vdb, ✓fvschedule, ✓dollarde, ✓dollarfr, ✓ispmt
|
|
114
114
|
- **Tier 4:** ✓yield, ✓price, duration, mduration, disc, intrate, received,
|
|
115
115
|
pricedisc, pricemat, yielddisc, yieldmat
|
|
116
|
-
- **Tier 5:** all others
|
|
116
|
+
- **Tier 5:** ✓coupdaybs, ✓coupdays, ✓coupdaysnc, all others
|
|
117
117
|
|
|
118
118
|
## License
|
|
119
119
|
|
package/package.json
CHANGED
package/src/coupdaybs.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
coupdaybs as coupdaybsUtil,
|
|
3
|
+
getCouponBounds,
|
|
4
|
+
toUtcDate,
|
|
5
|
+
} from "./util.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Returns the number of days from the beginning of the coupon period to the
|
|
9
|
+
* settlement date.
|
|
10
|
+
*
|
|
11
|
+
* Remarks:
|
|
12
|
+
* - `settlement`, `maturity`, `frequency`, and `basis` are truncated to
|
|
13
|
+
* integers.
|
|
14
|
+
* - If `settlement` or `maturity` is not a valid date, an error is thrown.
|
|
15
|
+
* - If `frequency` is any number other than `1`, `2`, or `4`, an error is
|
|
16
|
+
* thrown.
|
|
17
|
+
* - If `basis` < `0` or if `basis` > `4`, an error is thrown.
|
|
18
|
+
* - If `settlement` >= `maturity`, an error is thrown.
|
|
19
|
+
*
|
|
20
|
+
* @param {Date} settlement - The security's settlement date.
|
|
21
|
+
* @param {Date} maturity - The security's maturity date.
|
|
22
|
+
* @param {1|2|4} frequency - The number of coupon payments per year. For annual
|
|
23
|
+
* payments, frequency = `1`; for semiannual, frequency = `2`; for quarterly,
|
|
24
|
+
* frequency = `4`.
|
|
25
|
+
* @param {0|1|2|3|4} [basis=0] - The type of day count basis to use. `0` or
|
|
26
|
+
* omitted = US (NASD 30/360), `1` = actual/actual, `2` = actual/360, `3` =
|
|
27
|
+
* actual/365, `4` = European 30/360.
|
|
28
|
+
* @returns {number} The number of days from the beginning of the coupon period
|
|
29
|
+
* to the settlement date.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* coupdaybs(new Date("2011-01-25"), new Date("2011-11-15"), 2, 1); // 71
|
|
33
|
+
*/
|
|
34
|
+
export function coupdaybs(settlement, maturity, frequency, basis = 0) {
|
|
35
|
+
const settlementDate = toUtcDate(settlement);
|
|
36
|
+
const maturityDate = toUtcDate(maturity);
|
|
37
|
+
|
|
38
|
+
frequency = /** @type {1|2|4} */ (Math.trunc(frequency));
|
|
39
|
+
const basisNumber = Math.trunc(basis ?? 0);
|
|
40
|
+
|
|
41
|
+
if (![1, 2, 4].includes(frequency)) {
|
|
42
|
+
throw new RangeError("Invalid frequency.");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (basisNumber < 0 || basisNumber > 4) {
|
|
46
|
+
throw new RangeError("Invalid basis.");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** @type {0|1|2|3|4} */
|
|
50
|
+
const normalizedBasis = /** @type {0|1|2|3|4} */ (basisNumber);
|
|
51
|
+
|
|
52
|
+
if (settlementDate >= maturityDate) {
|
|
53
|
+
throw new RangeError("Settlement must be before maturity.");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const monthsPerCoupon = 12 / frequency;
|
|
57
|
+
const { previousCouponDate } = getCouponBounds(
|
|
58
|
+
settlementDate,
|
|
59
|
+
maturityDate,
|
|
60
|
+
monthsPerCoupon,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return coupdaybsUtil(previousCouponDate, settlementDate, normalizedBasis);
|
|
64
|
+
}
|
package/src/coupdays.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
coupdays as coupdaysUtil,
|
|
3
|
+
getCouponBounds,
|
|
4
|
+
toUtcDate,
|
|
5
|
+
} from "./util.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Returns the number of days in the coupon period that contains the settlement
|
|
9
|
+
* date.
|
|
10
|
+
*
|
|
11
|
+
* Remarks:
|
|
12
|
+
* - `settlement`, `maturity`, `frequency`, and `basis` are truncated to
|
|
13
|
+
* integers.
|
|
14
|
+
* - If `settlement` or `maturity` is not a valid date, an error is thrown.
|
|
15
|
+
* - If `frequency` is any number other than `1`, `2`, or `4`, an error is
|
|
16
|
+
* thrown.
|
|
17
|
+
* - If `basis` < `0` or if `basis` > `4`, an error is thrown.
|
|
18
|
+
* - If `settlement` >= `maturity`, an error is thrown.
|
|
19
|
+
*
|
|
20
|
+
* @param {Date} settlement - The security's settlement date.
|
|
21
|
+
* @param {Date} maturity - The security's maturity date.
|
|
22
|
+
* @param {1|2|4} frequency - The number of coupon payments per year. For annual
|
|
23
|
+
* payments, frequency = `1`; for semiannual, frequency = `2`; for quarterly,
|
|
24
|
+
* frequency = `4`.
|
|
25
|
+
* @param {0|1|2|3|4} [basis=0] - The type of day count basis to use. `0` or
|
|
26
|
+
* omitted = US (NASD 30/360), `1` = actual/actual, `2` = actual/360, `3` =
|
|
27
|
+
* actual/365, `4` = European 30/360.
|
|
28
|
+
* @returns {number} The number of days in the coupon period that contains the
|
|
29
|
+
* settlement date.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* coupdays(new Date("2011-01-25"), new Date("2011-11-15"), 2, 1); // 184
|
|
33
|
+
*/
|
|
34
|
+
export function coupdays(settlement, maturity, frequency, basis = 0) {
|
|
35
|
+
const settlementDate = toUtcDate(settlement);
|
|
36
|
+
const maturityDate = toUtcDate(maturity);
|
|
37
|
+
|
|
38
|
+
frequency = /** @type {1|2|4} */ (Math.trunc(frequency));
|
|
39
|
+
const basisNumber = Math.trunc(basis ?? 0);
|
|
40
|
+
|
|
41
|
+
if (![1, 2, 4].includes(frequency)) {
|
|
42
|
+
throw new RangeError("Invalid frequency.");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (basisNumber < 0 || basisNumber > 4) {
|
|
46
|
+
throw new RangeError("Invalid basis.");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** @type {0|1|2|3|4} */
|
|
50
|
+
const normalizedBasis = /** @type {0|1|2|3|4} */ (basisNumber);
|
|
51
|
+
|
|
52
|
+
if (settlementDate >= maturityDate) {
|
|
53
|
+
throw new RangeError("Settlement must be before maturity.");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const monthsPerCoupon = 12 / frequency;
|
|
57
|
+
const { previousCouponDate, nextCouponDate } = getCouponBounds(
|
|
58
|
+
settlementDate,
|
|
59
|
+
maturityDate,
|
|
60
|
+
monthsPerCoupon,
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return coupdaysUtil(
|
|
64
|
+
previousCouponDate,
|
|
65
|
+
nextCouponDate,
|
|
66
|
+
frequency,
|
|
67
|
+
normalizedBasis,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
coupdaysnc as coupdaysncUtil,
|
|
3
|
+
getCouponBounds,
|
|
4
|
+
toUtcDate,
|
|
5
|
+
} from "./util.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Returns the number of days from the settlement date to the next coupon date.
|
|
9
|
+
*
|
|
10
|
+
* Remarks:
|
|
11
|
+
* - `settlement`, `maturity`, `frequency`, and `basis` are truncated to
|
|
12
|
+
* integers.
|
|
13
|
+
* - If `settlement` or `maturity` is not a valid date, an error is thrown.
|
|
14
|
+
* - If `frequency` is any number other than `1`, `2`, or `4`, an error is
|
|
15
|
+
* thrown.
|
|
16
|
+
* - If `basis` < `0` or if `basis` > `4`, an error is thrown.
|
|
17
|
+
* - If `settlement` >= `maturity`, an error is thrown.
|
|
18
|
+
*
|
|
19
|
+
* @param {Date} settlement - The security's settlement date.
|
|
20
|
+
* @param {Date} maturity - The security's maturity date.
|
|
21
|
+
* @param {1|2|4} frequency - The number of coupon payments per year. For annual
|
|
22
|
+
* payments, frequency = `1`; for semiannual, frequency = `2`; for quarterly,
|
|
23
|
+
* frequency = `4`.
|
|
24
|
+
* @param {0|1|2|3|4} [basis=0] - The type of day count basis to use. `0` or
|
|
25
|
+
* omitted = US (NASD 30/360), `1` = actual/actual, `2` = actual/360, `3` =
|
|
26
|
+
* actual/365, `4` = European 30/360.
|
|
27
|
+
* @returns {number} The number of days from the settlement date to the next
|
|
28
|
+
* coupon date.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* coupdaysnc(new Date("2011-01-25"), new Date("2011-11-15"), 2, 1); // 113
|
|
32
|
+
*/
|
|
33
|
+
export function coupdaysnc(settlement, maturity, frequency, basis = 0) {
|
|
34
|
+
const settlementDate = toUtcDate(settlement);
|
|
35
|
+
const maturityDate = toUtcDate(maturity);
|
|
36
|
+
|
|
37
|
+
frequency = /** @type {1|2|4} */ (Math.trunc(frequency));
|
|
38
|
+
const basisNumber = Math.trunc(basis ?? 0);
|
|
39
|
+
|
|
40
|
+
if (![1, 2, 4].includes(frequency)) {
|
|
41
|
+
throw new RangeError("Invalid frequency.");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (basisNumber < 0 || basisNumber > 4) {
|
|
45
|
+
throw new RangeError("Invalid basis.");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** @type {0|1|2|3|4} */
|
|
49
|
+
const normalizedBasis = /** @type {0|1|2|3|4} */ (basisNumber);
|
|
50
|
+
|
|
51
|
+
if (settlementDate >= maturityDate) {
|
|
52
|
+
throw new RangeError("Settlement must be before maturity.");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const monthsPerCoupon = 12 / frequency;
|
|
56
|
+
const { nextCouponDate } = getCouponBounds(
|
|
57
|
+
settlementDate,
|
|
58
|
+
maturityDate,
|
|
59
|
+
monthsPerCoupon,
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
return coupdaysncUtil(settlementDate, nextCouponDate, normalizedBasis);
|
|
63
|
+
}
|
package/src/index.js
CHANGED
package/src/price.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
actualDays,
|
|
2
3
|
coupdaybs,
|
|
3
4
|
coupdays,
|
|
4
5
|
coupdaysnc,
|
|
@@ -108,13 +109,17 @@ export function price(
|
|
|
108
109
|
|
|
109
110
|
const a = coupdaybs(previousCouponDate, settlementDate, normalizedBasis);
|
|
110
111
|
let dsc = coupdaysnc(settlementDate, nextCouponDate, normalizedBasis);
|
|
111
|
-
|
|
112
|
+
let e = coupdays(
|
|
112
113
|
previousCouponDate,
|
|
113
114
|
nextCouponDate,
|
|
114
115
|
frequency,
|
|
115
116
|
normalizedBasis,
|
|
116
117
|
);
|
|
117
118
|
|
|
119
|
+
if (normalizedBasis === 2) {
|
|
120
|
+
e = actualDays(previousCouponDate, nextCouponDate);
|
|
121
|
+
}
|
|
122
|
+
|
|
118
123
|
if (normalizedBasis === 3) {
|
|
119
124
|
dsc = e - a;
|
|
120
125
|
}
|
package/src/util.js
CHANGED
|
@@ -283,7 +283,7 @@ export function coupdaybs(previousCouponDate, settlementDate, basis) {
|
|
|
283
283
|
* coupdays(new Date("2024-01-01"), new Date("2024-07-01"), 2, 3); // 182.5
|
|
284
284
|
*/
|
|
285
285
|
export function coupdays(previousCouponDate, nextCouponDate, frequency, basis) {
|
|
286
|
-
if (basis === 0 || basis === 4) {
|
|
286
|
+
if (basis === 0 || basis === 2 || basis === 4) {
|
|
287
287
|
return 360 / frequency;
|
|
288
288
|
}
|
|
289
289
|
|
package/src/yield_.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
actualDays,
|
|
2
3
|
coupdaybs,
|
|
3
4
|
coupdays,
|
|
4
5
|
coupdaysnc,
|
|
@@ -108,13 +109,17 @@ export function yield_(
|
|
|
108
109
|
|
|
109
110
|
const a = coupdaybs(previousCouponDate, settlementDate, normalizedBasis);
|
|
110
111
|
let dsc = coupdaysnc(settlementDate, nextCouponDate, normalizedBasis);
|
|
111
|
-
|
|
112
|
+
let e = coupdays(
|
|
112
113
|
previousCouponDate,
|
|
113
114
|
nextCouponDate,
|
|
114
115
|
frequency,
|
|
115
116
|
normalizedBasis,
|
|
116
117
|
);
|
|
117
118
|
|
|
119
|
+
if (normalizedBasis === 2) {
|
|
120
|
+
e = actualDays(previousCouponDate, nextCouponDate);
|
|
121
|
+
}
|
|
122
|
+
|
|
118
123
|
if (normalizedBasis === 3) {
|
|
119
124
|
dsc = e - a;
|
|
120
125
|
}
|