sec-edgar-api 0.2.1 → 0.2.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/build/services/ReportBuilder/FactFiscalCalculator.d.ts +51 -0
- package/build/services/ReportBuilder/FactFiscalCalculator.js +232 -0
- package/build/services/ReportBuilder/FactPeriodResolver.d.ts +48 -0
- package/build/services/ReportBuilder/FactPeriodResolver.js +190 -0
- package/build/services/ReportBuilder/FactRecordBuilder.d.ts +10 -0
- package/build/services/ReportBuilder/FactRecordBuilder.js +71 -0
- package/build/services/ReportBuilder/FactSplitAdjuster.d.ts +46 -0
- package/build/services/ReportBuilder/FactSplitAdjuster.js +203 -0
- package/build/services/ReportBuilder/ReportBuilder.d.ts +40 -0
- package/build/services/ReportBuilder/ReportBuilder.js +186 -0
- package/build/services/ReportBuilder/ReportRawResolvable.d.ts +17 -0
- package/build/services/ReportBuilder/ReportRawResolvable.js +114 -0
- package/build/services/ReportBuilder/index.d.ts +2 -0
- package/build/services/ReportBuilder/index.js +4 -0
- package/build/services/ReportParser/PropertyResolver.d.ts +1 -0
- package/build/services/ReportParser/PropertyResolver.js +1 -0
- package/build/services/ReportParser/ReportParser.d.ts +4 -11
- package/build/services/ReportParser/ReportParser.js +15 -27
- package/build/services/ReportParser/ReportRawParser.d.ts +3 -32
- package/build/services/ReportParser/ReportRawParser.js +6 -146
- package/build/services/ReportParser/ReportWrapper.js +4 -5
- package/build/services/ReportParser/resolvers/index.d.ts +2 -0
- package/build/services/ReportParser/resolvers/index.js +2 -0
- package/build/services/ReportParser/resolvers/resolve-cash-flow-capex.js +4 -3
- package/build/services/ReportParser/resolvers/resolve-cash-flow-operating.js +1 -1
- package/build/services/ReportParser/resolvers/resolve-cash-flow-working-capital-non-cash.js +1 -1
- package/build/services/ReportParser/resolvers/resolve-expense-depreciation.js +1 -1
- package/build/services/ReportParser/resolvers/resolve-fiscal-year-cumulative-properties.js +30 -15
- package/build/services/ReportParser/resolvers/resolve-q4-fiscal-year-matching-properties.js +32 -4
- package/build/services/ReportParser/resolvers/resolve-split-ratio.d.ts +2 -0
- package/build/services/ReportParser/resolvers/resolve-split-ratio.js +37 -0
- package/build/services/SecEdgarApi/SecEdgarApi.d.ts +1 -2
- package/build/types/report-raw.type.d.ts +5 -6
- package/build/types/report-translated.type.d.ts +4 -2
- package/build/util/calculation-map-by-ns.d.ts +6 -0
- package/build/util/calculation-map-by-ns.js +9 -0
- package/build/util/key-translations.js +5 -2
- package/package.json +1 -1
- package/build/services/ReportParser/FactIterator.d.ts +0 -18
- package/build/services/ReportParser/FactIterator.js +0 -35
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
/**
|
|
15
|
+
* Adjust share-based property values for splits. Checks where the split was applied,
|
|
16
|
+
* and adjusts all previously filed share facts accordingly.
|
|
17
|
+
*/
|
|
18
|
+
var FactSplitAdjuster = /** @class */ (function () {
|
|
19
|
+
function FactSplitAdjuster() {
|
|
20
|
+
this.splitKey = 'StockholdersEquityNoteStockSplitConversionRatio1';
|
|
21
|
+
this.splitByFiscalYearAmount = new Map();
|
|
22
|
+
this.factsByYearQuarterByPropertyName = new Map();
|
|
23
|
+
this.factsAnnaulByYearByPropertyName = new Map();
|
|
24
|
+
this.resolvedProperties = new Set();
|
|
25
|
+
this.sortedSplits = null;
|
|
26
|
+
}
|
|
27
|
+
FactSplitAdjuster.prototype.getMap = function (map, propertyName) {
|
|
28
|
+
var _a;
|
|
29
|
+
return (_a = map.get(propertyName)) !== null && _a !== void 0 ? _a : map.set(propertyName, new Map()).get(propertyName);
|
|
30
|
+
};
|
|
31
|
+
FactSplitAdjuster.prototype.add = function (fact) {
|
|
32
|
+
var propertyName = fact.name, year = fact.year, fiscalPeriod = fact.fiscalPeriod, unit = fact.unit, filed = fact.filed, value = fact.value, end = fact.end;
|
|
33
|
+
if (this.isSplitProperty(propertyName)) {
|
|
34
|
+
this.addSplitData({ end: end, filed: filed, fiscalYear: year, value: Number(value) });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (!this.isSplitAdjustableUnit(unit))
|
|
38
|
+
return;
|
|
39
|
+
if (this.resolvedProperties.has(propertyName)) {
|
|
40
|
+
throw new Error("Property ".concat(propertyName, " has already been resolved"));
|
|
41
|
+
}
|
|
42
|
+
var isAnnual = fiscalPeriod === 'FY';
|
|
43
|
+
var map = isAnnual
|
|
44
|
+
? this.getMap(this.factsAnnaulByYearByPropertyName, propertyName)
|
|
45
|
+
: this.getMap(this.factsByYearQuarterByPropertyName, propertyName);
|
|
46
|
+
var key = "".concat(year, "_").concat(fiscalPeriod);
|
|
47
|
+
map.set(key, fact);
|
|
48
|
+
};
|
|
49
|
+
FactSplitAdjuster.prototype.getSplitsAsc = function () {
|
|
50
|
+
if (this.sortedSplits)
|
|
51
|
+
return this.sortedSplits;
|
|
52
|
+
var sortedSplits = Array.from(this.splitByFiscalYearAmount.values()).sort(function (a, b) {
|
|
53
|
+
return a.filed < b.filed ? -1 : 1;
|
|
54
|
+
});
|
|
55
|
+
this.sortedSplits = sortedSplits;
|
|
56
|
+
return sortedSplits;
|
|
57
|
+
};
|
|
58
|
+
FactSplitAdjuster.prototype.isSplitProperty = function (propertyName) {
|
|
59
|
+
return propertyName === this.splitKey;
|
|
60
|
+
};
|
|
61
|
+
FactSplitAdjuster.prototype.addSplitData = function (data) {
|
|
62
|
+
var end = data.end, filed = data.filed, fiscalYear = data.fiscalYear, value = data.value;
|
|
63
|
+
var split = value;
|
|
64
|
+
var key = "".concat(fiscalYear, "-").concat(split);
|
|
65
|
+
var prevSplit = this.splitByFiscalYearAmount.get(key);
|
|
66
|
+
if (!prevSplit) {
|
|
67
|
+
this.splitByFiscalYearAmount.set(key, __assign(__assign({}, data), { firstFiled: filed }));
|
|
68
|
+
this.sortedSplits = null;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
var curEnd = end;
|
|
72
|
+
var curFiled = filed;
|
|
73
|
+
var prevEnd = prevSplit.end;
|
|
74
|
+
var prevFiled = prevSplit.filed;
|
|
75
|
+
var shouldUpdateFactItem = !prevSplit || prevEnd < curEnd || (prevEnd === curEnd && prevFiled > curFiled);
|
|
76
|
+
var shouldUpdateFirstFiled = prevFiled > curFiled;
|
|
77
|
+
if (shouldUpdateFactItem) {
|
|
78
|
+
var curData = this.splitByFiscalYearAmount.get(key);
|
|
79
|
+
curData.end = end;
|
|
80
|
+
curData.filed = filed;
|
|
81
|
+
curData.value = value;
|
|
82
|
+
curData.fiscalYear = fiscalYear;
|
|
83
|
+
this.sortedSplits = null;
|
|
84
|
+
}
|
|
85
|
+
if (shouldUpdateFirstFiled) {
|
|
86
|
+
var curData = this.splitByFiscalYearAmount.get(key);
|
|
87
|
+
curData.firstFiled = curFiled;
|
|
88
|
+
this.sortedSplits = null;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* TODO: Find a more reliable way of checking if the split has already been applied.
|
|
93
|
+
*/
|
|
94
|
+
FactSplitAdjuster.prototype.didApplySplit = function (params) {
|
|
95
|
+
var nextValue = params.nextValue, prevValue = params.prevValue, split = params.split, isShareRatio = params.isShareRatio, value = params.value, filed = params.filed;
|
|
96
|
+
if (filed > split.filed) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
var dateFiled = new Date(filed);
|
|
100
|
+
// TODO: adust by adding a year because sometimes the already adjusted facts are filed within the
|
|
101
|
+
// year before the split. this might be because the split is listed under a different property? Look into this...
|
|
102
|
+
if (dateFiled.setFullYear(dateFiled.getFullYear() + 1) < new Date(split.firstFiled).getTime()) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
var valWithSplit = isShareRatio ? value / split.value : value * split.value;
|
|
106
|
+
// if we still don't know, see if applying the split puts us closer or further from the prev/next quarter value.
|
|
107
|
+
if (prevValue !== null) {
|
|
108
|
+
var difference = Math.abs(prevValue - value);
|
|
109
|
+
var differenceSplit = Math.abs(prevValue - valWithSplit);
|
|
110
|
+
return difference < differenceSplit;
|
|
111
|
+
}
|
|
112
|
+
if (nextValue !== null) {
|
|
113
|
+
var difference = Math.abs(nextValue - value);
|
|
114
|
+
var differenceSplit = Math.abs(nextValue - valWithSplit);
|
|
115
|
+
return difference < differenceSplit;
|
|
116
|
+
}
|
|
117
|
+
return true;
|
|
118
|
+
};
|
|
119
|
+
FactSplitAdjuster.prototype.isSplitAdjustableUnit = function (unit) {
|
|
120
|
+
return unit.toLowerCase().includes('share');
|
|
121
|
+
};
|
|
122
|
+
FactSplitAdjuster.prototype.isShareRatioUnit = function (unit) {
|
|
123
|
+
var unitLower = unit.toLowerCase();
|
|
124
|
+
return unitLower !== 'shares' && unitLower.includes('share'); // ex: USD/shares or USD-per-share
|
|
125
|
+
};
|
|
126
|
+
FactSplitAdjuster.prototype.getSortedFacts = function (propertyName, isAnnual) {
|
|
127
|
+
var _a, _b, _c;
|
|
128
|
+
var bucket = isAnnual ? this.factsAnnaulByYearByPropertyName : this.factsByYearQuarterByPropertyName;
|
|
129
|
+
var facts = Array.from((_b = (_a = bucket.get(propertyName)) === null || _a === void 0 ? void 0 : _a.values()) !== null && _b !== void 0 ? _b : []);
|
|
130
|
+
return (_c = facts.sort(function (a, b) { return (a.filed < b.filed ? -1 : 1); })) !== null && _c !== void 0 ? _c : [];
|
|
131
|
+
};
|
|
132
|
+
FactSplitAdjuster.prototype.resolveProperty = function (propertyName) {
|
|
133
|
+
if (this.resolvedProperties.has(propertyName))
|
|
134
|
+
return;
|
|
135
|
+
var factsAscQuarter = this.getSortedFacts(propertyName, false);
|
|
136
|
+
var factsAscAnnual = this.getSortedFacts(propertyName, true);
|
|
137
|
+
this.adjustValuesForSplits({ facts: factsAscQuarter });
|
|
138
|
+
this.adjustValuesForSplits({ facts: factsAscAnnual });
|
|
139
|
+
this.resolvedProperties.add(propertyName);
|
|
140
|
+
};
|
|
141
|
+
FactSplitAdjuster.prototype.get = function (propertyName, year, fiscalPeriod) {
|
|
142
|
+
var _a;
|
|
143
|
+
this.resolveProperty(propertyName);
|
|
144
|
+
var key = "".concat(year, "_").concat(fiscalPeriod);
|
|
145
|
+
var isAnnual = fiscalPeriod === 'FY';
|
|
146
|
+
var bucket = isAnnual ? this.factsAnnaulByYearByPropertyName : this.factsByYearQuarterByPropertyName;
|
|
147
|
+
var fact = (_a = bucket.get(propertyName)) === null || _a === void 0 ? void 0 : _a.get(key);
|
|
148
|
+
return fact === null || fact === void 0 ? void 0 : fact.value;
|
|
149
|
+
};
|
|
150
|
+
FactSplitAdjuster.prototype.forEach = function (callback) {
|
|
151
|
+
var _this = this;
|
|
152
|
+
this.factsByYearQuarterByPropertyName.forEach(function (factsByYearQuarter, propertyName) {
|
|
153
|
+
_this.resolveProperty(propertyName);
|
|
154
|
+
factsByYearQuarter.forEach(function (fact, key) {
|
|
155
|
+
var _a = key.split('_'), year = _a[0], fiscalPeriod = _a[1];
|
|
156
|
+
callback({ propertyName: propertyName, year: Number(year), fiscalPeriod: fiscalPeriod, value: Number(fact.value) });
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
this.factsAnnaulByYearByPropertyName.forEach(function (factsByYear, propertyName) {
|
|
160
|
+
_this.resolveProperty(propertyName);
|
|
161
|
+
factsByYear.forEach(function (fact, key) {
|
|
162
|
+
var _a = key.split('_'), year = _a[0], fiscalPeriod = _a[1];
|
|
163
|
+
callback({ propertyName: propertyName, year: Number(year), fiscalPeriod: fiscalPeriod, value: Number(fact.value) });
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
FactSplitAdjuster.prototype.adjustValuesForSplits = function (params) {
|
|
168
|
+
var _a, _b, _c, _d;
|
|
169
|
+
var facts = params.facts;
|
|
170
|
+
var splits = this.getSplitsAsc();
|
|
171
|
+
if (facts.length === 0 || splits.length === 0)
|
|
172
|
+
return;
|
|
173
|
+
var isShareRatio = this.isShareRatioUnit(facts[0].unit);
|
|
174
|
+
for (var splitIndex = splits.length - 1; splitIndex >= 0; splitIndex--) {
|
|
175
|
+
var split = splits[splitIndex];
|
|
176
|
+
for (var factIndex = facts.length - 1; factIndex >= 0; factIndex--) {
|
|
177
|
+
var fact = facts[factIndex];
|
|
178
|
+
var value = fact.value, filed = fact.filed;
|
|
179
|
+
var nextValue = (_b = (_a = facts[factIndex + 1]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : null;
|
|
180
|
+
var prevValue = (_d = (_c = facts[factIndex - 1]) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : null;
|
|
181
|
+
var didApplySplit = this.didApplySplit({
|
|
182
|
+
filed: filed,
|
|
183
|
+
isShareRatio: isShareRatio,
|
|
184
|
+
nextValue: nextValue,
|
|
185
|
+
prevValue: prevValue,
|
|
186
|
+
split: split,
|
|
187
|
+
value: value,
|
|
188
|
+
});
|
|
189
|
+
if (didApplySplit || !split.value) {
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (isShareRatio) {
|
|
193
|
+
fact.value /= split.value;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
fact.value *= split.value;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
return FactSplitAdjuster;
|
|
202
|
+
}());
|
|
203
|
+
exports.default = FactSplitAdjuster;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { CompanyFactListData, FiscalPeriod, ReportRaw } from '../../types';
|
|
2
|
+
import { SetReportDatesParams } from './FactFiscalCalculator';
|
|
3
|
+
export interface FactItem {
|
|
4
|
+
cik: number | string;
|
|
5
|
+
end: string;
|
|
6
|
+
filed: string;
|
|
7
|
+
name: string;
|
|
8
|
+
unit: string;
|
|
9
|
+
value: number | string;
|
|
10
|
+
start?: string;
|
|
11
|
+
hasSegments?: boolean;
|
|
12
|
+
accn?: string;
|
|
13
|
+
form?: string;
|
|
14
|
+
fp?: string;
|
|
15
|
+
frame?: string;
|
|
16
|
+
fy?: number;
|
|
17
|
+
/** For XBRL reports only */
|
|
18
|
+
segments?: {
|
|
19
|
+
value: string;
|
|
20
|
+
dimension: string;
|
|
21
|
+
}[];
|
|
22
|
+
uuid?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface FactItemWithFiscals extends FactItem {
|
|
25
|
+
fiscalPeriod: FiscalPeriod;
|
|
26
|
+
year: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Builds ReportRaw objects from facts. also applies splits and adjusts for fiscal periods.
|
|
30
|
+
*/
|
|
31
|
+
export default class ReportBuilder {
|
|
32
|
+
private readonly factRecordBuilder;
|
|
33
|
+
createFacts(companyFacts: CompanyFactListData): {
|
|
34
|
+
facts: FactItem[];
|
|
35
|
+
};
|
|
36
|
+
buildReports(params: {
|
|
37
|
+
facts: FactItem[];
|
|
38
|
+
reportDates?: SetReportDatesParams[];
|
|
39
|
+
}): ReportRaw[];
|
|
40
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var FactFiscalCalculator_1 = require("./FactFiscalCalculator");
|
|
4
|
+
var FactPeriodResolver_1 = require("./FactPeriodResolver");
|
|
5
|
+
var FactRecordBuilder_1 = require("./FactRecordBuilder");
|
|
6
|
+
var FactSplitAdjuster_1 = require("./FactSplitAdjuster");
|
|
7
|
+
/**
|
|
8
|
+
* Builds ReportRaw objects from facts. also applies splits and adjusts for fiscal periods.
|
|
9
|
+
*/
|
|
10
|
+
var ReportBuilder = /** @class */ (function () {
|
|
11
|
+
function ReportBuilder() {
|
|
12
|
+
this.factRecordBuilder = new FactRecordBuilder_1.default();
|
|
13
|
+
}
|
|
14
|
+
ReportBuilder.prototype.createFacts = function (companyFacts) {
|
|
15
|
+
return this.factRecordBuilder.createFacts(companyFacts);
|
|
16
|
+
};
|
|
17
|
+
ReportBuilder.prototype.buildReports = function (params) {
|
|
18
|
+
var _a, _b, _c, _d, _e;
|
|
19
|
+
var facts = params.facts, reportDates = params.reportDates;
|
|
20
|
+
if (facts.length === 0) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
var accessionByYearQuarter = new Map();
|
|
24
|
+
reportDates === null || reportDates === void 0 ? void 0 : reportDates.forEach(function (params) {
|
|
25
|
+
var year = params.year, quarter = params.quarter, accn = params.accn;
|
|
26
|
+
if (accn)
|
|
27
|
+
accessionByYearQuarter.set("".concat(year, "_").concat(quarter), accn);
|
|
28
|
+
});
|
|
29
|
+
var reportsCik = Number(facts[0].cik);
|
|
30
|
+
var factFiscalCalculator = new FactFiscalCalculator_1.default();
|
|
31
|
+
var factPeriodResolver = new FactPeriodResolver_1.default({ cik: reportsCik });
|
|
32
|
+
var factSplitAdjuster = new FactSplitAdjuster_1.default();
|
|
33
|
+
facts.forEach(function (fact) { return factFiscalCalculator.add(fact); });
|
|
34
|
+
reportDates === null || reportDates === void 0 ? void 0 : reportDates.forEach(function (params) { return factFiscalCalculator.setReportDates(params); });
|
|
35
|
+
var unitByPropertyName = new Map();
|
|
36
|
+
var splitDateDataByKey = new Map();
|
|
37
|
+
var minYear = Infinity;
|
|
38
|
+
var maxYear = -Infinity;
|
|
39
|
+
var countByAccnByYearQuarter = new Map();
|
|
40
|
+
var filedByPropertyYearQuarterValue = new Map();
|
|
41
|
+
for (var _i = 0, facts_1 = facts; _i < facts_1.length; _i++) {
|
|
42
|
+
var fact = facts_1[_i];
|
|
43
|
+
var end = fact.end, name_1 = fact.name, unit = fact.unit, segments = fact.segments, start = fact.start, value = fact.value, cik = fact.cik, form = fact.form, filed = fact.filed, accn = fact.accn;
|
|
44
|
+
if (Number(fact.cik) !== Number(reportsCik)) {
|
|
45
|
+
throw new Error("All facts must have the same cik ".concat(reportsCik, " !== ").concat(Number(cik)));
|
|
46
|
+
}
|
|
47
|
+
var segmentValue = segments === null || segments === void 0 ? void 0 : segments.map(function (seg) { return "".concat(seg.dimension, "_").concat(seg.value); }).join('&');
|
|
48
|
+
var propertyName = (_a = name_1.split(':').pop()) !== null && _a !== void 0 ? _a : '';
|
|
49
|
+
var propertyNameWithSegment = propertyName + (segmentValue ? "_".concat(segmentValue) : '');
|
|
50
|
+
var _f = factFiscalCalculator.getFiscalYearQuarter({ dateStr: end }), quarter = _f.quarter, year = _f.year;
|
|
51
|
+
if (year < minYear)
|
|
52
|
+
minYear = year;
|
|
53
|
+
if (year > maxYear)
|
|
54
|
+
maxYear = year;
|
|
55
|
+
var splitKey = "".concat(year, "_").concat(value);
|
|
56
|
+
var factFiledKey = "".concat(year, "_").concat(quarter, "_").concat(propertyNameWithSegment, "_").concat(value);
|
|
57
|
+
var isSplit = factSplitAdjuster.isSplitProperty(propertyName);
|
|
58
|
+
unitByPropertyName.set(propertyNameWithSegment, unit);
|
|
59
|
+
filedByPropertyYearQuarterValue.set(factFiledKey, filed);
|
|
60
|
+
if (isSplit && new Date(end) > new Date((_c = (_b = splitDateDataByKey.get(splitKey)) === null || _b === void 0 ? void 0 : _b.end) !== null && _c !== void 0 ? _c : 0)) {
|
|
61
|
+
splitDateDataByKey.set(splitKey, { end: end, quarter: quarter });
|
|
62
|
+
}
|
|
63
|
+
var accnKey = "".concat(year, "_").concat(quarter);
|
|
64
|
+
var accnGiven = accessionByYearQuarter.get(accnKey);
|
|
65
|
+
var filedDistance = Math.abs(new Date(filed).getTime() - new Date(end !== null && end !== void 0 ? end : 0).getTime()) / 86400000;
|
|
66
|
+
var isFiledRecent = filedDistance < 60;
|
|
67
|
+
if (!accnGiven && isFiledRecent && accn && (!form || form === '10-K' || form === '10-Q')) {
|
|
68
|
+
var countByAccn = (_d = countByAccnByYearQuarter.get(accnKey)) !== null && _d !== void 0 ? _d : new Map();
|
|
69
|
+
countByAccn.set(accn, ((_e = countByAccn.get(accn)) !== null && _e !== void 0 ? _e : 0) + 1);
|
|
70
|
+
countByAccnByYearQuarter.set(accnKey, countByAccn);
|
|
71
|
+
}
|
|
72
|
+
factPeriodResolver.add({
|
|
73
|
+
year: year,
|
|
74
|
+
start: start,
|
|
75
|
+
end: end,
|
|
76
|
+
name: propertyNameWithSegment,
|
|
77
|
+
quarter: quarter,
|
|
78
|
+
value: value,
|
|
79
|
+
filed: filed,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
countByAccnByYearQuarter.forEach(function (countByAccn, yearQuarter) {
|
|
83
|
+
if (accessionByYearQuarter.has(yearQuarter))
|
|
84
|
+
return;
|
|
85
|
+
var maxCount = 0;
|
|
86
|
+
var accessionNumber = '';
|
|
87
|
+
countByAccn.forEach(function (count, accn) {
|
|
88
|
+
if (count > maxCount) {
|
|
89
|
+
maxCount = count;
|
|
90
|
+
accessionNumber = accn;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
accessionByYearQuarter.set(yearQuarter, accessionNumber);
|
|
94
|
+
});
|
|
95
|
+
minYear = Number.isFinite(minYear) ? minYear : new Date().getFullYear();
|
|
96
|
+
maxYear = Number.isFinite(maxYear) ? maxYear : new Date().getFullYear();
|
|
97
|
+
var reportsByKey = new Map();
|
|
98
|
+
// resolves quarterly and annual properties and creates reports
|
|
99
|
+
factPeriodResolver.forEach(function (data) {
|
|
100
|
+
var _a, _b;
|
|
101
|
+
var fiscalPeriod = data.fiscalPeriod, propertyName = data.propertyName, value = data.value, year = data.year;
|
|
102
|
+
var key = "".concat(year, "_").concat(fiscalPeriod);
|
|
103
|
+
var quarter = fiscalPeriod === 'FY' ? 4 : Number(fiscalPeriod[1]);
|
|
104
|
+
var dates = factFiscalCalculator.getDatesByYearQuarter({ quarter: quarter, year: year });
|
|
105
|
+
var _c = dates !== null && dates !== void 0 ? dates : { filed: '', end: '' }, filed = _c.filed, end = _c.end;
|
|
106
|
+
var accessionNumber = accessionByYearQuarter.get("".concat(year, "_").concat(quarter));
|
|
107
|
+
var accessionNoHyphen = accessionNumber === null || accessionNumber === void 0 ? void 0 : accessionNumber.replace(/-/g, '');
|
|
108
|
+
var url = accessionNumber
|
|
109
|
+
? "https://www.sec.gov/Archives/edgar/data/".concat(reportsCik, "/").concat(accessionNoHyphen, "/").concat(accessionNumber, ".txt")
|
|
110
|
+
: null;
|
|
111
|
+
if (!reportsByKey.has(key)) {
|
|
112
|
+
reportsByKey.set(key, {
|
|
113
|
+
cik: reportsCik,
|
|
114
|
+
url: url,
|
|
115
|
+
dateFiled: filed,
|
|
116
|
+
dateReport: end,
|
|
117
|
+
fiscalPeriod: fiscalPeriod,
|
|
118
|
+
fiscalYear: year,
|
|
119
|
+
splitDate: null,
|
|
120
|
+
splitRatio: null,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
var filedKey = "".concat(year, "_").concat(quarter, "_").concat(propertyName, "_").concat(value);
|
|
124
|
+
// add facts to adjust for splits
|
|
125
|
+
factSplitAdjuster.add({
|
|
126
|
+
end: end,
|
|
127
|
+
// use the original fact filed date instead of the report filed date to know if the fact has been split.
|
|
128
|
+
filed: (_a = filedByPropertyYearQuarterValue.get(filedKey)) !== null && _a !== void 0 ? _a : filed,
|
|
129
|
+
fiscalPeriod: fiscalPeriod,
|
|
130
|
+
name: propertyName,
|
|
131
|
+
unit: (_b = unitByPropertyName.get(propertyName)) !== null && _b !== void 0 ? _b : '',
|
|
132
|
+
year: year,
|
|
133
|
+
value: Number(value),
|
|
134
|
+
accn: accessionNumber !== null && accessionNumber !== void 0 ? accessionNumber : '',
|
|
135
|
+
});
|
|
136
|
+
var report = reportsByKey.get(key);
|
|
137
|
+
report[propertyName] = value;
|
|
138
|
+
});
|
|
139
|
+
// iterate through facts adjustable for splits and assign values to reports
|
|
140
|
+
factSplitAdjuster.forEach(function (data) {
|
|
141
|
+
var year = data.year, fiscalPeriod = data.fiscalPeriod, propertyName = data.propertyName, value = data.value;
|
|
142
|
+
var key = "".concat(year, "_").concat(fiscalPeriod);
|
|
143
|
+
var report = reportsByKey.get(key);
|
|
144
|
+
if (!report)
|
|
145
|
+
return;
|
|
146
|
+
report[propertyName] = Math.round(value * 10000) / 10000;
|
|
147
|
+
});
|
|
148
|
+
// add split dates and values to reports
|
|
149
|
+
factSplitAdjuster.getSplitsAsc().forEach(function (split) {
|
|
150
|
+
var _a, _b, _c, _d;
|
|
151
|
+
var _e = factFiscalCalculator.getFiscalYearQuarter({ dateStr: split.end }), quarter = _e.quarter, year = _e.year;
|
|
152
|
+
var keySplit = "".concat(year, "_").concat(split.value);
|
|
153
|
+
var splitDateData = (_a = splitDateDataByKey.get(keySplit)) !== null && _a !== void 0 ? _a : { end: null, quarter: null };
|
|
154
|
+
var splitDate = (_b = splitDateData.end) !== null && _b !== void 0 ? _b : split.filed;
|
|
155
|
+
var splitQuarter = (_c = splitDateData.quarter) !== null && _c !== void 0 ? _c : quarter;
|
|
156
|
+
var fiscalPeriod = "Q".concat(splitQuarter);
|
|
157
|
+
var keyReport = "".concat(year, "_").concat(fiscalPeriod);
|
|
158
|
+
var report = reportsByKey.get(keyReport);
|
|
159
|
+
var reportAnnual = splitQuarter === 4 ? (_d = reportsByKey.get("".concat(year, "_FY"))) !== null && _d !== void 0 ? _d : null : null;
|
|
160
|
+
if (report) {
|
|
161
|
+
report.splitRatio = split.value;
|
|
162
|
+
report.splitDate = splitDate;
|
|
163
|
+
}
|
|
164
|
+
// also assign to annual for Q4
|
|
165
|
+
if (reportAnnual) {
|
|
166
|
+
reportAnnual.splitRatio = split.value;
|
|
167
|
+
reportAnnual.splitDate = splitDate;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
// sort reports ASC by year and quarter
|
|
171
|
+
var reportsSorted = [];
|
|
172
|
+
for (var year = minYear; year <= maxYear; year++) {
|
|
173
|
+
for (var i = 0; i < 5; i++) {
|
|
174
|
+
var fiscalPeriod = i === 4 ? 'FY' : "Q".concat(i + 1);
|
|
175
|
+
var key = "".concat(year, "_").concat(fiscalPeriod);
|
|
176
|
+
var report = reportsByKey.get(key);
|
|
177
|
+
if (report && report.dateReport) {
|
|
178
|
+
reportsSorted.push(report);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return reportsSorted;
|
|
183
|
+
};
|
|
184
|
+
return ReportBuilder;
|
|
185
|
+
}());
|
|
186
|
+
exports.default = ReportBuilder;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ReportRaw } from '../../types';
|
|
2
|
+
export type TemplateCode = 'I' | 'T' | 'B' | 'M' | 'N' | 'U';
|
|
3
|
+
export default class ReportRawResolvable {
|
|
4
|
+
readonly report: ReportRaw;
|
|
5
|
+
private readonly emptyKeys;
|
|
6
|
+
private readonly addedProps;
|
|
7
|
+
private readonly calcMap;
|
|
8
|
+
private readonly templateCode;
|
|
9
|
+
private readonly keyStack;
|
|
10
|
+
constructor(report: ReportRaw, templateCode?: TemplateCode | null, calcMap?: Record<string, Record<string, string[]>>);
|
|
11
|
+
get(key: string): string | number | boolean | undefined;
|
|
12
|
+
getNumber(key: string): number;
|
|
13
|
+
isAdded(key: string): boolean;
|
|
14
|
+
private getChildKeysArr;
|
|
15
|
+
private calculateNumericKey;
|
|
16
|
+
toJSON(): ReportRaw;
|
|
17
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var calculation_map_by_ns_1 = require("../../util/calculation-map-by-ns");
|
|
4
|
+
var ReportRawResolvable = /** @class */ (function () {
|
|
5
|
+
function ReportRawResolvable(report, templateCode, calcMap) {
|
|
6
|
+
if (templateCode === void 0) { templateCode = null; }
|
|
7
|
+
if (calcMap === void 0) { calcMap = calculation_map_by_ns_1.calculationMapByNs; }
|
|
8
|
+
this.emptyKeys = new Set();
|
|
9
|
+
this.addedProps = new Set();
|
|
10
|
+
this.keyStack = new Set();
|
|
11
|
+
this.templateCode = templateCode !== null && templateCode !== void 0 ? templateCode : 'N';
|
|
12
|
+
this.report = report;
|
|
13
|
+
this.calcMap = calcMap;
|
|
14
|
+
}
|
|
15
|
+
ReportRawResolvable.prototype.get = function (key) {
|
|
16
|
+
var _a;
|
|
17
|
+
return (_a = this.report[key]) !== null && _a !== void 0 ? _a : this.calculateNumericKey(key, key);
|
|
18
|
+
};
|
|
19
|
+
ReportRawResolvable.prototype.getNumber = function (key) {
|
|
20
|
+
return Number(this.get(key)) || 0;
|
|
21
|
+
};
|
|
22
|
+
ReportRawResolvable.prototype.isAdded = function (key) {
|
|
23
|
+
return this.addedProps.has(key);
|
|
24
|
+
};
|
|
25
|
+
ReportRawResolvable.prototype.getChildKeysArr = function (key) {
|
|
26
|
+
var calcsByRole = this.calcMap[key];
|
|
27
|
+
if (calcsByRole === undefined) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
if (calcsByRole._) {
|
|
31
|
+
return [calcsByRole._];
|
|
32
|
+
}
|
|
33
|
+
var preferredKeys = [];
|
|
34
|
+
switch (this.templateCode) {
|
|
35
|
+
case 'I':
|
|
36
|
+
preferredKeys = [
|
|
37
|
+
'StatementOfCashFlowsIndirectInvestmentBasedOperations',
|
|
38
|
+
'StatementOfFinancialPositionUnclassified-InvestmentBasedOperations',
|
|
39
|
+
'StatementOfCashFlowsIndirectDepositBasedOperations',
|
|
40
|
+
'StatementOfFinancialPositionUnclassified-DepositBasedOperationsFirstAlternate',
|
|
41
|
+
'StatementOfFinancialPositionUnclassified-DepositBasedOperations',
|
|
42
|
+
];
|
|
43
|
+
break;
|
|
44
|
+
case 'B':
|
|
45
|
+
preferredKeys = [
|
|
46
|
+
'StatementOfFinancialPositionUnclassified-DepositBasedOperationsFirstAlternate',
|
|
47
|
+
'StatementOfFinancialPositionUnclassified-DepositBasedOperations',
|
|
48
|
+
];
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
var k = preferredKeys.find(function (k) { return calcsByRole[k]; });
|
|
52
|
+
if (!k) {
|
|
53
|
+
k = Object.keys(calcsByRole)[0];
|
|
54
|
+
}
|
|
55
|
+
return Object.keys(calcsByRole)
|
|
56
|
+
.sort(function (a, b) {
|
|
57
|
+
var indexA = preferredKeys.indexOf(a);
|
|
58
|
+
var indexB = preferredKeys.indexOf(b);
|
|
59
|
+
if (indexB === -1)
|
|
60
|
+
return -1;
|
|
61
|
+
if (indexA === -1)
|
|
62
|
+
return 1;
|
|
63
|
+
return indexA - indexB;
|
|
64
|
+
})
|
|
65
|
+
.map(function (k) { return calcsByRole[k]; });
|
|
66
|
+
};
|
|
67
|
+
ReportRawResolvable.prototype.calculateNumericKey = function (key, topLevelKey) {
|
|
68
|
+
var _a;
|
|
69
|
+
if (this.keyStack.has(key)) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
this.keyStack.add(key);
|
|
73
|
+
if (this.emptyKeys.has(key)) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
var childKeysArr = this.getChildKeysArr(key);
|
|
77
|
+
if (childKeysArr.length === 0) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
var didAdd = false;
|
|
81
|
+
var finalSum = 0;
|
|
82
|
+
for (var _i = 0, childKeysArr_1 = childKeysArr; _i < childKeysArr_1.length; _i++) {
|
|
83
|
+
var childKeys = childKeysArr_1[_i];
|
|
84
|
+
var sum = 0;
|
|
85
|
+
for (var _b = 0, childKeys_1 = childKeys; _b < childKeys_1.length; _b++) {
|
|
86
|
+
var k = childKeys_1[_b];
|
|
87
|
+
var _c = k.split('|'), childKey = _c[0], weightStr = _c[1];
|
|
88
|
+
var value = (_a = this.report[childKey]) !== null && _a !== void 0 ? _a : this.calculateNumericKey(childKey, topLevelKey);
|
|
89
|
+
if (typeof value !== 'number') {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
didAdd = true;
|
|
93
|
+
sum += value * Number(weightStr);
|
|
94
|
+
}
|
|
95
|
+
if (sum === 0) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
finalSum = sum;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
if (!didAdd) {
|
|
102
|
+
this.emptyKeys.add(key);
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
this.report[key] = finalSum;
|
|
106
|
+
this.addedProps.add(key);
|
|
107
|
+
return finalSum;
|
|
108
|
+
};
|
|
109
|
+
ReportRawResolvable.prototype.toJSON = function () {
|
|
110
|
+
return this.report;
|
|
111
|
+
};
|
|
112
|
+
return ReportRawResolvable;
|
|
113
|
+
}());
|
|
114
|
+
exports.default = ReportRawResolvable;
|
|
@@ -18,6 +18,7 @@ export default class PropertyResolver {
|
|
|
18
18
|
resolveLiabilityCurrent: typeof import("./resolvers/resolve-liability-current").resolveLiabilityCurrent;
|
|
19
19
|
resolveQ4FiscalYearMatchingProperties: typeof import("./resolvers/resolve-q4-fiscal-year-matching-properties").resolveQ4FiscalYearMatchingProperties;
|
|
20
20
|
resolveCashFlowWorkingCapitalNonCash: typeof import("./resolvers/resolve-cash-flow-working-capital-non-cash").resolveCashFlowWorkingCapitalNonCash;
|
|
21
|
+
resolveSplitRatio: typeof import("./resolvers/resolve-split-ratio").resolveSplitRatio;
|
|
21
22
|
};
|
|
22
23
|
});
|
|
23
24
|
getDefaultResolvers(): typeof resolvers;
|
|
@@ -37,6 +37,7 @@ var PropertyResolver = /** @class */ (function () {
|
|
|
37
37
|
_this.resolvers.resolveCashFlowOperating(report);
|
|
38
38
|
_this.resolvers.resolveCashFlowCapex(report);
|
|
39
39
|
_this.resolvers.resolveCashFlowFree(report);
|
|
40
|
+
_this.resolvers.resolveSplitRatio(report);
|
|
40
41
|
});
|
|
41
42
|
};
|
|
42
43
|
return PropertyResolver;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { CompanyFactListData, ReportRaw, ReportTranslated } from '../../types';
|
|
2
|
-
import { IterateFactsCallbackData } from './FactIterator';
|
|
3
2
|
import PropertyResolver from './PropertyResolver';
|
|
4
|
-
import ReportRawParser
|
|
3
|
+
import ReportRawParser from './ReportRawParser';
|
|
5
4
|
import ReportWrapper from './ReportWrapper';
|
|
6
5
|
interface ReportParserArgs {
|
|
7
6
|
reportRawParser?: ReportRawParser;
|
|
@@ -24,7 +23,7 @@ export default class ReportParser {
|
|
|
24
23
|
*
|
|
25
24
|
* @param companyFactListData This is the json file contents of CIK[number].json file from the SEC website. You can find these using their API or by downloading the companyfacts.zip file: https://www.sec.gov/edgar/sec-api-documentation
|
|
26
25
|
*/
|
|
27
|
-
parseReports(companyFactListData:
|
|
26
|
+
parseReports(companyFactListData: CompanyFactListData, usePropertyResolver?: boolean): ReportWrapper[];
|
|
28
27
|
/**
|
|
29
28
|
* Same as parseReports but accepts ReportRaw[] instead of CompanyFactListData
|
|
30
29
|
*/
|
|
@@ -34,17 +33,11 @@ export default class ReportParser {
|
|
|
34
33
|
*
|
|
35
34
|
* @see https://www.sec.gov/edgar/sec-api-documentation
|
|
36
35
|
*/
|
|
37
|
-
parseReportsRaw(companyFactListData:
|
|
36
|
+
parseReportsRaw(companyFactListData: CompanyFactListData): ReportRaw[];
|
|
38
37
|
/**
|
|
39
38
|
* parseReportsRaw but removes meta data from the report
|
|
40
39
|
*/
|
|
41
|
-
parseReportsRawNoMeta(companyFactListData:
|
|
42
|
-
/**
|
|
43
|
-
* Avoids deep nesting logic while iteratating through company facts
|
|
44
|
-
*
|
|
45
|
-
* @param callback called on each company fact.
|
|
46
|
-
*/
|
|
47
|
-
iterateCompanyFacts(companyFactListData: Pick<CompanyFactListData, 'facts'>, callback: (data: IterateFactsCallbackData) => void): void;
|
|
40
|
+
parseReportsRawNoMeta(companyFactListData: CompanyFactListData): Record<string, number>[];
|
|
48
41
|
/**
|
|
49
42
|
* Translate ReportRaw to ReportTranslated by default, but can be used to translate to any object using both the callback and keyTranslator
|
|
50
43
|
*
|