earningscall
Version:
The EarningsCall JavaScript library provides convenient access to the EarningsCall API. It includes a pre-defined set of classes for API resources that initialize themselves dynamically from API responses.
103 lines • 7.78 kB
JavaScript
import { getSymbolsV2 } from './api';
import { indexToIndustry, indexToSector } from './sectors';
// WARNING: Add new indexes to the *END* of this list
export const EXCHANGES_IN_ORDER = [
'NYSE',
'NASDAQ',
'AMEX',
'TSX',
'TSXV',
'OTC',
'LSE',
'CBOE',
'STO',
];
export function indexToExchange(index) {
if (index < 0 || index >= EXCHANGES_IN_ORDER.length) {
return 'UNKNOWN';
}
return EXCHANGES_IN_ORDER[index];
}
export class Symbols {
expiresDate = null;
lastModified = null;
cacheControlExpires = null;
exchanges = new Set();
byName = new Map();
byExchangeAndSym = new Map();
add = (companyInfo) => {
this.exchanges.add(companyInfo.exchange || '');
const exchangeSymbol = `${companyInfo.exchange}_${companyInfo.symbol}`;
this.byExchangeAndSym.set(exchangeSymbol, companyInfo);
this.byName.set(companyInfo.name || '', companyInfo);
};
getExchangeSymbol = (exchangeSymbol) => {
const symbol = this.byExchangeAndSym.get(exchangeSymbol.toUpperCase());
// if (!symbol) throw new Error(`Symbol not found: ${exchangeSymbol}`);
return symbol;
};
get = (exchange, symbol) => this.getExchangeSymbol(`${exchange}_${symbol}`);
getAll = function* () {
yield* this.byExchangeAndSym.values();
};
}
let symbols = null;
/**
* Loads the symbols from the API and returns a Symbols object.
*
* @returns {Promise<Symbols>} The Symbols object.
*/
export async function loadSymbols() {
const symbolsV2Response = await getSymbolsV2();
const responseHeaders = symbolsV2Response.headers;
const lastModified = new Date(responseHeaders.get('Last-Modified') || '');
const cacheControl = responseHeaders.get('Cache-Control');
const cacheControlMaxAge = cacheControl?.match(/max-age=(\d+)/)?.[1];
const cacheControlExpires = cacheControl?.match(/expires=(\d+)/)?.[1];
// By default, we cache the symbols for 1 day
// Otherwise, we use the Cache-Control header to determine the expiration date (max-age)
const expiresDate = new Date(Date.now() + parseInt(cacheControlMaxAge || '86400') * 1000);
const symbolsV2Text = await symbolsV2Response.text();
const symbols = new Symbols();
symbols.expiresDate = expiresDate;
symbols.lastModified = lastModified;
symbols.cacheControlExpires = cacheControlExpires || null;
symbolsV2Text
.split('\n')
.filter((line) => line.trim())
.forEach((line) => {
const [exchangeIndex, symbol, name, sectorIndex, industryIndex] = line.split('\t');
const companyInfo = {
exchange: indexToExchange(parseInt(exchangeIndex)),
symbol,
name,
sector: indexToSector(parseInt(sectorIndex)),
industry: indexToIndustry(parseInt(industryIndex)),
};
symbols.add(companyInfo);
});
return symbols;
}
/**
* Returns the symbols object. If the symbols object is not loaded, it will load it.
*
* @returns {Promise<Symbols>} The Symbols object.
*/
export async function getSymbols() {
if (!symbols) {
symbols = await loadSymbols();
}
if (symbols.expiresDate && symbols.expiresDate < new Date()) {
symbols = await loadSymbols();
}
return symbols;
}
/**
* Clears the symbols object.
*
* Forces a reload of the symbols from the API next time getSymbols is called.
*/
export function clearSymbols() {
symbols = null;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ltYm9scy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvc3ltYm9scy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBQ3JDLE9BQU8sRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRTNELHFEQUFxRDtBQUNyRCxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRztJQUNoQyxNQUFNO0lBQ04sUUFBUTtJQUNSLE1BQU07SUFDTixLQUFLO0lBQ0wsTUFBTTtJQUNOLEtBQUs7SUFDTCxLQUFLO0lBQ0wsTUFBTTtJQUNOLEtBQUs7Q0FDTixDQUFDO0FBRUYsTUFBTSxVQUFVLGVBQWUsQ0FBQyxLQUFhO0lBQzNDLElBQUksS0FBSyxHQUFHLENBQUMsSUFBSSxLQUFLLElBQUksa0JBQWtCLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDcEQsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUNELE9BQU8sa0JBQWtCLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDbkMsQ0FBQztBQUVELE1BQU0sT0FBTyxPQUFPO0lBQ2xCLFdBQVcsR0FBZ0IsSUFBSSxDQUFDO0lBQ2hDLFlBQVksR0FBZ0IsSUFBSSxDQUFDO0lBQ2pDLG1CQUFtQixHQUFrQixJQUFJLENBQUM7SUFFbEMsU0FBUyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDOUIsTUFBTSxHQUFHLElBQUksR0FBRyxFQUF1QixDQUFDO0lBQ3hDLGdCQUFnQixHQUFHLElBQUksR0FBRyxFQUF1QixDQUFDO0lBRTFELEdBQUcsR0FBRyxDQUFDLFdBQXdCLEVBQUUsRUFBRTtRQUNqQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQy9DLE1BQU0sY0FBYyxHQUFHLEdBQUcsV0FBVyxDQUFDLFFBQVEsSUFBSSxX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