def _companies( SIC_code, index: Optional[Index], company_identifiers, entire_universe=False, include_most_recent_filing_dates=False, NAICS_codes=None, ): if not (SIC_code or index or entire_universe or company_identifiers, NAICS_codes): raise ValueError( "Must supply SIC_code, NAICS_codes, index or company_identifiers or entire_univers." ) payload = {} if index: if index not in ("SP500", "DJIA"): raise ValueError("index must be either 'SP500' or 'DJIA'") payload["index"] = index elif SIC_code: payload["SICCodes"] = SIC_code elif NAICS_codes: payload["NAICSCodes"] = NAICS_codes elif company_identifiers: payload["companyIdentifiers"] = company_identifiers else: payload["universe"] = True payload["includeMostRecentFilingExtras"] = include_most_recent_filing_dates return _json_POST("companies", payload)
def _document_search_results(payload, progress_bar=None): results = {"moreResults": True} while results["moreResults"]: results = _json_POST("footnoteSearch", payload) disclosures = results["footnotes"] if progress_bar is not None: progress_bar.update(len(disclosures)) for result in disclosures: yield DocumentSearchResults(**result) payload["pageParameters"]["startOffset"] = results[ "nextGroupStartOffset"] payload["pageParameters"]["startOffset"] = None
def filings( company_identifiers: CompanyIdentifiers = [], entire_universe: bool = False, include_non_xbrl: bool = True, received_date: date = None, start_date: date = None, end_date: date = None, filing_types=[], ) -> Iterable[Filing]: """SEC filings https://www.calcbench.com/filings :param company_identifiers: list of tickers or CIK codes :param received_date: get all filings received on this date :param entire_universe: filings for all companies :param include_non_xbrl: include filings that do not have XBRL, 8-Ks, earnings releases etc. :param received_data: only filings published on this date :param start_date: filings received on or after this date :param end_date: filings received on or before theis date Usage:: >>> from datetime import date >>> calcbench.filings(received_date=date.today(), entire_universe=True) """ filings = _json_POST( "filingsV2", { "companiesParameters": { "companyIdentifiers": list(company_identifiers), "entireUniverse": entire_universe, }, "pageParameters": { "includeNonXBRL": include_non_xbrl, "filingTypes": filing_types, }, "periodParameters": { "updateDate": received_date and received_date.isoformat(), "dateRange": start_date and end_date and { "startDate": start_date.isoformat(), "endDate": end_date.isoformat(), }, "asOriginallyReported": False, }, }, ) for filing in filings: yield Filing(**filing)
def normalized_raw( company_identifiers: CompanyIdentifiers = [], metrics: Iterable[ str ] = [], # type str[] Full list of metrics is @ https://www.calcbench.com/home/standardizedmetrics start_year: int = None, start_period: PeriodArgument = None, end_year: int = None, end_period: PeriodArgument = None, entire_universe=False, accession_id: int = None, point_in_time: bool = False, include_trace: bool = False, update_date: date = None, all_history=False, year: int = None, period: PeriodArgument = None, period_type: PeriodType = None, include_preliminary: bool = False, use_fiscal_period: bool = False, ): """ Standardized data. Get normalized data from Calcbench. Each point is normalized by economic concept and time period. Args: company_identifiers: a sequence of tickers (or CIK codes), eg ['msft', 'goog', 'appl'] metrics: a sequence of metrics, see the full list @ https://www.calcbench.com/home/standardizedmetrics eg. ['revenue', 'accountsreceivable'] start_year: first year of data start_period: first quarter to get, for annual data pass 0, for quarters pass 1, 2, 3, 4 end_year: last year of data end_period: last_quarter to get, for annual data pass 0, for quarters pass 1, 2, 3, 4 entire_universe: Get data for all companies, this can take a while, talk to Calcbench before you do this in production. accession_id: Calcbench Accession ID include_trace: Include the facts used to calculate the normalized value. year: Get data for a single year, defaults to annual data. period_type: Either "annual" or "quarterly" include_preliminary: Include data from non-XBRL 8-Ks and press releases. Returns: A list of dictionaries with keys ['ticker', 'calendar_year', 'calendar_period', 'metric', 'value']. For example [ { "ticker": "MSFT", "calendar_year": 2010, "calendar_period": 1, "metric": "revenue", "value": 14503000000 }, { "ticker": "MSFT", "calendar_year": 2010, "calendar_period": 2, "metric": "revenue", "value": 16039000000 }, ] """ if [ bool(company_identifiers), bool(entire_universe), bool(accession_id), ].count(True) != 1: raise ValueError( "Must pass either company_identifiers and accession id or entire_universe=True" ) if accession_id and any( [ company_identifiers, start_year, start_period, end_year, end_period, entire_universe, year, period, ] ): raise ValueError( "Accession IDs are specific to a filing, no other qualifiers make sense." ) if period is not None: if start_period or end_period: raise ValueError( "Use period for a single period. start_period and end_period are for ranges." ) if period not in ("Y", 0) and (start_year or end_year): raise ValueError("With start_year or end_year only annual period works") start_period = end_period = period if year: if start_year or end_year: raise ValueError( "Use year for a single period. start_year and end_year for ranges." ) start_year = end_year = year if period_type and period_type not in ("annual", "quarterly"): raise ValueError('period_type must be either "annual" or "quarterly"') if include_preliminary and not point_in_time: raise ValueError("include_preliminary only works for PIT") try: start_year = int(start_year) # type: ignore except (ValueError, TypeError): pass try: start_period = int(start_period) # type: ignore except (ValueError, TypeError): pass try: end_year = int(end_year) # type: ignore except (ValueError, TypeError): pass try: end_period = int(end_period) # type: ignore except (ValueError, TypeError): pass payload = { "pageParameters": { "metrics": metrics, "includeTrace": include_trace, "pointInTime": point_in_time, "includePreliminary": include_preliminary, }, "periodParameters": { "year": start_year, "period": start_period, "endYear": end_year, "endPeriod": end_period, "allHistory": all_history, "updateDate": update_date and update_date.isoformat(), "periodType": period_type, "useFiscalPeriod": use_fiscal_period, "accessionID": accession_id, }, "companiesParameters": { "entireUniverse": entire_universe, "companyIdentifiers": list(company_identifiers), }, } return _json_POST("mappedData", payload)
def mapped_raw( company_identifiers=[], all_footnotes=False, point_in_time=False, update_date=None, metrics=[], all_history=False, entire_universe=False, start_year=None, end_year=None, start_period=None, end_period=None, period_type=None, use_fiscal_period=False, include_preliminary=False, all_face=False, include_xbrl=True, accession_id=None, include_trace=False, ): """ Only called by point in time """ if update_date: warnings.warn( "Request updates by accession_id rather than update date", DeprecationWarning, ) if accession_id and update_date: raise ValueError("Specifying accession_id and update_date is redundant.") payload = { "companiesParameters": { "companyIdentifiers": list(company_identifiers), "entireUniverse": entire_universe, }, "pageParameters": { "pointInTime": point_in_time, "allFootnotes": all_footnotes, "allface": all_face, "metrics": metrics, "includePreliminary": include_preliminary, "includeTrace": include_trace, }, } period_parameters = { "allHistory": all_history, "year": start_year, "endYear": end_year, "period": start_period, "endPeriod": end_period, "periodType": period_type, "useFiscalPeriod": use_fiscal_period, "includeXBRL": include_xbrl, "accessionID": accession_id, } if update_date: period_parameters["updateDate"] = update_date.isoformat() payload["periodParameters"] = period_parameters return _json_POST("mappedData", payload)