sec-edgar-api
Version:
Fetch and parse SEC earnings reports and other filings. Useful for financial analysis.
210 lines (209 loc) • 13 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildReportTrees = void 0;
function hrefToKey(href) {
var fragment = href.split('#').pop() || '';
return fragment.replace('_', ':');
}
function getLabelTypeByHref(linkbase) {
var _a, _b, _c, _d;
var labelLink = (_a = linkbase === null || linkbase === void 0 ? void 0 : linkbase.labelLink) === null || _a === void 0 ? void 0 : _a[0];
var labelLocByHref = new Map((_b = labelLink === null || labelLink === void 0 ? void 0 : labelLink.loc) === null || _b === void 0 ? void 0 : _b.map(function (l) { return [l.href, l]; }));
var labelArcByFrom = new Map((_c = labelLink === null || labelLink === void 0 ? void 0 : labelLink.labelArc) === null || _c === void 0 ? void 0 : _c.map(function (l) { return [l.from, l]; }));
var labelByTypeByLabelId = new Map();
(_d = labelLink === null || labelLink === void 0 ? void 0 : labelLink.label) === null || _d === void 0 ? void 0 : _d.forEach(function (l) {
var _a;
var bucket = (_a = labelByTypeByLabelId.get(l.label)) !== null && _a !== void 0 ? _a : labelByTypeByLabelId.set(l.label, {}).get(l.label);
bucket[l.type.substring(l.type.lastIndexOf('/') + 1)] = l.text;
});
var labelByTypeByHref = new Map();
labelLocByHref.forEach(function (locator, href) {
var _a, _b, _c;
labelByTypeByHref.set(href, (_c = labelByTypeByLabelId.get((_b = (_a = labelArcByFrom.get(locator.label)) === null || _a === void 0 ? void 0 : _a.to) !== null && _b !== void 0 ? _b : '')) !== null && _c !== void 0 ? _c : {});
});
return labelByTypeByHref;
}
function getBestLabel(params) {
var _a;
var href = params.href, labelByHref = params.labelByHref, preferredLabel = params.preferredLabel;
var bucket = labelByHref.get(href);
if (!bucket)
return null;
// try getting preferred label
var preferredLabelType = preferredLabel === null || preferredLabel === void 0 ? void 0 : preferredLabel.substring((preferredLabel === null || preferredLabel === void 0 ? void 0 : preferredLabel.lastIndexOf('/')) + 1);
if (preferredLabelType && bucket[preferredLabelType])
return bucket[preferredLabelType];
// if not provided, choose first of these.
for (var _i = 0, _b = ['verboseLabel', 'terseLabel', 'label', 'periodEndLabel']; _i < _b.length; _i++) {
var type = _b[_i];
if (bucket[type])
return bucket[type];
}
// return whatever is left
return (_a = Object.values(bucket)[0]) !== null && _a !== void 0 ? _a : null;
}
function getPeriodFacts(params) {
var _a;
var factsByConcept = params.factsByConcept, conceptKey = params.conceptKey, isPeriodStart = params.isPeriodStart;
var facts = (_a = factsByConcept.get(conceptKey)) !== null && _a !== void 0 ? _a : [];
var primaryFacts = facts.filter(function (f) { return f.isCurrentPeriod; });
if (!isPeriodStart || primaryFacts.length === 0)
return primaryFacts;
var primaryFact = primaryFacts[0];
var maxEnd = facts.reduce(function (max, f) { return (f.end > max && f.end < primaryFact.end ? f.end : max); }, '0000-00-00');
return facts.filter(function (f) { return !f.isCurrentPeriod && f.end === maxEnd; });
}
function extractMemberFacts(facts, memberInclusionRule, allowedMembers) {
if (memberInclusionRule === 'never')
return [];
var allMembers = facts
.filter(function (f) { var _a, _b; return ((_b = (_a = f.segments) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0; })
.map(function (f) { return ({ value: f.value, segments: f.segments }); });
if (memberInclusionRule === 'always')
return allMembers;
return allMembers.filter(function (m) {
return m.segments.every(function (s) { return (allowedMembers === null || allowedMembers === void 0 ? void 0 : allowedMembers.has(s.value)) && (allowedMembers === null || allowedMembers === void 0 ? void 0 : allowedMembers.has(s.dimension)); });
});
}
function extractPrimaryFact(facts) {
var _a;
return (_a = facts.find(function (f) { var _a, _b; return !((_b = (_a = f.segments) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0); })) !== null && _a !== void 0 ? _a : null;
}
function buildTemplateHierarchyFlat(params) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
var arcs = params.arcs, labelByHref = params.labelByHref, locByLabel = params.locByLabel, factsByConcept = params.factsByConcept, allowedMembers = params.allowedMembers, _o = params.memberInclusionRule, memberInclusionRule = _o === void 0 ? 'inReportsWherePresent' : _o;
var itemsById = new Map();
for (var _i = 0, arcs_1 = arcs; _i < arcs_1.length; _i++) {
var arc = arcs_1[_i];
var hrefFrom = (_b = (_a = locByLabel.get(arc.from)) === null || _a === void 0 ? void 0 : _a.href) !== null && _b !== void 0 ? _b : '';
var hrefTo = (_d = (_c = locByLabel.get(arc.to)) === null || _c === void 0 ? void 0 : _c.href) !== null && _d !== void 0 ? _d : '';
var keyFrom = hrefToKey(hrefFrom);
var keyTo = hrefToKey(hrefTo);
var isPeriodStart = (_f = (_e = arc.preferredLabel) === null || _e === void 0 ? void 0 : _e.endsWith('periodStartLabel')) !== null && _f !== void 0 ? _f : false;
if (!itemsById.has(arc.from)) {
var periodFactsFrom = getPeriodFacts({ conceptKey: keyFrom, factsByConcept: factsByConcept, isPeriodStart: isPeriodStart });
var membersFrom = extractMemberFacts(periodFactsFrom, memberInclusionRule, allowedMembers);
var primaryFactFrom = extractPrimaryFact(periodFactsFrom);
itemsById.set(arc.from, {
id: arc.from,
parentId: null,
key: keyFrom,
parentKey: null,
weight: 1,
order: 0,
label: (_g = getBestLabel({ href: hrefFrom, labelByHref: labelByHref, preferredLabel: arc.preferredLabel })) !== null && _g !== void 0 ? _g : keyFrom,
isPeriodStart: isPeriodStart,
period: (primaryFactFrom === null || primaryFactFrom === void 0 ? void 0 : primaryFactFrom.period) || 0,
value: (_h = primaryFactFrom === null || primaryFactFrom === void 0 ? void 0 : primaryFactFrom.value) !== null && _h !== void 0 ? _h : null,
unit: (_j = primaryFactFrom === null || primaryFactFrom === void 0 ? void 0 : primaryFactFrom.unit) !== null && _j !== void 0 ? _j : '',
members: membersFrom,
children: [],
});
}
var periodFactsTo = getPeriodFacts({ conceptKey: keyTo, factsByConcept: factsByConcept, isPeriodStart: isPeriodStart });
var membersTo = extractMemberFacts(periodFactsTo, memberInclusionRule, allowedMembers);
var primaryFactTo = extractPrimaryFact(periodFactsTo);
var hierarchyTo = {
id: arc.to,
parentId: arc.from,
key: keyTo,
parentKey: arc.from ? hrefToKey(hrefFrom) : null,
weight: arc.weight || 1,
order: arc.order || 0,
label: (_k = getBestLabel({ href: hrefTo, labelByHref: labelByHref, preferredLabel: arc.preferredLabel })) !== null && _k !== void 0 ? _k : keyTo,
isPeriodStart: isPeriodStart,
period: (primaryFactTo === null || primaryFactTo === void 0 ? void 0 : primaryFactTo.period) || 0,
value: (_l = primaryFactTo === null || primaryFactTo === void 0 ? void 0 : primaryFactTo.value) !== null && _l !== void 0 ? _l : null,
unit: (_m = primaryFactTo === null || primaryFactTo === void 0 ? void 0 : primaryFactTo.unit) !== null && _m !== void 0 ? _m : '',
members: membersTo,
children: [],
};
if (!itemsById.has(arc.to)) {
itemsById.set(arc.to, hierarchyTo);
}
else {
Object.assign(itemsById.get(arc.to), hierarchyTo);
}
itemsById.get(arc.from).children.push(itemsById.get(arc.to));
}
return itemsById;
}
function hierarchyToTree(itemsById) {
itemsById.forEach(function (item) {
var _a, _b;
if (item.parentId) {
itemsById.delete(item.id);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var itemUntyped = item;
delete itemUntyped.id;
delete itemUntyped.parentId;
delete itemUntyped.parentKey;
delete itemUntyped.order;
if (((_a = itemUntyped.children) === null || _a === void 0 ? void 0 : _a.length) === 0)
delete itemUntyped.children;
if (((_b = itemUntyped.members) === null || _b === void 0 ? void 0 : _b.length) === 0)
delete itemUntyped.members;
});
return Array.from(itemsById.values());
}
function buildReportTrees(params) {
var _a, _b, _c, _d, _e, _f, _g;
var xbrlJson = params.xbrlJson, _h = params.memberInclusionRule, memberInclusionRule = _h === void 0 ? 'inReportsWherePresent' : _h;
var filingSummary = xbrlJson.filingSummary;
if (!filingSummary)
return [];
var labelByHref = getLabelTypeByHref((_a = xbrlJson.linkbaseLabel) === null || _a === void 0 ? void 0 : _a.xbrl);
var factsByConcept = new Map();
xbrlJson.facts.forEach(function (fact) {
var _a;
var bucket = (_a = factsByConcept.get(fact.name)) !== null && _a !== void 0 ? _a : factsByConcept.set(fact.name, []).get(fact.name);
bucket.push(fact);
});
var calculationLinks = (_d = (_c = (_b = xbrlJson.linkbaseCalculation) === null || _b === void 0 ? void 0 : _b.xbrl) === null || _c === void 0 ? void 0 : _c.calculationLink) !== null && _d !== void 0 ? _d : [];
var presentationLinks = (_g = (_f = (_e = xbrlJson.linkbasePresentation) === null || _e === void 0 ? void 0 : _e.xbrl) === null || _f === void 0 ? void 0 : _f.presentationLink) !== null && _g !== void 0 ? _g : [];
// Iterate through the xbrl reports and build tree structures
var reports = filingSummary.reports.map(function (report) {
var _a, _b, _c, _d, _e;
var calculationLink = calculationLinks.find(function (link) { return link.role === report.role; });
var presentationLink = presentationLinks.find(function (link) { return link.role === report.role; });
var locatorByLabelCalc = new Map((_b = (_a = calculationLink === null || calculationLink === void 0 ? void 0 : calculationLink.loc) === null || _a === void 0 ? void 0 : _a.map(function (l) { return [l.label, l]; })) !== null && _b !== void 0 ? _b : []);
var locatorByLabelPres = new Map((_d = (_c = presentationLink === null || presentationLink === void 0 ? void 0 : presentationLink.loc) === null || _c === void 0 ? void 0 : _c.map(function (l) { return [l.label, l]; })) !== null && _d !== void 0 ? _d : []);
var allowedMembers = new Set();
(_e = presentationLink === null || presentationLink === void 0 ? void 0 : presentationLink.presentationArc) === null || _e === void 0 ? void 0 : _e.forEach(function (arc) {
var _a, _b, _c, _d;
allowedMembers.add(hrefToKey((_b = (_a = locatorByLabelPres.get(arc.to)) === null || _a === void 0 ? void 0 : _a.href) !== null && _b !== void 0 ? _b : ''));
allowedMembers.add(hrefToKey((_d = (_c = locatorByLabelPres.get(arc.from)) === null || _c === void 0 ? void 0 : _c.href) !== null && _d !== void 0 ? _d : ''));
});
var hierarchyCalc = buildTemplateHierarchyFlat({
arcs: (calculationLink === null || calculationLink === void 0 ? void 0 : calculationLink.calculationArc) || [],
labelByHref: labelByHref,
locByLabel: locatorByLabelCalc,
factsByConcept: factsByConcept,
allowedMembers: allowedMembers,
memberInclusionRule: memberInclusionRule,
});
var hierarchyPres = buildTemplateHierarchyFlat({
arcs: (presentationLink === null || presentationLink === void 0 ? void 0 : presentationLink.presentationArc) || [],
labelByHref: labelByHref,
locByLabel: locatorByLabelPres,
factsByConcept: factsByConcept,
allowedMembers: allowedMembers,
memberInclusionRule: memberInclusionRule,
});
return __assign(__assign({}, report), { calculationTree: hierarchyToTree(hierarchyCalc), presentationTree: hierarchyToTree(hierarchyPres) });
});
return reports;
}
exports.buildReportTrees = buildReportTrees;