UNPKG

sec-edgar-api

Version:

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

206 lines (205 loc) 9.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseInsiderTransactions = void 0; function parseTable(html) { var rows = html.split('<tr'); return rows .map(function (rowHtml) { return rowHtml .split('<td') .map(function (cellHtml) { return cellHtml.substring(cellHtml.indexOf('>') + 1, cellHtml.lastIndexOf('</td>')); }) .slice(1); }) .filter(function (row) { return row.length > 0; }); } function stripHtml(html) { return html .replace(/<.*?>/g, '') .replace(/&nbsp;/g, ' ') .replace(/\n/g, ' ') .replace(/\s+/, ' ') .trim(); } function toNumber(value) { return Number(value.replace(/,/g, '').trim()) || 0; } function parseInsiderTransactions(params) { var _a, _b, _c, _d; var xml = params.xml; var ownerTableHeadingIndex = xml.indexOf('sortid='); var transactionTableIdIndex = xml.indexOf('id="transaction-report"'); if (ownerTableHeadingIndex === -1) { throw new Error('Owner table heading not found in XML data'); } var ownerTableStartIndex = xml.lastIndexOf('<table', ownerTableHeadingIndex); var ownerTableEndIndex = xml.indexOf('</table>', ownerTableHeadingIndex) + 8; var ownerTableHtml = xml.substring(ownerTableStartIndex, ownerTableEndIndex); var transactionTableStartIndex = xml.lastIndexOf('<table', transactionTableIdIndex); var transactionTableEndIndex = xml.indexOf('</table>', transactionTableIdIndex) + 8; var transactionTableHtml = xml.substring(transactionTableStartIndex, transactionTableEndIndex); var issuerUrlIndex = xml.indexOf('cgi-bin/browse-edgar?action=getcompany'); var issuerUrlStartIndex = xml.lastIndexOf('<b>', issuerUrlIndex) + 3; var issuerUrlEndIndex = xml.indexOf('</b>', issuerUrlIndex); var issuerHtml = xml.substring(issuerUrlStartIndex, issuerUrlEndIndex).trim(); var issuerHtmlCikStart = issuerHtml.lastIndexOf('(') + 1; var issuerCik = toNumber(stripHtml(issuerHtml.substring(issuerHtmlCikStart, issuerHtml.lastIndexOf(')')))); var issuerName = issuerHtml.substring(0, issuerHtmlCikStart - 1).trim(); var headerOwner = ['owner_name', 'filings', 'transaction_date', 'type_of_owner']; var headerTransaction = [ 'acquisition_or_disposition', 'transaction_date', 'deemed_execution_date', 'reporting_owner', 'form', 'transaction_type', 'direct_or_indirect_ownership', 'num_securities_transacted', 'num_securities_following', 'line_number', 'owner_cik', 'security_title', ]; var ownerByCik = new Map(); var ownerRows = parseTable(ownerTableHtml); var transactionRows = parseTable(transactionTableHtml); var isSwitchedOwnerIssuer = stripHtml((_b = (_a = ownerRows[0]) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.toLowerCase()).includes('issuer') || false; for (var i = 1; i < ownerRows.length; i++) { var row = ownerRows[i]; // if (row.length === 0 || row[0].includes('Owner Name') || row[0].includes('Issuer')) continue // Skip header row var owner = { ownerName: '', ownerCik: 0, ownerPosition: null, isDirector: false, isOfficer: false, isTenPercentOwner: false, }; for (var i_1 = 0; i_1 < row.length; i_1++) { var colName = headerOwner[i_1]; var htmlStripped = stripHtml(row[i_1]); switch (colName) { case 'owner_name': owner.ownerName = htmlStripped.split('Current Name')[0]; break; case 'filings': owner.ownerCik = toNumber(htmlStripped); break; case 'type_of_owner': { var _e = htmlStripped.split(':').map(function (s) { return s.toLowerCase().trim(); }), ownerType = _e[0], _f = _e[1], position = _f === void 0 ? null : _f; owner.isDirector = ownerType.includes('director'); owner.isOfficer = ownerType.includes('officer'); owner.isTenPercentOwner = ownerType.includes('10 percent') || ownerType.includes('10%'); owner.ownerPosition = position; break; } } } ownerByCik.set(owner.ownerCik, owner); } var transactions = []; for (var _i = 0, transactionRows_1 = transactionRows; _i < transactionRows_1.length; _i++) { var row = transactionRows_1[_i]; if (row.length === 0 || row[0].includes('Acquisition or Dis')) continue; // Skip header row var transaction = { ownerName: '', ownerCik: 0, ownerPosition: null, issuerCik: issuerCik, issuerName: issuerName, isDirector: false, isOfficer: false, accessionNumber: '', deemedExecutionDate: '', form: '', /** true = buy, false = sell */ isAcquisition: false, isDirectOwnership: false, securityTitle: '', transactionDate: '', transactionCode: '', transactionShares: 0, sharesOwnedFollowingTransaction: 0, lineNumber: 0, isTenPercentOwner: false, }; for (var i = 0; i < row.length; i++) { var colName = headerTransaction[i]; var html = row[i]; var htmlStripped = stripHtml(html); switch (colName) { case 'acquisition_or_disposition': transaction.isAcquisition = String(htmlStripped).toLowerCase() === 'a'; break; case 'transaction_date': transaction.transactionDate = htmlStripped; break; case 'deemed_execution_date': transaction.deemedExecutionDate = htmlStripped; break; case 'reporting_owner': break; case 'form': { var url = (_d = (_c = html.match(/href="([^"]+)"/)) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : ''; transaction.accessionNumber = url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('-')); transaction.form = htmlStripped; break; } case 'transaction_type': transaction.transactionCode = htmlStripped.trim()[0]; break; case 'direct_or_indirect_ownership': transaction.isDirectOwnership = htmlStripped.toLowerCase().includes('d'); break; case 'num_securities_transacted': transaction.transactionShares = toNumber(htmlStripped) || 0; break; case 'num_securities_following': transaction.sharesOwnedFollowingTransaction = toNumber(htmlStripped); break; case 'line_number': transaction.lineNumber = toNumber(htmlStripped); break; case 'owner_cik': { var owner = ownerByCik.get(toNumber(htmlStripped) || 0); if (owner) { transaction.ownerName = owner.ownerName; transaction.ownerCik = owner.ownerCik; transaction.ownerPosition = owner.ownerPosition; transaction.isDirector = owner.isDirector; transaction.isOfficer = owner.isOfficer; transaction.isTenPercentOwner = owner.isTenPercentOwner; } break; } case 'security_title': transaction.securityTitle = htmlStripped; break; } } transactions.push(transaction); } var owners = Array.from(ownerByCik.values()); var issuers = [{ issuerName: issuerName, issuerCik: issuerCik }]; // if searching by person, owner and issuer data will be switched if (isSwitchedOwnerIssuer) { issuers = owners.map(function (owner) { return ({ issuerName: owner.ownerName, issuerCik: owner.ownerCik, }); }); owners = []; transactions.forEach(function (transaction) { var issuerName = transaction.issuerName, issuerCik = transaction.issuerCik, ownerName = transaction.ownerName, ownerCik = transaction.ownerCik; transaction.issuerCik = ownerCik; transaction.issuerName = ownerName; transaction.ownerCik = issuerCik; transaction.ownerName = issuerName; }); } return { transactions: transactions, owners: Array.from(ownerByCik.values()), issuers: issuers, }; } exports.parseInsiderTransactions = parseInsiderTransactions;