sec-edgar-api 0.5.2 → 0.5.4

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/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import ReportParser from './services/ReportParser';
2
2
  import SecEdgarApi from './services/SecEdgarApi';
3
3
  import ReportResolvable from './services/ReportParser/ReportResolvable';
4
4
  import { utilMap } from './util/util-map';
5
+ import FactFiscalCalculator from './services/ReportRawBuilder/FactFiscalCalculator';
5
6
  /**
6
7
  * Takes company facts data from the SEC and translates them to
7
8
  * reports as json objects.
@@ -14,5 +15,5 @@ declare const reportParser: ReportParser;
14
15
  * @see https://www.sec.gov/edgar/sec-api-documentation
15
16
  */
16
17
  declare const secEdgarApi: SecEdgarApi;
17
- export { reportParser, secEdgarApi, ReportResolvable, utilMap };
18
+ export { reportParser, secEdgarApi, ReportResolvable, utilMap, FactFiscalCalculator };
18
19
  export type * from './types';
package/build/index.js CHANGED
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.utilMap = exports.ReportResolvable = exports.secEdgarApi = exports.reportParser = void 0;
3
+ exports.FactFiscalCalculator = exports.utilMap = exports.ReportResolvable = exports.secEdgarApi = exports.reportParser = void 0;
4
4
  var ReportParser_1 = require("./services/ReportParser");
5
5
  var SecEdgarApi_1 = require("./services/SecEdgarApi");
6
6
  var ReportResolvable_1 = require("./services/ReportParser/ReportResolvable");
7
7
  exports.ReportResolvable = ReportResolvable_1.default;
8
8
  var util_map_1 = require("./util/util-map");
9
9
  Object.defineProperty(exports, "utilMap", { enumerable: true, get: function () { return util_map_1.utilMap; } });
10
+ var FactFiscalCalculator_1 = require("./services/ReportRawBuilder/FactFiscalCalculator");
11
+ exports.FactFiscalCalculator = FactFiscalCalculator_1.default;
10
12
  /**
11
13
  * Takes company facts data from the SEC and translates them to
12
14
  * reports as json objects.
@@ -1,9 +1,17 @@
1
1
  import type { FactItemExtended, ReportRaw, XMLParams } from '../../../types';
2
2
  import { GetDocumentXbrlParams } from '../../SecEdgarApi';
3
3
  import { XbrlParseResult } from '../XBRLParser/XBRLParser';
4
+ interface ReportWithPeriod extends ReportRaw {
5
+ period: number;
6
+ startDate: string;
7
+ endDate: string;
8
+ }
4
9
  export interface DocumentXbrlResult extends XbrlParseResult {
5
10
  report: ReportRaw | null;
6
11
  facts: FactItemExtended[];
7
12
  xml: string;
13
+ /** Facts grouped into reports by their start and end dates */
14
+ periodReports: ReportWithPeriod[];
8
15
  }
9
16
  export declare function parseXbrl(params: XMLParams & GetDocumentXbrlParams): DocumentXbrlResult;
17
+ export {};
@@ -24,15 +24,19 @@ var __rest = (this && this.__rest) || function (s, e) {
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.parseXbrl = void 0;
26
26
  var constants_1 = require("../../../util/constants");
27
+ var FactFiscalCalculator_1 = require("../../ReportRawBuilder/FactFiscalCalculator");
28
+ var FactPeriodResolver_1 = require("../../ReportRawBuilder/FactPeriodResolver");
27
29
  var XBRLParser_1 = require("../XBRLParser/XBRLParser");
28
30
  function isWithinDays(params) {
29
31
  var dateA = params.dateA, dateB = params.dateB, days = params.days;
32
+ if (dateA === dateB)
33
+ return true;
30
34
  var timeDiff = Math.abs(new Date(dateA).getTime() - new Date(dateB).getTime());
31
35
  var daysDiff = timeDiff / (1000 * 3600 * 24);
32
36
  return daysDiff < days;
33
37
  }
34
38
  function buildReportsFromFacts(params) {
35
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
39
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
36
40
  var filing = params.filing, facts = params.facts, fiscalPeriod = params.fiscalPeriod, fiscalYear = params.fiscalYear, pathSeparator = params.pathSeparator, cikProp = params.cik;
37
41
  var urlParts = (_a = filing === null || filing === void 0 ? void 0 : filing.url.split('/')) !== null && _a !== void 0 ? _a : [];
38
42
  var cik = cikProp !== null && cikProp !== void 0 ? cikProp : urlParts[(_b = urlParts.indexOf('data')) !== null && _b !== void 0 ? _b : -1];
@@ -59,22 +63,49 @@ function buildReportsFromFacts(params) {
59
63
  var roundPlacesByName = new Map();
60
64
  var scaleByName = new Map();
61
65
  var isFocusFactByDateKey = new Map();
66
+ var dateYearEnd = new Date(reportFocus.dateReport);
67
+ var offsetByFiscalPeriod = { Q1: 9, Q2: 6, Q3: 3, Q4: 0, FY: 0 };
68
+ dateYearEnd.setMonth(dateYearEnd.getMonth() + ((_h = offsetByFiscalPeriod[reportFocus.fiscalPeriod]) !== null && _h !== void 0 ? _h : 0));
69
+ var fiscalCalculator = new FactFiscalCalculator_1.default({
70
+ filings: filing ? [filing] : undefined,
71
+ facts: facts,
72
+ fiscalYearEnd: { day: dateYearEnd.getDate(), month: dateYearEnd.getMonth() + 1 },
73
+ });
74
+ var fiscalsByDateKey = new Map();
62
75
  for (var _i = 0, facts_1 = facts; _i < facts_1.length; _i++) {
63
76
  var fact = facts_1[_i];
64
77
  var dateKey = fact.start ? "".concat(fact.start, "_").concat(fact.end) : fact.end;
65
- (_h = reportByDateRange[dateKey]) !== null && _h !== void 0 ? _h : (reportByDateRange[dateKey] = {
66
- startDate: (_j = fact.start) !== null && _j !== void 0 ? _j : '',
78
+ if (!fiscalsByDateKey.has(dateKey)) {
79
+ var _x = fiscalCalculator.getFiscalYearQuarter({ dateStr: fact.end }), quarter = _x.quarter, year = _x.year;
80
+ var period = FactPeriodResolver_1.default.getPeriod({ end: fact.end, start: fact.start });
81
+ var fiscalPeriod_1 = (period === 12 && quarter === 4 ? 'FY' : "Q".concat(quarter));
82
+ fiscalsByDateKey.set(dateKey, { fiscalYear: year, fiscalPeriod: fiscalPeriod_1 });
83
+ }
84
+ (_j = reportByDateRange[dateKey]) !== null && _j !== void 0 ? _j : (reportByDateRange[dateKey] = {
85
+ cik: reportFocus.cik,
86
+ url: '',
87
+ splitDate: (_k = splitFact === null || splitFact === void 0 ? void 0 : splitFact.end) !== null && _k !== void 0 ? _k : null,
88
+ splitRatio: (splitFact === null || splitFact === void 0 ? void 0 : splitFact.value) ? Number(splitFact.value) : null,
89
+ dateFiled: reportFocus.dateFiled,
90
+ dateReport: fact.end,
91
+ fiscalPeriod: (_l = fiscalsByDateKey.get(dateKey)) === null || _l === void 0 ? void 0 : _l.fiscalPeriod,
92
+ startDate: (_m = fact.start) !== null && _m !== void 0 ? _m : '',
67
93
  endDate: fact.end,
94
+ fiscalYear: (_o = fiscalsByDateKey.get(dateKey)) === null || _o === void 0 ? void 0 : _o.fiscalYear,
95
+ period: FactPeriodResolver_1.default.getPeriod({ start: fact.start, end: fact.end }),
68
96
  });
69
97
  var isSplitFact = fact === splitFact;
70
- var isFocusFact = (_k = isFocusFactByDateKey.get(dateKey)) !== null && _k !== void 0 ? _k : (isWithinDays({ dateA: fact.end, dateB: reportFocus.dateReport, days: 45 }) || isSplitFact);
98
+ var isFocusFact = (_p = isFocusFactByDateKey.get(dateKey)) !== null && _p !== void 0 ? _p : (isWithinDays({ dateA: fact.end, dateB: reportFocus.dateReport, days: 45 }) || isSplitFact);
99
+ if (isFocusFact) {
100
+ fact.isCurrentPeriod = true;
101
+ }
71
102
  if (!isSplitFact) {
72
103
  isFocusFactByDateKey.set(dateKey, isFocusFact);
73
104
  }
74
105
  var el = fact;
75
- var scale = Number((_l = el.scale) !== null && _l !== void 0 ? _l : 0) || 0;
76
- var decimals = Number((_m = el.decimals) !== null && _m !== void 0 ? _m : 0) || 0;
77
- var suffix = (_o = fact === null || fact === void 0 ? void 0 : fact.segments) === null || _o === void 0 ? void 0 : _o.map(function (_a) {
106
+ var scale = Number((_q = el.scale) !== null && _q !== void 0 ? _q : 0) || 0;
107
+ var decimals = Number((_r = el.decimals) !== null && _r !== void 0 ? _r : 0) || 0;
108
+ var suffix = (_s = fact === null || fact === void 0 ? void 0 : fact.segments) === null || _s === void 0 ? void 0 : _s.map(function (_a) {
78
109
  var dimension = _a.dimension, value = _a.value;
79
110
  return "".concat(dimension).concat(pathSeparator).concat(value);
80
111
  }).join(pathSeparator);
@@ -88,8 +119,8 @@ function buildReportsFromFacts(params) {
88
119
  var prevRounding = roundPlacesByName.get(prevFactKey);
89
120
  var prevScale = scaleByName.get(prevFactKey);
90
121
  var prevFact_1 = factByName.get(prevFactKey);
91
- var prevUnit = (_q = (_p = prevFact_1 === null || prevFact_1 === void 0 ? void 0 : prevFact_1.unit) === null || _p === void 0 ? void 0 : _p.split('_').pop()) === null || _q === void 0 ? void 0 : _q.toLowerCase();
92
- var unit = (_s = (_r = fact.unit) === null || _r === void 0 ? void 0 : _r.split('_').pop()) === null || _s === void 0 ? void 0 : _s.toLowerCase();
122
+ var prevUnit = (_u = (_t = prevFact_1 === null || prevFact_1 === void 0 ? void 0 : prevFact_1.unit) === null || _t === void 0 ? void 0 : _t.split('_').pop()) === null || _u === void 0 ? void 0 : _u.toLowerCase();
123
+ var unit = (_w = (_v = fact.unit) === null || _v === void 0 ? void 0 : _v.split('_').pop()) === null || _w === void 0 ? void 0 : _w.toLowerCase();
93
124
  var shouldSkip = [
94
125
  (prevUnit === null || prevUnit === void 0 ? void 0 : prevUnit.length) === 3 && (unit === null || unit === void 0 ? void 0 : unit.length) === 3 && prevUnit !== unit && prevUnit === 'usd',
95
126
  (prevRounding !== null && prevRounding !== void 0 ? prevRounding : 0) < roundPlaces,
@@ -177,7 +208,7 @@ function parseXbrl(params) {
177
208
  url: "https://www.sec.gov/Archives/edgar/data/".concat(cik, "/").concat(accessionNumberNoHyphens, "/").concat(accessionNumber, ".txt"),
178
209
  urlPrimaryDocument: '',
179
210
  },
180
- }), factsFiltered = _p.factsFiltered, reportFocus = _p.reportFocus;
181
- return __assign(__assign({}, response), { facts: factsFiltered, report: factsFiltered.length > 0 ? reportFocus : null, xml: xml });
211
+ }), factsFiltered = _p.factsFiltered, reportFocus = _p.reportFocus, reportByDateRange = _p.reportByDateRange;
212
+ return __assign(__assign({}, response), { facts: factsFiltered, report: factsFiltered.length > 0 ? reportFocus : null, xml: xml, periodReports: Object.values(reportByDateRange) });
182
213
  }
183
214
  exports.parseXbrl = parseXbrl;
@@ -40,7 +40,7 @@ export default class ReportParser {
40
40
  *
41
41
  * @see https://www.sec.gov/edgar/sec-api-documentation
42
42
  */
43
- parseReportsRaw(companyFactListData: CompanyFactListData, options: Omit<BuildReportsParams, 'facts'> & {
43
+ parseReportsRaw(companyFactListData: CompanyFactListData, options?: Omit<BuildReportsParams, 'facts'> & {
44
44
  includeNamePrefix?: boolean;
45
45
  }): ReportRaw[];
46
46
  /**
@@ -86,7 +86,7 @@ var ReportParser = /** @class */ (function () {
86
86
  * @see https://www.sec.gov/edgar/sec-api-documentation
87
87
  */
88
88
  ReportParser.prototype.parseReportsRaw = function (companyFactListData, options) {
89
- var includeNamePrefix = options.includeNamePrefix;
89
+ var includeNamePrefix = (options !== null && options !== void 0 ? options : {}).includeNamePrefix;
90
90
  var facts = this.reportBuilder.createFacts(companyFactListData, includeNamePrefix).facts;
91
91
  return this.reportBuilder.buildReports(__assign({ facts: facts }, options));
92
92
  };
@@ -18,9 +18,14 @@ export default class FactFiscalCalculator {
18
18
  private readonly endDateCountMap;
19
19
  private readonly filedDateCountByEndDate;
20
20
  private didResolve;
21
+ private readonly fiscalYearEnd;
21
22
  constructor(params?: {
22
23
  facts?: Pick<FactItem, 'end' | 'filed'>[];
23
24
  filings?: Pick<FilingListItemTranslated, 'form' | 'reportDate' | 'filingDate' | 'accessionNumber'>[];
25
+ fiscalYearEnd?: {
26
+ month: number;
27
+ day: number;
28
+ } | null;
24
29
  });
25
30
  private useFilingsForDates;
26
31
  add(fact: {
@@ -42,13 +47,21 @@ export default class FactFiscalCalculator {
42
47
  getFiscalYearQuarter(params: {
43
48
  dateStr: string;
44
49
  endDateByYear?: Map<number, Date>;
50
+ fiscalYearEnd?: {
51
+ month: number;
52
+ day: number;
53
+ } | null;
45
54
  }): {
46
55
  year: number;
47
56
  quarter: number;
48
57
  };
49
58
  static getFiscalYearQuarter(params: {
50
59
  dateStr: string;
51
- endDateByYear: Map<number, Date>;
60
+ endDateByYear?: Map<number, Date>;
61
+ fiscalYearEnd?: {
62
+ month: number;
63
+ day: number;
64
+ } | null;
52
65
  }): {
53
66
  quarter: number;
54
67
  year: number;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ var constants_1 = require("../../util/constants");
3
4
  /**
4
5
  * Gets the fiscal period for a given date. does this by checking when the FY end periods are,
5
6
  * Then measures the offset from the end date to the next/previous fiscal year end.
@@ -14,7 +15,9 @@ var FactFiscalCalculator = /** @class */ (function () {
14
15
  this.endDateCountMap = new Map();
15
16
  this.filedDateCountByEndDate = new Map();
16
17
  this.didResolve = false;
17
- var _a = params !== null && params !== void 0 ? params : {}, _b = _a.facts, facts = _b === void 0 ? [] : _b, _c = _a.filings, filings = _c === void 0 ? [] : _c;
18
+ this.fiscalYearEnd = null;
19
+ var _a = params !== null && params !== void 0 ? params : {}, _b = _a.facts, facts = _b === void 0 ? [] : _b, _c = _a.filings, filings = _c === void 0 ? [] : _c, fiscalYearEnd = _a.fiscalYearEnd;
20
+ this.fiscalYearEnd = fiscalYearEnd !== null && fiscalYearEnd !== void 0 ? fiscalYearEnd : null;
18
21
  this.useFilingsForDates({ filings: filings });
19
22
  facts.forEach(function (fact) { return _this.add(fact); });
20
23
  }
@@ -24,12 +27,12 @@ var FactFiscalCalculator = /** @class */ (function () {
24
27
  var endDateByYear = new Map();
25
28
  filings.forEach(function (_a) {
26
29
  var reportDate = _a.reportDate, form = _a.form;
27
- if (form === '10-K' || form === '20-F') {
30
+ if (constants_1.FORMS_EARNINGS_ANNUAL.includes(form)) {
28
31
  endDateByYear.set(Number(reportDate.substring(0, 4)), new Date(reportDate));
29
32
  }
30
33
  });
31
34
  filings.forEach(function (filing) {
32
- if (filing.form === '10-K' || filing.form === '10-Q' || filing.form === '20-F' || filing.form === '40-F') {
35
+ if (constants_1.FORMS_EARNINGS.includes(filing.form)) {
33
36
  var _a = _this.getFiscalYearQuarter({
34
37
  dateStr: filing.reportDate,
35
38
  endDateByYear: endDateByYear,
@@ -201,17 +204,25 @@ var FactFiscalCalculator = /** @class */ (function () {
201
204
  return (_a = this.datesByFiscals.get("".concat(params.year, "_").concat(params.quarter))) !== null && _a !== void 0 ? _a : null;
202
205
  };
203
206
  FactFiscalCalculator.prototype.getFiscalYearQuarter = function (params) {
204
- var dateStr = params.dateStr, _a = params.endDateByYear, endDateByYear = _a === void 0 ? this.endDateByYear : _a;
207
+ var dateStr = params.dateStr, _a = params.endDateByYear, endDateByYear = _a === void 0 ? this.endDateByYear : _a, _b = params.fiscalYearEnd, fiscalYearEnd = _b === void 0 ? this.fiscalYearEnd : _b;
205
208
  if (this.fiscalsByEndDate.has(dateStr)) {
206
209
  return this.fiscalsByEndDate.get(dateStr);
207
210
  }
208
- var fiscals = FactFiscalCalculator.getFiscalYearQuarter({ dateStr: dateStr, endDateByYear: endDateByYear });
211
+ var fiscals = FactFiscalCalculator.getFiscalYearQuarter({ dateStr: dateStr, endDateByYear: endDateByYear, fiscalYearEnd: fiscalYearEnd });
209
212
  this.fiscalsByEndDate.set(dateStr, fiscals);
210
213
  return fiscals;
211
214
  };
212
215
  FactFiscalCalculator.getFiscalYearQuarter = function (params) {
213
- var dateStr = params.dateStr, endDateByYear = params.endDateByYear;
214
- if (endDateByYear.size === 0) {
216
+ var _a;
217
+ var dateStr = params.dateStr, endDateByYearProp = params.endDateByYear, fiscalYearEnd = params.fiscalYearEnd;
218
+ var endDateByYear = endDateByYearProp !== null && endDateByYearProp !== void 0 ? endDateByYearProp : new Map();
219
+ if (fiscalYearEnd) {
220
+ var month = fiscalYearEnd.month, day = fiscalYearEnd.day;
221
+ var year = new Date().getFullYear();
222
+ var yearEndDate_1 = new Date("".concat(year, "-").concat(month, "-").concat(day));
223
+ endDateByYear.set(year, (_a = endDateByYear.get(year)) !== null && _a !== void 0 ? _a : yearEndDate_1);
224
+ }
225
+ if (!(endDateByYear === null || endDateByYear === void 0 ? void 0 : endDateByYear.size)) {
215
226
  throw new Error('No annual report dates provided');
216
227
  }
217
228
  var getYearEndDate = function (year) {
@@ -17,6 +17,10 @@ export interface BuildReportsParams {
17
17
  * For member facts (facts with segments), the separator between the fact name and the segments.
18
18
  */
19
19
  pathSeparatorForMemberFacts?: string;
20
+ fiscalYearEnd?: {
21
+ month: number;
22
+ day: number;
23
+ } | null;
20
24
  }
21
25
  /**
22
26
  * Builds ReportRaw objects from company facts. Adjusts for splits and resolves period values.
@@ -37,7 +37,7 @@ var ReportRawBuilder = /** @class */ (function () {
37
37
  };
38
38
  ReportRawBuilder.prototype.buildReports = function (params) {
39
39
  var _this = this;
40
- var factsProp = params.facts, filings = params.filings, splitsProp = params.splits, _a = params.resolvePeriodValues, resolvePeriodValues = _a === void 0 ? true : _a, _b = params.adjustForSplits, adjustForSplits = _b === void 0 ? true : _b, _c = params.pathSeparatorForMemberFacts, pathSeparatorForMemberFacts = _c === void 0 ? '>' : _c;
40
+ var factsProp = params.facts, filings = params.filings, splitsProp = params.splits, _a = params.resolvePeriodValues, resolvePeriodValues = _a === void 0 ? true : _a, _b = params.adjustForSplits, adjustForSplits = _b === void 0 ? true : _b, _c = params.pathSeparatorForMemberFacts, pathSeparatorForMemberFacts = _c === void 0 ? '>' : _c, fiscalYearEnd = params.fiscalYearEnd;
41
41
  // Rename member facts to prevent overwriting parent facts.
42
42
  var facts = factsProp.map(function (fact) {
43
43
  var factKey = _this.getFactKey(fact, pathSeparatorForMemberFacts);
@@ -50,6 +50,7 @@ var ReportRawBuilder = /** @class */ (function () {
50
50
  var fiscalCalculator = new FactFiscalCalculator_1.default({
51
51
  filings: filings === null || filings === void 0 ? void 0 : filings.filter(function (f) { return constants_1.FORMS_EARNINGS.includes(f.form); }),
52
52
  facts: facts,
53
+ fiscalYearEnd: fiscalYearEnd,
53
54
  });
54
55
  var accessionByYearQuarter = new Map();
55
56
  filings === null || filings === void 0 ? void 0 : filings.forEach(function (f) {
@@ -76,6 +76,7 @@ export interface FactItem {
76
76
  }
77
77
  export interface FactItemExtended extends FactItem {
78
78
  isUsedInReport?: boolean;
79
+ isCurrentPeriod?: boolean;
79
80
  decimals?: number;
80
81
  scale?: number;
81
82
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sec-edgar-api",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "Fetch and parse SEC earnings reports and other filings. Useful for financial analysis.",
5
5
  "main": "build/index.js",
6
6
  "author": "Andrew Evers (https://github.com/andyevers)",