UNPKG

sec-edgar-api

Version:

Fetch and parse SEC earnings reports and other filings. Useful for financial analysis.

215 lines (214 loc) 12.1 kB
"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 }); var FactPeriodResolver_1 = require("./FactPeriodResolver"); var FactSplitAdjuster_1 = require("./FactSplitAdjuster"); /** * There are many facts properties for the same period but filed at different times. * This groups those together and resolves the period and trailing values for each group. */ var FactGrouper = /** @class */ (function () { function FactGrouper() { this.preferFirstValue = true; } FactGrouper.prototype.createFactGroup = function (params) { return __assign({ name: '', unit: '', reportEnd: '', accn: '', reportFiled: '', isResolverGenerated: true, fiscalYear: 0, quarter: 0, filedFirst: '', filedLast: '', endFirst: '', endLast: '', valuePeriodFirst: null, valuePeriodLast: null, valueTrailingFirst: null, valueTrailingLast: null, valuePeriodResolved: null, valueTrailingResolved: null, valueSplitAdjustedPeriod: null, valueSplitAdjustedTrailing: null, values: [], facts: [] }, params); }; FactGrouper.prototype.createGroupKey = function (params) { var fiscalYear = params.fiscalYear, quarter = params.quarter, name = params.name; return "".concat(fiscalYear, "_").concat(quarter, "_").concat(name); }; FactGrouper.prototype.toValue = function (value) { return !isNaN(value) ? Number(value) : value || null; }; /** * Map structure { 2022_Q3: { name: ... } }. NOTE: Does not include fiscal year report key. * All groups contain both trailing and period values, so use trailing from Q4 to get FY values. */ FactGrouper.prototype.buildFactGroupsByReportKey = function (params) { var _this = this; var _a, _b, _c, _d; var facts = params.facts, cik = params.cik, fiscalCalculator = params.fiscalCalculator, resolvePeriodValues = params.resolvePeriodValues, _e = params.generateMissingGroups, generateMissingGroups = _e === void 0 ? false : _e, splits = params.splits; // min and max year will be used to sort the reports var minYear = 0; var maxYear = 9999; var factGroupByKey = new Map(); var periodResolver = new FactPeriodResolver_1.default({ cik: cik }); var factSplitAdjuster = new FactSplitAdjuster_1.default(); // used for groups that need to be generated without using a fact var unitByPropertyName = new Map(); var accnByFiled = new Map(); // Create groups from facts. for (var _i = 0, facts_1 = facts; _i < facts_1.length; _i++) { var fact = facts_1[_i]; var _f = fiscalCalculator.getFiscalYearQuarter({ dateStr: fact.end }), quarter = _f.quarter, year = _f.year; var _g = (_a = fiscalCalculator.getDatesByYearQuarter({ quarter: quarter, year: year })) !== null && _a !== void 0 ? _a : {}, _h = _g.end, reportEnd = _h === void 0 ? '' : _h, _j = _g.filed, reportFiled = _j === void 0 ? '' : _j; var groupKey = this.createGroupKey({ fiscalYear: year, quarter: quarter, name: fact.name }); if (year < minYear) minYear = year; if (year > maxYear) maxYear = year; // period checks to see if the fact needs to be resolved for quarterly or trailing values var period = periodResolver.getPeriod(fact); var isPeriodFact = period <= 3; var isTrailingFact = period > 3 || (isPeriodFact && quarter === 1); var factValue = this.toValue(fact.value); // if no group exists, create from fact if (!factGroupByKey.has(groupKey)) { var group_1 = this.createFactGroup({ name: fact.name, accn: periodResolver.isOriginalFiling({ end: fact.end, filed: fact.filed }) ? fact.accn : '', unit: fact.unit, reportEnd: reportEnd, reportFiled: reportFiled, isResolverGenerated: false, fiscalYear: year, quarter: quarter, filedFirst: fact.filed, filedLast: fact.filed, endFirst: fact.end, endLast: fact.end, valuePeriodFirst: isPeriodFact ? factValue : null, valuePeriodLast: isPeriodFact ? factValue : null, valueTrailingFirst: isTrailingFact ? factValue : null, valueTrailingLast: isTrailingFact ? factValue : null, values: [], facts: [fact], }); if (factValue !== null) { group_1.values.push(factValue); } accnByFiled.set(fact.filed, (_b = fact.accn) !== null && _b !== void 0 ? _b : ''); unitByPropertyName.set(fact.name, fact.unit); factGroupByKey.set(groupKey, group_1); continue; } // if group already exists, update values var group = factGroupByKey.get(groupKey); group.facts.push(fact); group.endFirst = fact.end < group.endFirst ? fact.end : group.endFirst; group.endLast = fact.end > group.endLast ? fact.end : group.endLast; group.filedFirst = fact.filed < group.filedFirst ? fact.filed : group.filedFirst; group.filedLast = fact.filed > group.filedLast ? fact.filed : group.filedLast; if (factValue !== null && !group.values.includes(factValue)) { group.values.push(factValue); } if (periodResolver.isOriginalFiling({ end: fact.end, filed: fact.filed })) { group.accn = (_d = (_c = fact.accn) !== null && _c !== void 0 ? _c : group.accn) !== null && _d !== void 0 ? _d : ''; accnByFiled.set(fact.filed, group.accn); } if (isPeriodFact) { if (group.valuePeriodFirst === null) { group.valuePeriodFirst = factValue; } if (factValue !== group.valuePeriodFirst && factValue !== group.valuePeriodLast) { group.valuePeriodLast = factValue; } } if (isTrailingFact) { if (group.valueTrailingFirst === null) { group.valueTrailingFirst = factValue; } if (factValue !== group.valueTrailingFirst && factValue !== group.valueTrailingLast) { group.valueTrailingLast = factValue; } } } // adjust for splits var factGroupsByReportKey = new Map(); if (splits) { factSplitAdjuster.adjustForSplits({ factGroups: Array.from(factGroupByKey.values()), splits: splits, }); } factGroupByKey.forEach(function (group) { var _a, _b; // add to the period resolver to resolve quarterly and trailing values var preferredValuePeriod = _this.preferFirstValue ? group.valuePeriodLast : group.valuePeriodLast; var preferredValueTrailing = _this.preferFirstValue ? group.valueTrailingFirst : group.valueTrailingLast; var selectedFactPeriod = group.facts.find(function (fact) { var period = FactPeriodResolver_1.default.getPeriod(fact); return fact.value === preferredValuePeriod && period <= 3; }); var selectedFactTrailing = group.facts.find(function (fact) { var period = FactPeriodResolver_1.default.getPeriod(fact); return fact.value === preferredValueTrailing && (period > 3 || period === 0); }); var valuePeriod = _this.toValue((_a = group.valueSplitAdjustedPeriod) !== null && _a !== void 0 ? _a : preferredValuePeriod); var valueTrailing = _this.toValue((_b = group.valueSplitAdjustedTrailing) !== null && _b !== void 0 ? _b : preferredValueTrailing); if (selectedFactPeriod && valuePeriod !== null) { periodResolver.add({ end: selectedFactPeriod.end, filed: selectedFactPeriod.filed, name: selectedFactPeriod.name, quarter: group.quarter, value: valuePeriod, year: group.fiscalYear, start: selectedFactPeriod.start, }); } if (selectedFactTrailing && valueTrailing !== null) { periodResolver.add({ end: selectedFactTrailing.end, filed: selectedFactTrailing.filed, name: selectedFactTrailing.name, quarter: group.quarter, value: valueTrailing, year: group.fiscalYear, start: selectedFactTrailing.start, }); } }); // Resolve quarterly and trailing values, and if no facts present for a certain period, create a group with resolved values. periodResolver.forEach(function (_a) { var _b, _c, _d, _e, _f, _g; var propertyName = _a.propertyName, quarter = _a.quarter, valueQuarter = _a.valueQuarter, valueTrailing = _a.valueTrailing, year = _a.year; var groupKey = _this.createGroupKey({ fiscalYear: year, name: propertyName, quarter: quarter }); var group = factGroupByKey.get(groupKey); if (!group && (!resolvePeriodValues || !generateMissingGroups)) return; var _h = (_b = fiscalCalculator.getDatesByYearQuarter({ quarter: quarter, year: year })) !== null && _b !== void 0 ? _b : { end: '', filed: '' }, end = _h.end, filed = _h.filed; var reportKey = "".concat(year, "_Q").concat(quarter); var bucket = (_c = factGroupsByReportKey.get(reportKey)) !== null && _c !== void 0 ? _c : factGroupsByReportKey.set(reportKey, []).get(reportKey); if (!group) { group = _this.createFactGroup({ reportEnd: end, reportFiled: filed, endFirst: end, endLast: end, name: propertyName, accn: (_d = accnByFiled.get(filed)) !== null && _d !== void 0 ? _d : '', unit: (_e = unitByPropertyName.get(propertyName)) !== null && _e !== void 0 ? _e : '', isResolverGenerated: true, fiscalYear: year, quarter: quarter, valuePeriodResolved: valueQuarter, valueTrailingResolved: valueTrailing, }); factGroupByKey.set(groupKey, group); } else if (resolvePeriodValues) { var shouldUseTrailingForQuarter = FactPeriodResolver_1.default.isAverageShares({ propertyName: group.name }) && group.quarter === 4; group.valuePeriodResolved = shouldUseTrailingForQuarter ? valueTrailing : valueQuarter; group.valueTrailingResolved = valueTrailing; (_f = group.valuePeriodFirst) !== null && _f !== void 0 ? _f : (group.valuePeriodFirst = shouldUseTrailingForQuarter ? valueTrailing : valueQuarter); (_g = group.valueTrailingFirst) !== null && _g !== void 0 ? _g : (group.valueTrailingFirst = valueTrailing); } bucket.push(group); }); return { factGroupsByReportKey: factGroupsByReportKey, minYear: minYear, maxYear: maxYear }; }; return FactGrouper; }()); exports.default = FactGrouper;