@fintekkers/ledger-models 0.4.1 → 0.4.3
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/hierarchy.json +2 -2
- package/node/fintekkers/models/security/bond/agency_grpc_pb.js +1 -0
- package/node/fintekkers/models/security/bond/agency_pb.d.ts +14 -0
- package/node/fintekkers/models/security/bond/agency_pb.js +35 -0
- package/node/fintekkers/models/security/product_type_pb.d.ts +1 -0
- package/node/fintekkers/models/security/product_type_pb.js +1 -0
- package/node/fintekkers/models/security/security_pb.d.ts +69 -0
- package/node/fintekkers/models/security/security_pb.js +572 -1
- package/node/wrappers/models/security/BondSecurity.d.ts +5 -21
- package/node/wrappers/models/security/BondSecurity.fromPricerInputs.test.js +17 -11
- package/node/wrappers/models/security/BondSecurity.fromPricerInputs.test.js.map +1 -1
- package/node/wrappers/models/security/BondSecurity.fromPricerInputs.test.ts +17 -11
- package/node/wrappers/models/security/BondSecurity.js +15 -32
- package/node/wrappers/models/security/BondSecurity.js.map +1 -1
- package/node/wrappers/models/security/BondSecurity.ts +18 -37
- package/node/wrappers/models/security/Issuance.d.ts +3 -5
- package/node/wrappers/models/security/Issuance.js +3 -8
- package/node/wrappers/models/security/Issuance.js.map +1 -1
- package/node/wrappers/models/security/Issuance.test.js +16 -8
- package/node/wrappers/models/security/Issuance.test.js.map +1 -1
- package/node/wrappers/models/security/Issuance.test.ts +10 -2
- package/node/wrappers/models/security/Issuance.ts +6 -12
- package/node/wrappers/models/security/MortgageBackedSecurity.d.ts +48 -0
- package/node/wrappers/models/security/MortgageBackedSecurity.fromPricerInputs.test.d.ts +1 -0
- package/node/wrappers/models/security/MortgageBackedSecurity.fromPricerInputs.test.js +97 -0
- package/node/wrappers/models/security/MortgageBackedSecurity.fromPricerInputs.test.js.map +1 -0
- package/node/wrappers/models/security/MortgageBackedSecurity.fromPricerInputs.test.ts +111 -0
- package/node/wrappers/models/security/MortgageBackedSecurity.js +131 -0
- package/node/wrappers/models/security/MortgageBackedSecurity.js.map +1 -0
- package/node/wrappers/models/security/MortgageBackedSecurity.ts +125 -0
- package/node/wrappers/models/security/TIPSBond.d.ts +2 -3
- package/node/wrappers/models/security/TIPSBond.js +2 -4
- package/node/wrappers/models/security/TIPSBond.js.map +1 -1
- package/node/wrappers/models/security/TIPSBond.ts +5 -7
- package/node/wrappers/models/security/security.d.ts +39 -12
- package/node/wrappers/models/security/security.js +64 -16
- package/node/wrappers/models/security/security.js.map +1 -1
- package/node/wrappers/models/security/security.test.js +91 -10
- package/node/wrappers/models/security/security.test.js.map +1 -1
- package/node/wrappers/models/security/security.test.ts +106 -11
- package/node/wrappers/models/security/security.ts +70 -17
- package/node/wrappers/models/transaction/transaction.d.ts +2 -3
- package/node/wrappers/models/transaction/transaction.js +23 -21
- package/node/wrappers/models/transaction/transaction.js.map +1 -1
- package/node/wrappers/models/transaction/transaction.ts +22 -21
- package/node/wrappers/models/transaction/transaction_constructor.test.js +4 -2
- package/node/wrappers/models/transaction/transaction_constructor.test.js.map +1 -1
- package/node/wrappers/models/transaction/transaction_constructor.test.ts +10 -8
- package/node/wrappers/models/utils/date.d.ts +13 -1
- package/node/wrappers/models/utils/date.js +26 -1
- package/node/wrappers/models/utils/date.js.map +1 -1
- package/node/wrappers/models/utils/date.ts +25 -1
- package/node/wrappers/services/security-service/security.maturityLadder.test.js +4 -2
- package/node/wrappers/services/security-service/security.maturityLadder.test.js.map +1 -1
- package/node/wrappers/services/security-service/security.maturityLadder.test.ts +3 -2
- package/package.json +1 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const security_1 = __importDefault(require("./security"));
|
|
7
|
+
const BondSecurity_1 = __importDefault(require("./BondSecurity"));
|
|
8
|
+
const MortgageBackedSecurity_1 = __importDefault(require("./MortgageBackedSecurity"));
|
|
9
|
+
const security_pb_1 = require("../../../fintekkers/models/security/security_pb");
|
|
10
|
+
const product_type_pb_1 = require("../../../fintekkers/models/security/product_type_pb");
|
|
11
|
+
const coupon_type_pb_1 = require("../../../fintekkers/models/security/coupon_type_pb");
|
|
12
|
+
const coupon_frequency_pb_1 = require("../../../fintekkers/models/security/coupon_frequency_pb");
|
|
13
|
+
const agency_pb_1 = require("../../../fintekkers/models/security/bond/agency_pb");
|
|
14
|
+
const decimal_js_1 = require("decimal.js");
|
|
15
|
+
function makeDate(y, m, d) {
|
|
16
|
+
const date = new Date(y, m - 1, d);
|
|
17
|
+
date.setHours(0, 0, 0, 0);
|
|
18
|
+
return date;
|
|
19
|
+
}
|
|
20
|
+
const baseInputs = {
|
|
21
|
+
faceValue: new decimal_js_1.Decimal('250000000'),
|
|
22
|
+
couponRate: new decimal_js_1.Decimal('0.04'),
|
|
23
|
+
couponType: coupon_type_pb_1.CouponTypeProto.FIXED,
|
|
24
|
+
couponFrequency: coupon_frequency_pb_1.CouponFrequencyProto.MONTHLY,
|
|
25
|
+
issueDate: makeDate(2024, 1, 1),
|
|
26
|
+
maturityDate: makeDate(2054, 1, 1),
|
|
27
|
+
};
|
|
28
|
+
const mbsInputs = Object.assign(Object.assign({}, baseInputs), { poolNumber: 'FN AS1234', agency: agency_pb_1.AgencyProto.FNMA, wac: new decimal_js_1.Decimal('0.045'), wam: 358, passThroughRate: new decimal_js_1.Decimal('0.04'), currentFactor: new decimal_js_1.Decimal('0.95'), originalFaceValue: new decimal_js_1.Decimal('250000000'), currentUpb: new decimal_js_1.Decimal('237500000'), psaSpeed: new decimal_js_1.Decimal('150') });
|
|
29
|
+
test('MortgageBackedSecurity.fromPricerInputs populates bond_details and mbs_extension', () => {
|
|
30
|
+
var _a, _b, _c, _d, _e, _f;
|
|
31
|
+
const proto = MortgageBackedSecurity_1.default.fromPricerInputs(mbsInputs);
|
|
32
|
+
expect(proto.getProductType()).toBe(product_type_pb_1.ProductTypeProto.MORTGAGE_BACKED);
|
|
33
|
+
expect(proto.hasBondDetails()).toBe(true);
|
|
34
|
+
expect(proto.hasMbsExtension()).toBe(true);
|
|
35
|
+
const ext = proto.getMbsExtension();
|
|
36
|
+
expect(ext.getPoolNumber()).toBe('FN AS1234');
|
|
37
|
+
expect(ext.getAgency()).toBe(agency_pb_1.AgencyProto.FNMA);
|
|
38
|
+
expect((_a = ext.getWac()) === null || _a === void 0 ? void 0 : _a.getArbitraryPrecisionValue()).toBe('0.045');
|
|
39
|
+
expect(ext.getWam()).toBe(358);
|
|
40
|
+
expect((_b = ext.getPassThroughRate()) === null || _b === void 0 ? void 0 : _b.getArbitraryPrecisionValue()).toBe('0.04');
|
|
41
|
+
expect((_c = ext.getCurrentFactor()) === null || _c === void 0 ? void 0 : _c.getArbitraryPrecisionValue()).toBe('0.95');
|
|
42
|
+
expect((_d = ext.getOriginalFaceValue()) === null || _d === void 0 ? void 0 : _d.getArbitraryPrecisionValue()).toBe('250000000');
|
|
43
|
+
expect((_e = ext.getCurrentUpb()) === null || _e === void 0 ? void 0 : _e.getArbitraryPrecisionValue()).toBe('237500000');
|
|
44
|
+
expect((_f = ext.getPsaSpeed()) === null || _f === void 0 ? void 0 : _f.getArbitraryPrecisionValue()).toBe('150');
|
|
45
|
+
});
|
|
46
|
+
test('MortgageBackedSecurity round-trips via serializeBinary / deserializeBinary preserving all 9 mbs fields', () => {
|
|
47
|
+
var _a, _b, _c, _d, _e, _f;
|
|
48
|
+
const proto = MortgageBackedSecurity_1.default.fromPricerInputs(mbsInputs);
|
|
49
|
+
const bytes = proto.serializeBinary();
|
|
50
|
+
const round = security_pb_1.SecurityProto.deserializeBinary(bytes);
|
|
51
|
+
expect(round.getProductType()).toBe(product_type_pb_1.ProductTypeProto.MORTGAGE_BACKED);
|
|
52
|
+
expect(round.hasBondDetails()).toBe(true);
|
|
53
|
+
expect(round.hasMbsExtension()).toBe(true);
|
|
54
|
+
const ext = round.getMbsExtension();
|
|
55
|
+
expect(ext.getPoolNumber()).toBe('FN AS1234');
|
|
56
|
+
expect(ext.getAgency()).toBe(agency_pb_1.AgencyProto.FNMA);
|
|
57
|
+
expect((_a = ext.getWac()) === null || _a === void 0 ? void 0 : _a.getArbitraryPrecisionValue()).toBe('0.045');
|
|
58
|
+
expect(ext.getWam()).toBe(358);
|
|
59
|
+
expect((_b = ext.getPassThroughRate()) === null || _b === void 0 ? void 0 : _b.getArbitraryPrecisionValue()).toBe('0.04');
|
|
60
|
+
expect((_c = ext.getCurrentFactor()) === null || _c === void 0 ? void 0 : _c.getArbitraryPrecisionValue()).toBe('0.95');
|
|
61
|
+
expect((_d = ext.getOriginalFaceValue()) === null || _d === void 0 ? void 0 : _d.getArbitraryPrecisionValue()).toBe('250000000');
|
|
62
|
+
expect((_e = ext.getCurrentUpb()) === null || _e === void 0 ? void 0 : _e.getArbitraryPrecisionValue()).toBe('237500000');
|
|
63
|
+
expect((_f = ext.getPsaSpeed()) === null || _f === void 0 ? void 0 : _f.getArbitraryPrecisionValue()).toBe('150');
|
|
64
|
+
});
|
|
65
|
+
test('MortgageBackedSecurity wraps via Security.create factory dispatch', () => {
|
|
66
|
+
const proto = MortgageBackedSecurity_1.default.fromPricerInputs(mbsInputs);
|
|
67
|
+
const sec = security_1.default.create(proto);
|
|
68
|
+
expect(sec).toBeInstanceOf(MortgageBackedSecurity_1.default);
|
|
69
|
+
// Inherits BondSecurity behaviour.
|
|
70
|
+
expect(sec).toBeInstanceOf(BondSecurity_1.default);
|
|
71
|
+
expect(sec.isBond()).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
test('MortgageBackedSecurity typed accessors read back the expected values', () => {
|
|
74
|
+
var _a, _b, _c, _d, _e, _f;
|
|
75
|
+
const proto = MortgageBackedSecurity_1.default.fromPricerInputs(mbsInputs);
|
|
76
|
+
const sec = security_1.default.create(proto);
|
|
77
|
+
// Bond-side checks (inherited from BondSecurity).
|
|
78
|
+
expect(sec.getCouponRate().equals(new decimal_js_1.Decimal('0.04'))).toBe(true);
|
|
79
|
+
expect(sec.getFaceValue().equals(new decimal_js_1.Decimal('250000000'))).toBe(true);
|
|
80
|
+
const issueDate = sec.getIssueDate();
|
|
81
|
+
const maturityDate = sec.getMaturityDate();
|
|
82
|
+
expect(issueDate).toBeInstanceOf(Date);
|
|
83
|
+
expect(maturityDate).toBeInstanceOf(Date);
|
|
84
|
+
expect(issueDate.getFullYear()).toBe(2024);
|
|
85
|
+
expect(maturityDate.getFullYear()).toBe(2054);
|
|
86
|
+
// MBS-specific accessor checks.
|
|
87
|
+
expect(sec.getPoolNumber()).toBe('FN AS1234');
|
|
88
|
+
expect(sec.getAgency()).toBe(agency_pb_1.AgencyProto.FNMA);
|
|
89
|
+
expect((_a = sec.getWac()) === null || _a === void 0 ? void 0 : _a.toString()).toBe('0.045');
|
|
90
|
+
expect(sec.getWam()).toBe(358);
|
|
91
|
+
expect((_b = sec.getPassThroughRate()) === null || _b === void 0 ? void 0 : _b.toString()).toBe('0.04');
|
|
92
|
+
expect((_c = sec.getCurrentFactor()) === null || _c === void 0 ? void 0 : _c.toString()).toBe('0.95');
|
|
93
|
+
expect((_d = sec.getOriginalFaceValue()) === null || _d === void 0 ? void 0 : _d.toString()).toBe('250000000');
|
|
94
|
+
expect((_e = sec.getCurrentUpb()) === null || _e === void 0 ? void 0 : _e.toString()).toBe('237500000');
|
|
95
|
+
expect((_f = sec.getPsaSpeed()) === null || _f === void 0 ? void 0 : _f.toString()).toBe('150');
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=MortgageBackedSecurity.fromPricerInputs.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MortgageBackedSecurity.fromPricerInputs.test.js","sourceRoot":"","sources":["MortgageBackedSecurity.fromPricerInputs.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import Security from './security';
|
|
2
|
+
import BondSecurity from './BondSecurity';
|
|
3
|
+
import MortgageBackedSecurity from './MortgageBackedSecurity';
|
|
4
|
+
import { SecurityProto } from '../../../fintekkers/models/security/security_pb';
|
|
5
|
+
import { ProductTypeProto } from '../../../fintekkers/models/security/product_type_pb';
|
|
6
|
+
import { CouponTypeProto } from '../../../fintekkers/models/security/coupon_type_pb';
|
|
7
|
+
import { CouponFrequencyProto } from '../../../fintekkers/models/security/coupon_frequency_pb';
|
|
8
|
+
import { AgencyProto } from '../../../fintekkers/models/security/bond/agency_pb';
|
|
9
|
+
import { Decimal } from 'decimal.js';
|
|
10
|
+
|
|
11
|
+
function makeDate(y: number, m: number, d: number): Date {
|
|
12
|
+
const date = new Date(y, m - 1, d);
|
|
13
|
+
date.setHours(0, 0, 0, 0);
|
|
14
|
+
return date;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const baseInputs = {
|
|
18
|
+
faceValue: new Decimal('250000000'),
|
|
19
|
+
couponRate: new Decimal('0.04'),
|
|
20
|
+
couponType: CouponTypeProto.FIXED,
|
|
21
|
+
couponFrequency: CouponFrequencyProto.MONTHLY,
|
|
22
|
+
issueDate: makeDate(2024, 1, 1),
|
|
23
|
+
maturityDate: makeDate(2054, 1, 1),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const mbsInputs = {
|
|
27
|
+
...baseInputs,
|
|
28
|
+
poolNumber: 'FN AS1234',
|
|
29
|
+
agency: AgencyProto.FNMA,
|
|
30
|
+
wac: new Decimal('0.045'),
|
|
31
|
+
wam: 358,
|
|
32
|
+
passThroughRate: new Decimal('0.04'),
|
|
33
|
+
currentFactor: new Decimal('0.95'),
|
|
34
|
+
originalFaceValue: new Decimal('250000000'),
|
|
35
|
+
currentUpb: new Decimal('237500000'),
|
|
36
|
+
psaSpeed: new Decimal('150'),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
test('MortgageBackedSecurity.fromPricerInputs populates bond_details and mbs_extension', () => {
|
|
40
|
+
const proto = MortgageBackedSecurity.fromPricerInputs(mbsInputs);
|
|
41
|
+
expect(proto.getProductType()).toBe(ProductTypeProto.MORTGAGE_BACKED);
|
|
42
|
+
expect(proto.hasBondDetails()).toBe(true);
|
|
43
|
+
expect(proto.hasMbsExtension()).toBe(true);
|
|
44
|
+
|
|
45
|
+
const ext = proto.getMbsExtension()!;
|
|
46
|
+
expect(ext.getPoolNumber()).toBe('FN AS1234');
|
|
47
|
+
expect(ext.getAgency()).toBe(AgencyProto.FNMA);
|
|
48
|
+
expect(ext.getWac()?.getArbitraryPrecisionValue()).toBe('0.045');
|
|
49
|
+
expect(ext.getWam()).toBe(358);
|
|
50
|
+
expect(ext.getPassThroughRate()?.getArbitraryPrecisionValue()).toBe('0.04');
|
|
51
|
+
expect(ext.getCurrentFactor()?.getArbitraryPrecisionValue()).toBe('0.95');
|
|
52
|
+
expect(ext.getOriginalFaceValue()?.getArbitraryPrecisionValue()).toBe('250000000');
|
|
53
|
+
expect(ext.getCurrentUpb()?.getArbitraryPrecisionValue()).toBe('237500000');
|
|
54
|
+
expect(ext.getPsaSpeed()?.getArbitraryPrecisionValue()).toBe('150');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('MortgageBackedSecurity round-trips via serializeBinary / deserializeBinary preserving all 9 mbs fields', () => {
|
|
58
|
+
const proto = MortgageBackedSecurity.fromPricerInputs(mbsInputs);
|
|
59
|
+
const bytes = proto.serializeBinary();
|
|
60
|
+
const round = SecurityProto.deserializeBinary(bytes);
|
|
61
|
+
|
|
62
|
+
expect(round.getProductType()).toBe(ProductTypeProto.MORTGAGE_BACKED);
|
|
63
|
+
expect(round.hasBondDetails()).toBe(true);
|
|
64
|
+
expect(round.hasMbsExtension()).toBe(true);
|
|
65
|
+
|
|
66
|
+
const ext = round.getMbsExtension()!;
|
|
67
|
+
expect(ext.getPoolNumber()).toBe('FN AS1234');
|
|
68
|
+
expect(ext.getAgency()).toBe(AgencyProto.FNMA);
|
|
69
|
+
expect(ext.getWac()?.getArbitraryPrecisionValue()).toBe('0.045');
|
|
70
|
+
expect(ext.getWam()).toBe(358);
|
|
71
|
+
expect(ext.getPassThroughRate()?.getArbitraryPrecisionValue()).toBe('0.04');
|
|
72
|
+
expect(ext.getCurrentFactor()?.getArbitraryPrecisionValue()).toBe('0.95');
|
|
73
|
+
expect(ext.getOriginalFaceValue()?.getArbitraryPrecisionValue()).toBe('250000000');
|
|
74
|
+
expect(ext.getCurrentUpb()?.getArbitraryPrecisionValue()).toBe('237500000');
|
|
75
|
+
expect(ext.getPsaSpeed()?.getArbitraryPrecisionValue()).toBe('150');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('MortgageBackedSecurity wraps via Security.create factory dispatch', () => {
|
|
79
|
+
const proto = MortgageBackedSecurity.fromPricerInputs(mbsInputs);
|
|
80
|
+
const sec = Security.create(proto);
|
|
81
|
+
expect(sec).toBeInstanceOf(MortgageBackedSecurity);
|
|
82
|
+
// Inherits BondSecurity behaviour.
|
|
83
|
+
expect(sec).toBeInstanceOf(BondSecurity);
|
|
84
|
+
expect(sec.isBond()).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('MortgageBackedSecurity typed accessors read back the expected values', () => {
|
|
88
|
+
const proto = MortgageBackedSecurity.fromPricerInputs(mbsInputs);
|
|
89
|
+
const sec = Security.create(proto) as MortgageBackedSecurity;
|
|
90
|
+
|
|
91
|
+
// Bond-side checks (inherited from BondSecurity).
|
|
92
|
+
expect(sec.getCouponRate()!.equals(new Decimal('0.04'))).toBe(true);
|
|
93
|
+
expect(sec.getFaceValue()!.equals(new Decimal('250000000'))).toBe(true);
|
|
94
|
+
const issueDate = sec.getIssueDate();
|
|
95
|
+
const maturityDate = sec.getMaturityDate();
|
|
96
|
+
expect(issueDate).toBeInstanceOf(Date);
|
|
97
|
+
expect(maturityDate).toBeInstanceOf(Date);
|
|
98
|
+
expect(issueDate!.getFullYear()).toBe(2024);
|
|
99
|
+
expect(maturityDate!.getFullYear()).toBe(2054);
|
|
100
|
+
|
|
101
|
+
// MBS-specific accessor checks.
|
|
102
|
+
expect(sec.getPoolNumber()).toBe('FN AS1234');
|
|
103
|
+
expect(sec.getAgency()).toBe(AgencyProto.FNMA);
|
|
104
|
+
expect(sec.getWac()?.toString()).toBe('0.045');
|
|
105
|
+
expect(sec.getWam()).toBe(358);
|
|
106
|
+
expect(sec.getPassThroughRate()?.toString()).toBe('0.04');
|
|
107
|
+
expect(sec.getCurrentFactor()?.toString()).toBe('0.95');
|
|
108
|
+
expect(sec.getOriginalFaceValue()?.toString()).toBe('250000000');
|
|
109
|
+
expect(sec.getCurrentUpb()?.toString()).toBe('237500000');
|
|
110
|
+
expect(sec.getPsaSpeed()?.toString()).toBe('150');
|
|
111
|
+
});
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const BondSecurity_1 = __importStar(require("./BondSecurity"));
|
|
27
|
+
const security_pb_1 = require("../../../fintekkers/models/security/security_pb");
|
|
28
|
+
const agency_pb_1 = require("../../../fintekkers/models/security/bond/agency_pb");
|
|
29
|
+
const product_type_pb_1 = require("../../../fintekkers/models/security/product_type_pb");
|
|
30
|
+
const decimal_js_1 = require("decimal.js");
|
|
31
|
+
/**
|
|
32
|
+
* MBS-specific accessors layered on top of BondSecurity. Pool-level fields
|
|
33
|
+
* (agency, WAC, WAM, pass-through rate, factors, balances, PSA) live in
|
|
34
|
+
* the parallel mbs_extension sub-message; bond_details still carries the
|
|
35
|
+
* canonical coupon/dates/face value.
|
|
36
|
+
*/
|
|
37
|
+
class MortgageBackedSecurity extends BondSecurity_1.default {
|
|
38
|
+
constructor(proto) {
|
|
39
|
+
super(proto);
|
|
40
|
+
}
|
|
41
|
+
getMbsExtension() {
|
|
42
|
+
var _a;
|
|
43
|
+
return (_a = this.proto.getMbsExtension()) !== null && _a !== void 0 ? _a : undefined;
|
|
44
|
+
}
|
|
45
|
+
/** Pool identifier (e.g. "FN AS1234"). */
|
|
46
|
+
getPoolNumber() {
|
|
47
|
+
const ext = this.getMbsExtension();
|
|
48
|
+
return ext ? ext.getPoolNumber() : '';
|
|
49
|
+
}
|
|
50
|
+
/** Issuing agency (FNMA / FHLMC / GNMA). */
|
|
51
|
+
getAgency() {
|
|
52
|
+
const ext = this.getMbsExtension();
|
|
53
|
+
return ext ? ext.getAgency() : agency_pb_1.AgencyProto.AGENCY_UNKNOWN;
|
|
54
|
+
}
|
|
55
|
+
/** Weighted Average Coupon across underlying loans. */
|
|
56
|
+
getWac() {
|
|
57
|
+
const ext = this.getMbsExtension();
|
|
58
|
+
const v = ext ? ext.getWac() : undefined;
|
|
59
|
+
if (!v)
|
|
60
|
+
return null;
|
|
61
|
+
return new decimal_js_1.Decimal(v.getArbitraryPrecisionValue());
|
|
62
|
+
}
|
|
63
|
+
/** Weighted Average Maturity, in months. */
|
|
64
|
+
getWam() {
|
|
65
|
+
const ext = this.getMbsExtension();
|
|
66
|
+
return ext ? ext.getWam() : 0;
|
|
67
|
+
}
|
|
68
|
+
/** Pass-through rate paid to investors (net of servicing/guarantee fees). */
|
|
69
|
+
getPassThroughRate() {
|
|
70
|
+
const ext = this.getMbsExtension();
|
|
71
|
+
const v = ext ? ext.getPassThroughRate() : undefined;
|
|
72
|
+
if (!v)
|
|
73
|
+
return null;
|
|
74
|
+
return new decimal_js_1.Decimal(v.getArbitraryPrecisionValue());
|
|
75
|
+
}
|
|
76
|
+
/** Current pool factor (remaining UPB / original face). */
|
|
77
|
+
getCurrentFactor() {
|
|
78
|
+
const ext = this.getMbsExtension();
|
|
79
|
+
const v = ext ? ext.getCurrentFactor() : undefined;
|
|
80
|
+
if (!v)
|
|
81
|
+
return null;
|
|
82
|
+
return new decimal_js_1.Decimal(v.getArbitraryPrecisionValue());
|
|
83
|
+
}
|
|
84
|
+
/** Original face value at issuance. */
|
|
85
|
+
getOriginalFaceValue() {
|
|
86
|
+
const ext = this.getMbsExtension();
|
|
87
|
+
const v = ext ? ext.getOriginalFaceValue() : undefined;
|
|
88
|
+
if (!v)
|
|
89
|
+
return null;
|
|
90
|
+
return new decimal_js_1.Decimal(v.getArbitraryPrecisionValue());
|
|
91
|
+
}
|
|
92
|
+
/** Current Unpaid Principal Balance. */
|
|
93
|
+
getCurrentUpb() {
|
|
94
|
+
const ext = this.getMbsExtension();
|
|
95
|
+
const v = ext ? ext.getCurrentUpb() : undefined;
|
|
96
|
+
if (!v)
|
|
97
|
+
return null;
|
|
98
|
+
return new decimal_js_1.Decimal(v.getArbitraryPrecisionValue());
|
|
99
|
+
}
|
|
100
|
+
/** PSA prepayment speed assumption. */
|
|
101
|
+
getPsaSpeed() {
|
|
102
|
+
const ext = this.getMbsExtension();
|
|
103
|
+
const v = ext ? ext.getPsaSpeed() : undefined;
|
|
104
|
+
if (!v)
|
|
105
|
+
return null;
|
|
106
|
+
return new decimal_js_1.Decimal(v.getArbitraryPrecisionValue());
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Build a fresh SecurityProto for an agency MBS pass-through. product_type
|
|
110
|
+
* is set to MORTGAGE_BACKED so Security.create routes back to this wrapper.
|
|
111
|
+
*/
|
|
112
|
+
static fromPricerInputs(args) {
|
|
113
|
+
const bond = (0, BondSecurity_1.buildBondDetails)(args);
|
|
114
|
+
const mbs = new security_pb_1.MbsExtensionProto()
|
|
115
|
+
.setPoolNumber(args.poolNumber)
|
|
116
|
+
.setAgency(args.agency)
|
|
117
|
+
.setWac((0, BondSecurity_1.decimalToProto)(args.wac))
|
|
118
|
+
.setWam(args.wam)
|
|
119
|
+
.setPassThroughRate((0, BondSecurity_1.decimalToProto)(args.passThroughRate))
|
|
120
|
+
.setCurrentFactor((0, BondSecurity_1.decimalToProto)(args.currentFactor))
|
|
121
|
+
.setOriginalFaceValue((0, BondSecurity_1.decimalToProto)(args.originalFaceValue))
|
|
122
|
+
.setCurrentUpb((0, BondSecurity_1.decimalToProto)(args.currentUpb))
|
|
123
|
+
.setPsaSpeed((0, BondSecurity_1.decimalToProto)(args.psaSpeed));
|
|
124
|
+
return new security_pb_1.SecurityProto()
|
|
125
|
+
.setProductType(product_type_pb_1.ProductTypeProto.MORTGAGE_BACKED)
|
|
126
|
+
.setBondDetails(bond)
|
|
127
|
+
.setMbsExtension(mbs);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
exports.default = MortgageBackedSecurity;
|
|
131
|
+
//# sourceMappingURL=MortgageBackedSecurity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MortgageBackedSecurity.js","sourceRoot":"","sources":["MortgageBackedSecurity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import BondSecurity, {
|
|
2
|
+
BondPricerInputs,
|
|
3
|
+
buildBondDetails,
|
|
4
|
+
decimalToProto,
|
|
5
|
+
} from './BondSecurity';
|
|
6
|
+
import { SecurityProto, MbsExtensionProto } from '../../../fintekkers/models/security/security_pb';
|
|
7
|
+
import { AgencyProto } from '../../../fintekkers/models/security/bond/agency_pb';
|
|
8
|
+
import { ProductTypeProto } from '../../../fintekkers/models/security/product_type_pb';
|
|
9
|
+
import { Decimal } from 'decimal.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* MBS-specific accessors layered on top of BondSecurity. Pool-level fields
|
|
13
|
+
* (agency, WAC, WAM, pass-through rate, factors, balances, PSA) live in
|
|
14
|
+
* the parallel mbs_extension sub-message; bond_details still carries the
|
|
15
|
+
* canonical coupon/dates/face value.
|
|
16
|
+
*/
|
|
17
|
+
class MortgageBackedSecurity extends BondSecurity {
|
|
18
|
+
constructor(proto: SecurityProto) {
|
|
19
|
+
super(proto);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private getMbsExtension(): MbsExtensionProto | undefined {
|
|
23
|
+
return this.proto.getMbsExtension() ?? undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Pool identifier (e.g. "FN AS1234"). */
|
|
27
|
+
getPoolNumber(): string {
|
|
28
|
+
const ext = this.getMbsExtension();
|
|
29
|
+
return ext ? ext.getPoolNumber() : '';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Issuing agency (FNMA / FHLMC / GNMA). */
|
|
33
|
+
getAgency(): AgencyProto {
|
|
34
|
+
const ext = this.getMbsExtension();
|
|
35
|
+
return ext ? ext.getAgency() : AgencyProto.AGENCY_UNKNOWN;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Weighted Average Coupon across underlying loans. */
|
|
39
|
+
getWac(): Decimal | null {
|
|
40
|
+
const ext = this.getMbsExtension();
|
|
41
|
+
const v = ext ? ext.getWac() : undefined;
|
|
42
|
+
if (!v) return null;
|
|
43
|
+
return new Decimal(v.getArbitraryPrecisionValue());
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Weighted Average Maturity, in months. */
|
|
47
|
+
getWam(): number {
|
|
48
|
+
const ext = this.getMbsExtension();
|
|
49
|
+
return ext ? ext.getWam() : 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Pass-through rate paid to investors (net of servicing/guarantee fees). */
|
|
53
|
+
getPassThroughRate(): Decimal | null {
|
|
54
|
+
const ext = this.getMbsExtension();
|
|
55
|
+
const v = ext ? ext.getPassThroughRate() : undefined;
|
|
56
|
+
if (!v) return null;
|
|
57
|
+
return new Decimal(v.getArbitraryPrecisionValue());
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Current pool factor (remaining UPB / original face). */
|
|
61
|
+
getCurrentFactor(): Decimal | null {
|
|
62
|
+
const ext = this.getMbsExtension();
|
|
63
|
+
const v = ext ? ext.getCurrentFactor() : undefined;
|
|
64
|
+
if (!v) return null;
|
|
65
|
+
return new Decimal(v.getArbitraryPrecisionValue());
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Original face value at issuance. */
|
|
69
|
+
getOriginalFaceValue(): Decimal | null {
|
|
70
|
+
const ext = this.getMbsExtension();
|
|
71
|
+
const v = ext ? ext.getOriginalFaceValue() : undefined;
|
|
72
|
+
if (!v) return null;
|
|
73
|
+
return new Decimal(v.getArbitraryPrecisionValue());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Current Unpaid Principal Balance. */
|
|
77
|
+
getCurrentUpb(): Decimal | null {
|
|
78
|
+
const ext = this.getMbsExtension();
|
|
79
|
+
const v = ext ? ext.getCurrentUpb() : undefined;
|
|
80
|
+
if (!v) return null;
|
|
81
|
+
return new Decimal(v.getArbitraryPrecisionValue());
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** PSA prepayment speed assumption. */
|
|
85
|
+
getPsaSpeed(): Decimal | null {
|
|
86
|
+
const ext = this.getMbsExtension();
|
|
87
|
+
const v = ext ? ext.getPsaSpeed() : undefined;
|
|
88
|
+
if (!v) return null;
|
|
89
|
+
return new Decimal(v.getArbitraryPrecisionValue());
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Build a fresh SecurityProto for an agency MBS pass-through. product_type
|
|
94
|
+
* is set to MORTGAGE_BACKED so Security.create routes back to this wrapper.
|
|
95
|
+
*/
|
|
96
|
+
static fromPricerInputs(args: BondPricerInputs & {
|
|
97
|
+
poolNumber: string;
|
|
98
|
+
agency: AgencyProto;
|
|
99
|
+
wac: Decimal;
|
|
100
|
+
wam: number;
|
|
101
|
+
passThroughRate: Decimal;
|
|
102
|
+
currentFactor: Decimal;
|
|
103
|
+
originalFaceValue: Decimal;
|
|
104
|
+
currentUpb: Decimal;
|
|
105
|
+
psaSpeed: Decimal;
|
|
106
|
+
}): SecurityProto {
|
|
107
|
+
const bond = buildBondDetails(args);
|
|
108
|
+
const mbs = new MbsExtensionProto()
|
|
109
|
+
.setPoolNumber(args.poolNumber)
|
|
110
|
+
.setAgency(args.agency)
|
|
111
|
+
.setWac(decimalToProto(args.wac))
|
|
112
|
+
.setWam(args.wam)
|
|
113
|
+
.setPassThroughRate(decimalToProto(args.passThroughRate))
|
|
114
|
+
.setCurrentFactor(decimalToProto(args.currentFactor))
|
|
115
|
+
.setOriginalFaceValue(decimalToProto(args.originalFaceValue))
|
|
116
|
+
.setCurrentUpb(decimalToProto(args.currentUpb))
|
|
117
|
+
.setPsaSpeed(decimalToProto(args.psaSpeed));
|
|
118
|
+
return new SecurityProto()
|
|
119
|
+
.setProductType(ProductTypeProto.MORTGAGE_BACKED)
|
|
120
|
+
.setBondDetails(bond)
|
|
121
|
+
.setMbsExtension(mbs);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export default MortgageBackedSecurity;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import BondSecurity, { BondPricerInputs } from './BondSecurity';
|
|
2
2
|
import { SecurityProto } from '../../../fintekkers/models/security/security_pb';
|
|
3
3
|
import { IndexTypeProto } from '../../../fintekkers/models/security/index/index_type_pb';
|
|
4
|
-
import { LocalDate } from '../utils/date';
|
|
5
4
|
import { Decimal } from 'decimal.js';
|
|
6
5
|
/**
|
|
7
6
|
* TIPS-specific accessors layered on top of BondSecurity. The inflation
|
|
@@ -14,7 +13,7 @@ declare class TIPSBond extends BondSecurity {
|
|
|
14
13
|
/** Base CPI value at issue, used to scale inflation-adjusted principal. */
|
|
15
14
|
getBaseCpi(): Decimal | null;
|
|
16
15
|
/** Reference date for the base CPI fixing. */
|
|
17
|
-
getIndexDate():
|
|
16
|
+
getIndexDate(): Date | null;
|
|
18
17
|
/** Which inflation index drives accruals (CPI_U on US TIPS). */
|
|
19
18
|
getInflationIndexType(): IndexTypeProto;
|
|
20
19
|
/**
|
|
@@ -23,7 +22,7 @@ declare class TIPSBond extends BondSecurity {
|
|
|
23
22
|
*/
|
|
24
23
|
static fromPricerInputs(args: BondPricerInputs & {
|
|
25
24
|
baseCpi: Decimal;
|
|
26
|
-
indexDate:
|
|
25
|
+
indexDate: Date;
|
|
27
26
|
inflationIndexType: IndexTypeProto;
|
|
28
27
|
}): SecurityProto;
|
|
29
28
|
}
|
|
@@ -54,9 +54,7 @@ class TIPSBond extends BondSecurity_1.default {
|
|
|
54
54
|
getIndexDate() {
|
|
55
55
|
const ext = this.getTipsExtension();
|
|
56
56
|
const d = ext ? ext.getIndexDate() : undefined;
|
|
57
|
-
|
|
58
|
-
return null;
|
|
59
|
-
return new date_1.LocalDate(d);
|
|
57
|
+
return (0, date_1.localDateProtoToDate)(d);
|
|
60
58
|
}
|
|
61
59
|
/** Which inflation index drives accruals (CPI_U on US TIPS). */
|
|
62
60
|
getInflationIndexType() {
|
|
@@ -71,7 +69,7 @@ class TIPSBond extends BondSecurity_1.default {
|
|
|
71
69
|
const bond = (0, BondSecurity_1.buildBondDetails)(args);
|
|
72
70
|
const tips = new security_pb_1.TipsExtensionProto()
|
|
73
71
|
.setBaseCpi((0, BondSecurity_1.decimalToProto)(args.baseCpi))
|
|
74
|
-
.setIndexDate((0,
|
|
72
|
+
.setIndexDate((0, date_1.dateToLocalDateProto)(args.indexDate))
|
|
75
73
|
.setInflationIndexType(args.inflationIndexType);
|
|
76
74
|
return new security_pb_1.SecurityProto()
|
|
77
75
|
.setProductType(product_type_pb_1.ProductTypeProto.TIPS)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TIPSBond.js","sourceRoot":"","sources":["TIPSBond.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+
|
|
1
|
+
{"version":3,"file":"TIPSBond.js","sourceRoot":"","sources":["TIPSBond.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+DAIwB;AACxB,iFAAoG;AACpG,yFAAuF;AACvF,2FAAyF;AACzF,wCAA2E;AAC3E,2CAAqC;AAErC;;;;GAIG;AACH,MAAM,QAAS,SAAQ,sBAAY;IACjC,YAAY,KAAoB;QAC9B,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;IAEO,gBAAgB;;QACtB,OAAO,MAAA,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,mCAAI,SAAS,CAAC;IACpD,CAAC;IAED,2EAA2E;IAC3E,UAAU;QACR,MAAM,GAAG,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7C,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACpB,OAAO,IAAI,oBAAO,CAAC,CAAC,CAAC,0BAA0B,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,8CAA8C;IAC9C,YAAY;QACV,MAAM,GAAG,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC/C,OAAO,IAAA,2BAAoB,EAAC,CAAC,CAAC,CAAC;IACjC,CAAC;IAED,gEAAgE;IAChE,qBAAqB;QACnB,MAAM,GAAG,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACpC,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC,8BAAc,CAAC,kBAAkB,CAAC;IAC/E,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAIvB;QACC,MAAM,IAAI,GAAG,IAAA,+BAAgB,EAAC,IAAI,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,IAAI,gCAAkB,EAAE;aAClC,UAAU,CAAC,IAAA,6BAAc,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC;aACxC,YAAY,CAAC,IAAA,2BAAoB,EAAC,IAAI,CAAC,SAAS,CAAC,CAAC;aAClD,qBAAqB,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAClD,OAAO,IAAI,2BAAa,EAAE;aACvB,cAAc,CAAC,kCAAgB,CAAC,IAAI,CAAC;aACrC,cAAc,CAAC,IAAI,CAAC;aACpB,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;CACF;AAED,kBAAe,QAAQ,CAAC"}
|
|
@@ -2,12 +2,11 @@ import BondSecurity, {
|
|
|
2
2
|
BondPricerInputs,
|
|
3
3
|
buildBondDetails,
|
|
4
4
|
decimalToProto,
|
|
5
|
-
localDateToProto,
|
|
6
5
|
} from './BondSecurity';
|
|
7
6
|
import { SecurityProto, TipsExtensionProto } from '../../../fintekkers/models/security/security_pb';
|
|
8
7
|
import { ProductTypeProto } from '../../../fintekkers/models/security/product_type_pb';
|
|
9
8
|
import { IndexTypeProto } from '../../../fintekkers/models/security/index/index_type_pb';
|
|
10
|
-
import {
|
|
9
|
+
import { dateToLocalDateProto, localDateProtoToDate } from '../utils/date';
|
|
11
10
|
import { Decimal } from 'decimal.js';
|
|
12
11
|
|
|
13
12
|
/**
|
|
@@ -33,11 +32,10 @@ class TIPSBond extends BondSecurity {
|
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
/** Reference date for the base CPI fixing. */
|
|
36
|
-
getIndexDate():
|
|
35
|
+
getIndexDate(): Date | null {
|
|
37
36
|
const ext = this.getTipsExtension();
|
|
38
37
|
const d = ext ? ext.getIndexDate() : undefined;
|
|
39
|
-
|
|
40
|
-
return new LocalDate(d);
|
|
38
|
+
return localDateProtoToDate(d);
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
/** Which inflation index drives accruals (CPI_U on US TIPS). */
|
|
@@ -52,13 +50,13 @@ class TIPSBond extends BondSecurity {
|
|
|
52
50
|
*/
|
|
53
51
|
static fromPricerInputs(args: BondPricerInputs & {
|
|
54
52
|
baseCpi: Decimal;
|
|
55
|
-
indexDate:
|
|
53
|
+
indexDate: Date;
|
|
56
54
|
inflationIndexType: IndexTypeProto;
|
|
57
55
|
}): SecurityProto {
|
|
58
56
|
const bond = buildBondDetails(args);
|
|
59
57
|
const tips = new TipsExtensionProto()
|
|
60
58
|
.setBaseCpi(decimalToProto(args.baseCpi))
|
|
61
|
-
.setIndexDate(
|
|
59
|
+
.setIndexDate(dateToLocalDateProto(args.indexDate))
|
|
62
60
|
.setInflationIndexType(args.inflationIndexType);
|
|
63
61
|
return new SecurityProto()
|
|
64
62
|
.setProductType(ProductTypeProto.TIPS)
|