sec-edgar-api 0.0.1

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.
Files changed (84) hide show
  1. package/README.md +27 -0
  2. package/build/index.d.ts +21 -0
  3. package/build/index.js +26 -0
  4. package/build/services/FactFileReader/FactFileReader.d.ts +30 -0
  5. package/build/services/FactFileReader/FactFileReader.js +36 -0
  6. package/build/services/FactFileReader/index.d.ts +2 -0
  7. package/build/services/FactFileReader/index.js +4 -0
  8. package/build/services/ReportParser/FactIterator.d.ts +18 -0
  9. package/build/services/ReportParser/FactIterator.js +35 -0
  10. package/build/services/ReportParser/PropertyResolver.d.ts +25 -0
  11. package/build/services/ReportParser/PropertyResolver.js +44 -0
  12. package/build/services/ReportParser/ReportParser.d.ts +53 -0
  13. package/build/services/ReportParser/ReportParser.js +97 -0
  14. package/build/services/ReportParser/ReportRawParser.d.ts +34 -0
  15. package/build/services/ReportParser/ReportRawParser.js +154 -0
  16. package/build/services/ReportParser/ReportTranslatedProxy.d.ts +9 -0
  17. package/build/services/ReportParser/ReportTranslatedProxy.js +40 -0
  18. package/build/services/ReportParser/ReportWrapper.d.ts +27 -0
  19. package/build/services/ReportParser/ReportWrapper.js +89 -0
  20. package/build/services/ReportParser/index.d.ts +2 -0
  21. package/build/services/ReportParser/index.js +4 -0
  22. package/build/services/ReportParser/resolvers/helpers.d.ts +21 -0
  23. package/build/services/ReportParser/resolvers/helpers.js +49 -0
  24. package/build/services/ReportParser/resolvers/index.d.ts +31 -0
  25. package/build/services/ReportParser/resolvers/index.js +33 -0
  26. package/build/services/ReportParser/resolvers/resolve-asset-current.d.ts +2 -0
  27. package/build/services/ReportParser/resolvers/resolve-asset-current.js +20 -0
  28. package/build/services/ReportParser/resolvers/resolve-asset-non-current-ppe-gross.d.ts +2 -0
  29. package/build/services/ReportParser/resolvers/resolve-asset-non-current-ppe-gross.js +20 -0
  30. package/build/services/ReportParser/resolvers/resolve-cash-flow-capex.d.ts +5 -0
  31. package/build/services/ReportParser/resolvers/resolve-cash-flow-capex.js +37 -0
  32. package/build/services/ReportParser/resolvers/resolve-cash-flow-free.d.ts +2 -0
  33. package/build/services/ReportParser/resolvers/resolve-cash-flow-free.js +23 -0
  34. package/build/services/ReportParser/resolvers/resolve-cash-flow-operating.d.ts +2 -0
  35. package/build/services/ReportParser/resolvers/resolve-cash-flow-operating.js +39 -0
  36. package/build/services/ReportParser/resolvers/resolve-cash-flow-working-capital-non-cash.d.ts +2 -0
  37. package/build/services/ReportParser/resolvers/resolve-cash-flow-working-capital-non-cash.js +22 -0
  38. package/build/services/ReportParser/resolvers/resolve-ebit.d.ts +2 -0
  39. package/build/services/ReportParser/resolvers/resolve-ebit.js +25 -0
  40. package/build/services/ReportParser/resolvers/resolve-expense-depreciation.d.ts +2 -0
  41. package/build/services/ReportParser/resolvers/resolve-expense-depreciation.js +96 -0
  42. package/build/services/ReportParser/resolvers/resolve-expense-operating.d.ts +2 -0
  43. package/build/services/ReportParser/resolvers/resolve-expense-operating.js +22 -0
  44. package/build/services/ReportParser/resolvers/resolve-expense-total.d.ts +2 -0
  45. package/build/services/ReportParser/resolvers/resolve-expense-total.js +20 -0
  46. package/build/services/ReportParser/resolvers/resolve-fiscal-year-cumulative-properties.d.ts +5 -0
  47. package/build/services/ReportParser/resolvers/resolve-fiscal-year-cumulative-properties.js +70 -0
  48. package/build/services/ReportParser/resolvers/resolve-liability-current.d.ts +2 -0
  49. package/build/services/ReportParser/resolvers/resolve-liability-current.js +20 -0
  50. package/build/services/ReportParser/resolvers/resolve-q4-fiscal-year-matching-properties.d.ts +5 -0
  51. package/build/services/ReportParser/resolvers/resolve-q4-fiscal-year-matching-properties.js +24 -0
  52. package/build/services/ReportParser/resolvers/resolve-revenue-total.d.ts +2 -0
  53. package/build/services/ReportParser/resolvers/resolve-revenue-total.js +20 -0
  54. package/build/services/SecEdgarApi/Client.d.ts +44 -0
  55. package/build/services/SecEdgarApi/Client.js +104 -0
  56. package/build/services/SecEdgarApi/Downloader.d.ts +26 -0
  57. package/build/services/SecEdgarApi/Downloader.js +102 -0
  58. package/build/services/SecEdgarApi/FactsDownloader.d.ts +30 -0
  59. package/build/services/SecEdgarApi/FactsDownloader.js +125 -0
  60. package/build/services/SecEdgarApi/SecConnector.d.ts +47 -0
  61. package/build/services/SecEdgarApi/SecConnector.js +143 -0
  62. package/build/services/SecEdgarApi/SecEdgarApi.d.ts +92 -0
  63. package/build/services/SecEdgarApi/SecEdgarApi.js +184 -0
  64. package/build/services/SecEdgarApi/Throttler.d.ts +34 -0
  65. package/build/services/SecEdgarApi/Throttler.js +111 -0
  66. package/build/services/SecEdgarApi/Unzipper.d.ts +40 -0
  67. package/build/services/SecEdgarApi/Unzipper.js +40 -0
  68. package/build/services/SecEdgarApi/index.d.ts +3 -0
  69. package/build/services/SecEdgarApi/index.js +19 -0
  70. package/build/types/company-facts.type.d.ts +53 -0
  71. package/build/types/company-facts.type.js +2 -0
  72. package/build/types/index.d.ts +4 -0
  73. package/build/types/index.js +20 -0
  74. package/build/types/report-raw.type.d.ts +23 -0
  75. package/build/types/report-raw.type.js +2 -0
  76. package/build/types/report-translated.type.d.ts +58 -0
  77. package/build/types/report-translated.type.js +2 -0
  78. package/build/types/submission.type.d.ts +70 -0
  79. package/build/types/submission.type.js +2 -0
  80. package/build/util/cik-by-symbol.d.ts +5 -0
  81. package/build/util/cik-by-symbol.js +9632 -0
  82. package/build/util/key-translations.d.ts +7 -0
  83. package/build/util/key-translations.js +174 -0
  84. package/package.json +41 -0
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # sec-edgar-api
2
+
3
+ Fetch and parse earnings reports and other documents filed with the SEC using the EDGAR API.
4
+ This package is focused on the earnings reports for stock analysis.
5
+
6
+ ## Resolvers
7
+
8
+ The main problem with the edgar API is that the property names and data provided are not uniform. You have to deal with companies omitting important data
9
+ in some filings, or using different property keys for the same data point.
10
+
11
+ Resolvers attempt to get information from each report and output a uniform interface. The resolvers will calculate missing data if there is other data that can be used to derive from.
12
+
13
+ | Resolver | Formula used to derive values |
14
+ | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
15
+ | resolveAssetCurrent | assetTotal - assetNonCurrent = assetCurrent |
16
+ | resolveAssetNonCurrentPpeGross | assetNonCurrentPPENet + expenseDepreciationAccumulated = assetNonCurrentPpeGross |
17
+ | resolveCashFlowCapex | Q1 + Q2 + Q3 + Q4 = FY (if FY known, divides evenly between missing quarters) |
18
+ | resolveCashFlowFree | cashFlowOperating - cashFlowCapex = cashFlowFree |
19
+ | resolveCashFlowOperating | incomeNet + expenseDepreciation - changeInWorkingCapitalNonCash = cashFlowOperating |
20
+ | resolveCashFlowWorkingCapitalNonCash | (assetCurrent - assetCurrentCashEquivalents) - (liabilityCurrent - liabilityCurrentDebt) = cashFlowWorkingCapitalNonCash |
21
+ | resolveEbit | expenseDepreciation + ebitda = ebit |
22
+ | resolveExpenseDepreciation | (expenseDepreciationFY / assetNonCurrentPpeGrossFY) x assetNonCurrentPpeGross = expenseDepreciation |
23
+ | resolveExpenseOperating | revenueTotal - incomeOperating - revenueCost = expenseOperating |
24
+ | resolveExpenseTotal | revenueTotal - incomeNet = expenseTotal |
25
+ | resolveFiscalYearCumulativeProperties | Q1 + Q2 + Q3 + Q4 = FY (for quarterly properties that add to annual) |
26
+ | resolveQ4FiscalYearMatchingProperties | Q4 = FY (for non-cumulative properties such as sharesOutstanding) |
27
+ | resolveRevenueTotal | revenueCost + profitGross = revenueTotal |
@@ -0,0 +1,21 @@
1
+ import FactFileReader from './services/FactFileReader';
2
+ import ReportParser from './services/ReportParser';
3
+ import SecEdgarApi from './services/SecEdgarApi';
4
+ /**
5
+ * Takes company facts data from the SEC and translates them to
6
+ * reports as json objects.
7
+ */
8
+ declare const reportParser: ReportParser;
9
+ /**
10
+ * Reads files from the companyfacts directory (which can be downloaded
11
+ * using secEdgarApi.downloadCompanyFacts()).
12
+ */
13
+ declare const factFileReader: FactFileReader;
14
+ /**
15
+ * Gets company reports and filings from the SEC EDGAR API. Requests are
16
+ * throttled with 120ms delay between requests to avoid rate limiting.
17
+ *
18
+ * @see https://www.sec.gov/edgar/sec-api-documentation
19
+ */
20
+ declare const secEdgarApi: SecEdgarApi;
21
+ export { reportParser, factFileReader, secEdgarApi };
package/build/index.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.secEdgarApi = exports.factFileReader = exports.reportParser = void 0;
4
+ var FactFileReader_1 = require("./services/FactFileReader");
5
+ var ReportParser_1 = require("./services/ReportParser");
6
+ var SecEdgarApi_1 = require("./services/SecEdgarApi");
7
+ /**
8
+ * Takes company facts data from the SEC and translates them to
9
+ * reports as json objects.
10
+ */
11
+ var reportParser = new ReportParser_1.default();
12
+ exports.reportParser = reportParser;
13
+ /**
14
+ * Reads files from the companyfacts directory (which can be downloaded
15
+ * using secEdgarApi.downloadCompanyFacts()).
16
+ */
17
+ var factFileReader = new FactFileReader_1.default();
18
+ exports.factFileReader = factFileReader;
19
+ /**
20
+ * Gets company reports and filings from the SEC EDGAR API. Requests are
21
+ * throttled with 120ms delay between requests to avoid rate limiting.
22
+ *
23
+ * @see https://www.sec.gov/edgar/sec-api-documentation
24
+ */
25
+ var secEdgarApi = new SecEdgarApi_1.default();
26
+ exports.secEdgarApi = secEdgarApi;
@@ -0,0 +1,30 @@
1
+ import { CompanyFactListData } from '../../types/company-facts.type';
2
+ interface FileManager {
3
+ readFileSync(path: string, encoding: string | object): string;
4
+ }
5
+ interface FactFileReaderArgs {
6
+ companyFactsDirname?: string;
7
+ cikBySymbol?: Record<string, number>;
8
+ fileManager?: FileManager;
9
+ }
10
+ interface ReadFactFileParams {
11
+ symbol: string;
12
+ companyFactsDirname: string;
13
+ }
14
+ /**
15
+ * Reads files from companyfacts folder from sec
16
+ */
17
+ export default class FactFileReader {
18
+ private readonly fileManager;
19
+ private readonly cikBySymbol;
20
+ constructor(args?: FactFileReaderArgs);
21
+ getCikBySymbol(): Record<string, number>;
22
+ /**
23
+ * opens fact file from companyfacts directory
24
+ *
25
+ * @param symbol ex: AAPL
26
+ * @param companyFactsDirname ex: path.resolve(__dirname, './downloads/companyfacts')
27
+ */
28
+ readFactFile(params: ReadFactFileParams): CompanyFactListData;
29
+ }
30
+ export {};
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var fs = require("fs");
4
+ var cik_by_symbol_1 = require("../../util/cik-by-symbol");
5
+ /**
6
+ * Reads files from companyfacts folder from sec
7
+ */
8
+ var FactFileReader = /** @class */ (function () {
9
+ function FactFileReader(args) {
10
+ var _a = args !== null && args !== void 0 ? args : {}, _b = _a.fileManager, fileManager = _b === void 0 ? fs : _b, _c = _a.cikBySymbol, cikBySymbol = _c === void 0 ? cik_by_symbol_1.default : _c;
11
+ this.fileManager = fileManager;
12
+ this.cikBySymbol = cikBySymbol;
13
+ }
14
+ FactFileReader.prototype.getCikBySymbol = function () {
15
+ return this.cikBySymbol;
16
+ };
17
+ /**
18
+ * opens fact file from companyfacts directory
19
+ *
20
+ * @param symbol ex: AAPL
21
+ * @param companyFactsDirname ex: path.resolve(__dirname, './downloads/companyfacts')
22
+ */
23
+ FactFileReader.prototype.readFactFile = function (params) {
24
+ var _a;
25
+ var companyFactsDirname = params.companyFactsDirname, symbol = params.symbol;
26
+ var cik = (_a = this.cikBySymbol[symbol]) !== null && _a !== void 0 ? _a : null;
27
+ if (!cik) {
28
+ throw new Error("No cik found for symbol ".concat(symbol));
29
+ }
30
+ var cikStr = cik.toString().padStart(10, '0');
31
+ var result = this.fileManager.readFileSync("".concat(companyFactsDirname, "/CIK").concat(cikStr, ".json"), 'utf-8');
32
+ return JSON.parse(result);
33
+ };
34
+ return FactFileReader;
35
+ }());
36
+ exports.default = FactFileReader;
@@ -0,0 +1,2 @@
1
+ import FactFileReader from './FactFileReader';
2
+ export default FactFileReader;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var FactFileReader_1 = require("./FactFileReader");
4
+ exports.default = FactFileReader_1.default;
@@ -0,0 +1,18 @@
1
+ import { CompanyFactListData, FactValue } from '../../types/company-facts.type';
2
+ export interface IterateFactsCallbackData {
3
+ factValue: FactValue;
4
+ propertyName: string;
5
+ description: string;
6
+ label: string;
7
+ unit: string;
8
+ taxonomy: string;
9
+ stopIteration: () => void;
10
+ }
11
+ export default class FactIterator {
12
+ /**
13
+ * Avoids deep nesting logic while iteratating through company facts
14
+ *
15
+ * @param callback called on each company fact.
16
+ */
17
+ iterateCompanyFacts(companyFactListData: Pick<CompanyFactListData, 'facts'>, callback: (data: IterateFactsCallbackData) => void): void;
18
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var FactIterator = /** @class */ (function () {
4
+ function FactIterator() {
5
+ }
6
+ /**
7
+ * Avoids deep nesting logic while iteratating through company facts
8
+ *
9
+ * @param callback called on each company fact.
10
+ */
11
+ FactIterator.prototype.iterateCompanyFacts = function (companyFactListData, callback) {
12
+ var facts = companyFactListData.facts;
13
+ var shouldContinue = true;
14
+ var stopIteration = function () {
15
+ shouldContinue = false;
16
+ };
17
+ for (var taxonomy in facts) {
18
+ var factByPropertyName = facts[taxonomy];
19
+ for (var propertyName in factByPropertyName) {
20
+ var _a = factByPropertyName[propertyName], description = _a.description, label = _a.label, units = _a.units;
21
+ for (var unit in units) {
22
+ var factValues = units[unit];
23
+ for (var _i = 0, factValues_1 = factValues; _i < factValues_1.length; _i++) {
24
+ var factValue = factValues_1[_i];
25
+ callback({ factValue: factValue, taxonomy: taxonomy, propertyName: propertyName, unit: unit, description: description, label: label, stopIteration: stopIteration });
26
+ if (!shouldContinue)
27
+ return;
28
+ }
29
+ }
30
+ }
31
+ }
32
+ };
33
+ return FactIterator;
34
+ }());
35
+ exports.default = FactIterator;
@@ -0,0 +1,25 @@
1
+ import ReportWrapper from '../ReportParser/ReportWrapper';
2
+ import resolvers from './resolvers';
3
+ export default class PropertyResolver {
4
+ private readonly resolvers;
5
+ constructor(args?: {
6
+ resolvers: {
7
+ resolveAssetNonCurrentPPEGross: typeof import("./resolvers/resolve-asset-non-current-ppe-gross").resolveAssetNonCurrentPPEGross;
8
+ resolveExpenseDepreciation: typeof import("./resolvers/resolve-expense-depreciation").resolveExpenseDepreciation;
9
+ resolveExpenseOperating: typeof import("./resolvers/resolve-expense-operating").resolveExpenseOperating;
10
+ resolveCashFlowFree: typeof import("./resolvers/resolve-cash-flow-free").resolveCashFlowFree;
11
+ resolveEbit: typeof import("./resolvers/resolve-ebit").resolveEbit;
12
+ resolveAssetCurrent: typeof import("./resolvers/resolve-asset-current").resolveAssetCurrent;
13
+ resolveCashFlowCapex: typeof import("./resolvers/resolve-cash-flow-capex").resolveCashFlowCapex;
14
+ resolveFiscalYearCumulativeProperties: typeof import("./resolvers/resolve-fiscal-year-cumulative-properties").resolveFiscalYearCumulativeProperties;
15
+ resolveRevenueTotal: typeof import("./resolvers/resolve-revenue-total").resolveRevenueTotal;
16
+ resolveExpenseTotal: typeof import("./resolvers/resolve-expense-total").resolveExpenseTotal;
17
+ resolveCashFlowOperating: typeof import("./resolvers/resolve-cash-flow-operating").resolveCashFlowOperating;
18
+ resolveLiabilityCurrent: typeof import("./resolvers/resolve-liability-current").resolveLiabilityCurrent;
19
+ resolveQ4FiscalYearMatchingProperties: typeof import("./resolvers/resolve-q4-fiscal-year-matching-properties").resolveQ4FiscalYearMatchingProperties;
20
+ resolveCashFlowWorkingCapitalNonCash: typeof import("./resolvers/resolve-cash-flow-working-capital-non-cash").resolveCashFlowWorkingCapitalNonCash;
21
+ };
22
+ });
23
+ getDefaultResolvers(): typeof resolvers;
24
+ resolveAll(reports: ReportWrapper[] | Map<string, ReportWrapper>): void;
25
+ }
@@ -0,0 +1,44 @@
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
+ var resolvers_1 = require("./resolvers");
15
+ var PropertyResolver = /** @class */ (function () {
16
+ function PropertyResolver(args) {
17
+ if (args === void 0) { args = { resolvers: resolvers_1.default }; }
18
+ this.resolvers = args.resolvers;
19
+ }
20
+ PropertyResolver.prototype.getDefaultResolvers = function () {
21
+ return __assign({}, this.resolvers);
22
+ };
23
+ PropertyResolver.prototype.resolveAll = function (reports) {
24
+ var _this = this;
25
+ reports.forEach(function (report) {
26
+ _this.resolvers.resolveQ4FiscalYearMatchingProperties(report);
27
+ _this.resolvers.resolveFiscalYearCumulativeProperties(report);
28
+ _this.resolvers.resolveRevenueTotal(report);
29
+ _this.resolvers.resolveExpenseTotal(report);
30
+ _this.resolvers.resolveAssetCurrent(report);
31
+ _this.resolvers.resolveLiabilityCurrent(report);
32
+ _this.resolvers.resolveCashFlowWorkingCapitalNonCash(report);
33
+ _this.resolvers.resolveExpenseOperating(report);
34
+ _this.resolvers.resolveAssetNonCurrentPPEGross(report);
35
+ _this.resolvers.resolveEbit(report);
36
+ _this.resolvers.resolveExpenseDepreciation(report);
37
+ _this.resolvers.resolveCashFlowOperating(report);
38
+ _this.resolvers.resolveCashFlowCapex(report);
39
+ _this.resolvers.resolveCashFlowFree(report);
40
+ });
41
+ };
42
+ return PropertyResolver;
43
+ }());
44
+ exports.default = PropertyResolver;
@@ -0,0 +1,53 @@
1
+ import { CompanyFactListData, ReportRaw, ReportTranslated } from '../../types';
2
+ import { IterateFactsCallbackData } from './FactIterator';
3
+ import PropertyResolver from './PropertyResolver';
4
+ import ReportRawParser, { ParseReportsOptions } from './ReportRawParser';
5
+ import ReportWrapper from './ReportWrapper';
6
+ interface ReportParserArgs {
7
+ reportRawParser?: ReportRawParser;
8
+ propertyResolver?: PropertyResolver;
9
+ keyTranslator?: Record<string, string[]>;
10
+ }
11
+ type TranslateRawReportsCallback<T> = (report: T extends undefined ? ReportTranslated : Record<keyof T, string | number>, reportRaw: ReportRaw, keyTranslator: T) => any;
12
+ /**
13
+ * Takes company facts data from the SEC and translates them to reports as json objects.
14
+ */
15
+ export default class ReportParser {
16
+ private readonly reportRawParser;
17
+ private readonly keyTranslator;
18
+ private readonly propertyResolver;
19
+ constructor(args?: ReportParserArgs);
20
+ /**
21
+ * translates company facts to ReportTranslated. To translate to custom report, use parseReportsRaw and translateReportsRaw
22
+ *
23
+ * This includes only 10-K and 10-Q annual and quarterly reports. To include all reports, use parseReportsRaw
24
+ *
25
+ * @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
+ */
27
+ parseReports(companyFactListData: Pick<CompanyFactListData, 'facts'>): ReportWrapper[];
28
+ /**
29
+ * Same as parseReports but accepts ReportRaw[] instead of CompanyFactListData
30
+ */
31
+ parseReportsFromRaw(reportsRaw: ReportRaw[]): ReportWrapper[];
32
+ /**
33
+ * Note that this includes all reports by default, not just annual and quarterly. use options.reportsToInclude to filter
34
+ *
35
+ * @see https://www.sec.gov/edgar/sec-api-documentation
36
+ */
37
+ parseReportsRaw(companyFactListData: Pick<CompanyFactListData, 'facts'>, options?: ParseReportsOptions): ReportRaw[];
38
+ /**
39
+ * Avoids deep nesting logic while iteratating through company facts
40
+ *
41
+ * @param callback called on each company fact.
42
+ */
43
+ iterateCompanyFacts(companyFactListData: Pick<CompanyFactListData, 'facts'>, callback: (data: IterateFactsCallbackData) => void): void;
44
+ /**
45
+ * Translate ReportRaw to ReportTranslated by default, but can be used to translate to any object using both the callback and keyTranslator
46
+ *
47
+ * @param reportsRaw this is the output of parseReportsRaw
48
+ * @param callback this is called for each report and can be used to modify the report. This gets the report built by keyTranslator if provided, otherwise ReportTranslated
49
+ * @param keyTranslator this is iterated through to build the report using the keys. If the ReportRaw has a key that matches a key in the keyTranslator, the value is used. if not, the value is null
50
+ */
51
+ translateReportsRaw<C extends TranslateRawReportsCallback<T>, T extends undefined | object = undefined>(reportsRaw: ReportRaw[], callback?: C, keyTranslator?: T): C extends unknown ? ReportTranslated[] : ReturnType<C>[];
52
+ }
53
+ export {};
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var key_translations_1 = require("../../util/key-translations");
4
+ var PropertyResolver_1 = require("./PropertyResolver");
5
+ var ReportRawParser_1 = require("./ReportRawParser");
6
+ var ReportWrapper_1 = require("./ReportWrapper");
7
+ /**
8
+ * Takes company facts data from the SEC and translates them to reports as json objects.
9
+ */
10
+ var ReportParser = /** @class */ (function () {
11
+ function ReportParser(args) {
12
+ var _a = args !== null && args !== void 0 ? args : {}, _b = _a.reportRawParser, reportRawParser = _b === void 0 ? new ReportRawParser_1.default() : _b, _c = _a.propertyResolver, propertyResolver = _c === void 0 ? new PropertyResolver_1.default() : _c, _d = _a.keyTranslator, keyTranslator = _d === void 0 ? key_translations_1.default : _d;
13
+ this.reportRawParser = reportRawParser;
14
+ this.keyTranslator = keyTranslator;
15
+ this.propertyResolver = propertyResolver;
16
+ }
17
+ /**
18
+ * translates company facts to ReportTranslated. To translate to custom report, use parseReportsRaw and translateReportsRaw
19
+ *
20
+ * This includes only 10-K and 10-Q annual and quarterly reports. To include all reports, use parseReportsRaw
21
+ *
22
+ * @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
23
+ */
24
+ ReportParser.prototype.parseReports = function (companyFactListData) {
25
+ var reportsRaw = this.reportRawParser.parseReports(companyFactListData, {
26
+ reportsToInclude: ['ANNUAL', 'QUARTERLY'],
27
+ });
28
+ return this.parseReportsFromRaw(reportsRaw);
29
+ };
30
+ /**
31
+ * Same as parseReports but accepts ReportRaw[] instead of CompanyFactListData
32
+ */
33
+ ReportParser.prototype.parseReportsFromRaw = function (reportsRaw) {
34
+ var reportByYearQuarter = new Map();
35
+ var reportsRawFiltered = reportsRaw.filter(function (reportRaw) {
36
+ return reportRaw.reportType === 'ANNUAL' || reportRaw.reportType === 'QUARTERLY';
37
+ });
38
+ this.translateReportsRaw(reportsRawFiltered, function (report, reportRaw) {
39
+ var fiscalPeriod = report.fiscalPeriod, fiscalYear = report.fiscalYear;
40
+ var keyReport = "".concat(fiscalYear, "_").concat(fiscalPeriod);
41
+ reportByYearQuarter.set(keyReport, new ReportWrapper_1.default(report, reportRaw, reportByYearQuarter));
42
+ return report;
43
+ });
44
+ var reportWrappers = Array.from(reportByYearQuarter.values());
45
+ this.propertyResolver.resolveAll(reportWrappers);
46
+ return reportWrappers;
47
+ };
48
+ /**
49
+ * Note that this includes all reports by default, not just annual and quarterly. use options.reportsToInclude to filter
50
+ *
51
+ * @see https://www.sec.gov/edgar/sec-api-documentation
52
+ */
53
+ ReportParser.prototype.parseReportsRaw = function (companyFactListData, options) {
54
+ return this.reportRawParser.parseReports(companyFactListData, options);
55
+ };
56
+ /**
57
+ * Avoids deep nesting logic while iteratating through company facts
58
+ *
59
+ * @param callback called on each company fact.
60
+ */
61
+ ReportParser.prototype.iterateCompanyFacts = function (companyFactListData, callback) {
62
+ this.reportRawParser.iterateCompanyFacts(companyFactListData, callback);
63
+ };
64
+ /**
65
+ * Translate ReportRaw to ReportTranslated by default, but can be used to translate to any object using both the callback and keyTranslator
66
+ *
67
+ * @param reportsRaw this is the output of parseReportsRaw
68
+ * @param callback this is called for each report and can be used to modify the report. This gets the report built by keyTranslator if provided, otherwise ReportTranslated
69
+ * @param keyTranslator this is iterated through to build the report using the keys. If the ReportRaw has a key that matches a key in the keyTranslator, the value is used. if not, the value is null
70
+ */
71
+ ReportParser.prototype.translateReportsRaw = function (reportsRaw, callback, keyTranslator) {
72
+ var keyTranslations = (keyTranslator !== null && keyTranslator !== void 0 ? keyTranslator : this.keyTranslator);
73
+ var reports = [];
74
+ reportsRaw.forEach(function (reportRaw) {
75
+ var reportNew = {};
76
+ // iterate translation keys, ensuring same order and priority
77
+ for (var key in keyTranslations) {
78
+ var keysRaw = keyTranslations[key];
79
+ reportNew[key] = null;
80
+ for (var _i = 0, keysRaw_1 = keysRaw; _i < keysRaw_1.length; _i++) {
81
+ var keyRaw = keysRaw_1[_i];
82
+ if (reportRaw[keyRaw] === undefined)
83
+ continue;
84
+ reportNew[key] = reportRaw[keyRaw];
85
+ break;
86
+ }
87
+ }
88
+ var reportFiltered = callback
89
+ ? callback(reportNew, reportRaw, keyTranslations)
90
+ : reportNew;
91
+ reports.push(reportFiltered);
92
+ });
93
+ return reports;
94
+ };
95
+ return ReportParser;
96
+ }());
97
+ exports.default = ReportParser;
@@ -0,0 +1,34 @@
1
+ import { CompanyFactListData } from '../../types/company-facts.type';
2
+ import { ReportRaw, ReportType } from '../../types/report-raw.type';
3
+ import FactIterator, { IterateFactsCallbackData } from './FactIterator';
4
+ interface ReportRawParserArgs {
5
+ factIterator?: FactIterator;
6
+ }
7
+ export interface ParseReportsOptions {
8
+ /**
9
+ * Instantaneous data may be filed later than the original filing date.
10
+ * It is flagged by "I" at the end of the frame property. defaults to true. see https://www.sec.gov/edgar/sec-api-documentation
11
+ * */
12
+ mergeInstantaneousData?: boolean;
13
+ reportsToInclude?: ReportType | ReportType[] | null;
14
+ }
15
+ /**
16
+ * @see https://www.sec.gov/edgar/sec-api-documentation
17
+ */
18
+ export default class ReportRawParser {
19
+ private readonly factIterator;
20
+ constructor(args?: ReportRawParserArgs);
21
+ /**
22
+ * Avoids deep nesting logic while iteratating through company facts
23
+ *
24
+ * @param callback called on each company fact.
25
+ */
26
+ iterateCompanyFacts(companyFactListData: Pick<CompanyFactListData, 'facts'>, callback: (data: IterateFactsCallbackData) => void): void;
27
+ /**
28
+ * Returns raw reports in ascending order by report date. if date is the same, priority is filed date, frame, form
29
+ */
30
+ parseReports(companyFactListData: Pick<CompanyFactListData, 'facts'>, options?: ParseReportsOptions): ReportRaw[];
31
+ private getReportType;
32
+ private getFiscalYear;
33
+ }
34
+ export {};
@@ -0,0 +1,154 @@
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
+ var FactIterator_1 = require("./FactIterator");
15
+ /**
16
+ * @see https://www.sec.gov/edgar/sec-api-documentation
17
+ */
18
+ var ReportRawParser = /** @class */ (function () {
19
+ function ReportRawParser(args) {
20
+ var _a = (args !== null && args !== void 0 ? args : {}).factIterator, factIterator = _a === void 0 ? new FactIterator_1.default() : _a;
21
+ this.factIterator = factIterator;
22
+ }
23
+ /**
24
+ * Avoids deep nesting logic while iteratating through company facts
25
+ *
26
+ * @param callback called on each company fact.
27
+ */
28
+ ReportRawParser.prototype.iterateCompanyFacts = function (companyFactListData, callback) {
29
+ this.factIterator.iterateCompanyFacts(companyFactListData, callback);
30
+ };
31
+ /**
32
+ * Returns raw reports in ascending order by report date. if date is the same, priority is filed date, frame, form
33
+ */
34
+ ReportRawParser.prototype.parseReports = function (companyFactListData, options) {
35
+ var _this = this;
36
+ var _a = options !== null && options !== void 0 ? options : {}, reportsToInclude = _a.reportsToInclude, mergeInstantaneousData = _a.mergeInstantaneousData;
37
+ // default to all report types
38
+ var reportsToIncludeSet = reportsToInclude
39
+ ? new Set(Array.isArray(reportsToInclude) ? reportsToInclude : [reportsToInclude])
40
+ : null;
41
+ // for getting the earliest filed date for each report
42
+ var datesFiledByDateForm = new Map();
43
+ // for mapping individual properties to the report
44
+ var reportsByKey = new Map();
45
+ // fiscal period only provided for filed date, used to map to later assign for quarter end date
46
+ var monthsFiledByFiscalPeriod = new Map();
47
+ // iterate individual properties AKA "facts"
48
+ this.iterateCompanyFacts(companyFactListData, function (_a) {
49
+ var _b, _c, _d, _e, _f, _g, _h;
50
+ var factValue = _a.factValue, propertyName = _a.propertyName, taxonomy = _a.taxonomy;
51
+ var filed = factValue.filed, val = factValue.val, form = factValue.form, fp = factValue.fp, dateReport = factValue.end;
52
+ // get frame for keys and to merge instantaneous data
53
+ var isInstantaneousData = (_c = (_b = factValue.frame) === null || _b === void 0 ? void 0 : _b.endsWith('I')) !== null && _c !== void 0 ? _c : false;
54
+ var isMergableFrame = (mergeInstantaneousData !== null && mergeInstantaneousData !== void 0 ? mergeInstantaneousData : true) && isInstantaneousData;
55
+ var frame = isMergableFrame ? (_d = factValue.frame) === null || _d === void 0 ? void 0 : _d.substring(0, factValue.frame.length - 1) : factValue.frame;
56
+ // keys to map report and file dates
57
+ var keyDateForm = "".concat(dateReport, "_").concat(form);
58
+ var keyReport = "".concat(frame, "_").concat(keyDateForm);
59
+ // set earliest date filed
60
+ var dateFiledPrev = (_e = datesFiledByDateForm.get(keyDateForm)) !== null && _e !== void 0 ? _e : filed;
61
+ var dateFiled = filed < dateFiledPrev ? filed : dateFiledPrev;
62
+ datesFiledByDateForm.set(keyDateForm, dateFiled);
63
+ // if frame is undefined, the value is no longer the most recent
64
+ if (!frame)
65
+ return;
66
+ var isTTM = frame.substring(6, 8).length !== 2;
67
+ var reportType = _this.getReportType({ form: form, taxonomy: taxonomy, isTTM: isTTM });
68
+ var isReportToInclude = (_f = reportsToIncludeSet === null || reportsToIncludeSet === void 0 ? void 0 : reportsToIncludeSet.has(reportType)) !== null && _f !== void 0 ? _f : true;
69
+ if (!isReportToInclude)
70
+ return;
71
+ // set the month filed, will be used to get the fiscal period and year
72
+ if (reportType === 'QUARTERLY' || reportType === 'ANNUAL') {
73
+ var monthFiled = Number(filed.substring(5, 7));
74
+ monthsFiledByFiscalPeriod.set(fp, ((_g = monthsFiledByFiscalPeriod.get(fp)) !== null && _g !== void 0 ? _g : new Set()).add(monthFiled));
75
+ }
76
+ var report = (_h = reportsByKey.get(keyReport)) !== null && _h !== void 0 ? _h : {
77
+ dateReport: dateReport,
78
+ dateFiled: dateFiled,
79
+ form: form,
80
+ isTTM: isTTM,
81
+ frame: frame,
82
+ taxonomy: taxonomy,
83
+ reportType: reportType,
84
+ // these will be updated
85
+ fiscalPeriod: 'FY',
86
+ fiscalYear: 0,
87
+ };
88
+ reportsByKey.set(keyReport, report);
89
+ // update earliest date filed
90
+ report.dateFiled = dateFiled;
91
+ report[propertyName] = val;
92
+ });
93
+ // end date is typically the month before the filed date, so subtract 1, set to 12 if 0
94
+ var fiscalPeriodsByMonth = new Map();
95
+ monthsFiledByFiscalPeriod.forEach(function (monthsSet, fiscalPeriod) {
96
+ monthsSet.forEach(function (month) { return fiscalPeriodsByMonth.set(month - 1 || 12, fiscalPeriod); });
97
+ });
98
+ // set fiscal period and year, then merge by year_quarter, because some reports have end dates a couple days apart
99
+ var reportsByYearPeriod = new Map();
100
+ reportsByKey.forEach(function (report) {
101
+ var _a;
102
+ var dateReport = report.dateReport, reportType = report.reportType;
103
+ var monthReport = Number(dateReport.substring(5, 7));
104
+ var fiscalPeriod = (_a = fiscalPeriodsByMonth.get(monthReport)) !== null && _a !== void 0 ? _a : 'FY';
105
+ // Q4 is always FY, so needs to be changed to Q4 (comes from fp property in fact)
106
+ report.fiscalPeriod = reportType === 'QUARTERLY' && fiscalPeriod === 'FY' ? 'Q4' : fiscalPeriod;
107
+ report.fiscalYear = _this.getFiscalYear({ dateReport: dateReport, reportType: reportType, fiscalPeriod: report.fiscalPeriod });
108
+ var keyReport = "".concat(report.fiscalYear, "_").concat(report.fiscalPeriod);
109
+ var reportPrev = reportsByYearPeriod.get(keyReport);
110
+ // if a report was already assigned to this key, merge and use the latest dateReport
111
+ if (reportPrev) {
112
+ var dateReport_1 = report.dateReport > reportPrev.dateReport ? report.dateReport : reportPrev.dateReport;
113
+ reportPrev.dateReport = dateReport_1;
114
+ reportsByYearPeriod.set(keyReport, __assign(__assign({}, reportPrev), report));
115
+ }
116
+ else {
117
+ reportsByYearPeriod.set(keyReport, report);
118
+ }
119
+ });
120
+ // return in ascending order by date report, date filed, frame, form
121
+ return Array.from(reportsByYearPeriod.values()).sort(function (a, b) {
122
+ var keyA = "".concat(a.fiscalYear, "_").concat(a.isTTM ? 'Q5' : a.fiscalPeriod, "_").concat(a.dateReport, "_").concat(a.dateFiled);
123
+ var keyB = "".concat(b.fiscalYear, "_").concat(b.isTTM ? 'Q5' : b.fiscalPeriod, "_").concat(b.dateReport, "_").concat(b.dateFiled);
124
+ return keyA > keyB ? 1 : -1;
125
+ });
126
+ };
127
+ ReportRawParser.prototype.getReportType = function (data) {
128
+ var form = data.form, taxonomy = data.taxonomy, isTTM = data.isTTM;
129
+ if (form === '8-K')
130
+ return '8K';
131
+ else if (taxonomy === 'dei')
132
+ return 'DOCUMENT_ENTITY_INFO';
133
+ else if (isTTM)
134
+ return 'ANNUAL';
135
+ return 'QUARTERLY';
136
+ };
137
+ ReportRawParser.prototype.getFiscalYear = function (data) {
138
+ var dateReport = data.dateReport, reportType = data.reportType, fiscalPeriod = data.fiscalPeriod;
139
+ var date = new Date("".concat(dateReport, "T00:00:00"));
140
+ var day = date.getDate();
141
+ var month = day < 14 ? date.getMonth() || 12 : date.getMonth() + 1;
142
+ var year = date.getFullYear();
143
+ var monthAddMap = {
144
+ Q1: 9,
145
+ Q2: 6,
146
+ Q3: 3,
147
+ Q4: 0,
148
+ FY: 0,
149
+ };
150
+ return month + monthAddMap[fiscalPeriod] > 12 && reportType === 'QUARTERLY' ? year + 1 : year;
151
+ };
152
+ return ReportRawParser;
153
+ }());
154
+ exports.default = ReportRawParser;
@@ -0,0 +1,9 @@
1
+ import { ReportTranslated } from '../../types';
2
+ type ExtendableReportProxy = {
3
+ new (report: ReportTranslated): ReportTranslated;
4
+ };
5
+ /**
6
+ * Used to make ReportWrapper implement ReportTranslated interface via proxy
7
+ */
8
+ declare const ReportTranslatedProxy: ExtendableReportProxy;
9
+ export default ReportTranslatedProxy;