From 06e38834d067a5e32d8596f8980a636cd7df9e86 Mon Sep 17 00:00:00 2001 From: Danglewood <85772166+deeleeramone@users.noreply.github.com> Date: Tue, 19 Dec 2023 04:26:13 -0800 Subject: [PATCH] feature/financials - PR for working on structure of financial statements. (#5794) * balance sheet draft * balance_sheet draft * cash_flow draft * income_statement draft * intrinio financials * description * period field * ruff * income statement * field * label - gross profit ratio * cash flow statement * investing order * add option for caching to cashflow * add caching to balance and income * typos and update order for financial institutions * replace 0 values with None * add financial ratios from intrinio * black * missing test params * balance cassette * query param description * symbol list warning * black * handle BRK-A and symbols with a dash for Intrinio * fix typo error * add free cash flow to bottom of cash flow statement * amortization_expense * dev_install.py * undo dev_install.. wrong branch * cash flow order things * standardized cash flow * fields * integration tests * cash flow model validator * more polygon cash * black * black * Delete openbb_sdk/providers/polygon/openbb_polygon/utils/definitions.py wrong file * balance sheet * some cleanup * ruff * income statement * black * test params * financial ratios async update * recapture fmp and polygon tests * yFinance financials * yfinance tests * delete financial_statements standard model * intrinio balance sheet order * fiscal year standard param * remove file accidentally committed * add reported_financials end point * fiscal_year param for reported_financials * fix url * fmp test cassette * add safe-guard with warning for fiscal year before 2008 * periods can only be annual and quarter * url in docstring correction * add fiscal_year param to intrinio standardized financials and ratios * fix fmp ratios * black * rename fields as per Minh * rogue field * black * Fix typo in a docstring * Resolve linting errors * type ignore * disable=unused-argument * changing the arg name cc @minhhoang1023 --------- Co-authored-by: Igor Radovanovic <74266147+IgorWounds@users.noreply.github.com> Co-authored-by: Theodore Aptekarev Co-authored-by: hjoaquim --- .../provider/standard_models/balance_sheet.py | 173 +------- .../provider/standard_models/cash_flow.py | 129 +----- .../standard_models/financial_ratios.py | 175 +------- .../standard_models/income_statement.py | 138 +----- .../standard_models/reported_financials.py | 66 +++ .../provider/utils/descriptions.py | 2 + .../equity/integration/test_equity_api.py | 78 +++- .../equity/integration/test_equity_python.py | 73 ++- .../fundamental/fundamental_router.py | 11 + .../fmp/openbb_fmp/models/balance_sheet.py | 129 +++--- .../fmp/openbb_fmp/models/cash_flow.py | 109 ++--- .../fmp/openbb_fmp/models/financial_ratios.py | 226 ++++++++-- .../fmp/openbb_fmp/models/income_statement.py | 133 ++---- .../test_fmp_balance_sheet_fetcher.yaml | 74 ++-- .../test_fmp_cash_flow_statement_fetcher.yaml | 68 +-- .../test_fmp_income_statement_fetcher.yaml | 66 +-- .../intrinio/openbb_intrinio/__init__.py | 4 + .../openbb_intrinio/models/balance_sheet.py | 417 +++++++++++++++--- .../openbb_intrinio/models/cash_flow.py | 270 +++++++++--- .../models/financial_ratios.py | 315 +++++++++++++ .../models/income_statement.py | 401 ++++++++++++++--- .../models/reported_financials.py | 142 ++++++ .../intrinio/openbb_intrinio/utils/helpers.py | 15 +- .../test_intrinio_balance_sheet_fetcher.yaml | 2 +- ...est_intrinio_financial_ratios_fetcher.yaml | 241 ++++++++++ ..._intrinio_reported_financials_fetcher.yaml | 128 ++++++ .../intrinio/tests/test_intrinio_fetchers.py | 25 ++ .../openbb_polygon/models/balance_sheet.py | 129 ++++-- .../openbb_polygon/models/cash_flow.py | 101 +++-- .../openbb_polygon/models/income_statement.py | 173 ++++++-- .../test_polygon_balance_sheet_fetcher.yaml | 295 +++++++++---- ...t_polygon_cash_flow_statement_fetcher.yaml | 158 +++---- ...test_polygon_income_statement_fetcher.yaml | 158 +++---- .../openbb_yfinance/models/balance_sheet.py | 34 +- .../openbb_yfinance/models/cash_flow.py | 31 +- .../models/income_statement.py | 39 +- .../test_y_finance_balance_sheet_fetcher.yaml | 330 ++++++++++---- ...y_finance_cash_flow_statement_fetcher.yaml | 301 +++++++++---- 38 files changed, 3706 insertions(+), 1653 deletions(-) create mode 100644 openbb_platform/core/openbb_core/provider/standard_models/reported_financials.py create mode 100644 openbb_platform/providers/intrinio/openbb_intrinio/models/financial_ratios.py create mode 100644 openbb_platform/providers/intrinio/openbb_intrinio/models/reported_financials.py create mode 100644 openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_financial_ratios_fetcher.yaml create mode 100644 openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_reported_financials_fetcher.yaml diff --git a/openbb_platform/core/openbb_core/provider/standard_models/balance_sheet.py b/openbb_platform/core/openbb_core/provider/standard_models/balance_sheet.py index 0b8832bcca9..80ef5c30d3a 100644 --- a/openbb_platform/core/openbb_core/provider/standard_models/balance_sheet.py +++ b/openbb_platform/core/openbb_core/provider/standard_models/balance_sheet.py @@ -1,27 +1,25 @@ """Balance Sheet Standard Model.""" +import warnings +from datetime import date as dateType +from typing import Optional -from datetime import ( - date as dateType, - datetime, -) -from typing import List, Literal, Optional, Set, Union - -from pydantic import Field, NonNegativeInt, StrictFloat, field_validator +from pydantic import Field, NonNegativeInt, field_validator from openbb_core.provider.abstract.data import Data from openbb_core.provider.abstract.query_params import QueryParams from openbb_core.provider.utils.descriptions import ( - DATA_DESCRIPTIONS, QUERY_DESCRIPTIONS, ) +_warn = warnings.warn + class BalanceSheetQueryParams(QueryParams): """Balance Sheet Query.""" symbol: str = Field(description=QUERY_DESCRIPTIONS.get("symbol", "")) - period: Optional[Literal["annual", "quarter"]] = Field( + period: str = Field( default="annual", description=QUERY_DESCRIPTIONS.get("period", ""), ) @@ -31,159 +29,22 @@ class BalanceSheetQueryParams(QueryParams): @field_validator("symbol", mode="before", check_fields=False) @classmethod - def upper_symbol(cls, v: Union[str, List[str], Set[str]]): + def upper_symbol(cls, v: str): """Convert symbol to uppercase.""" + if "," in v: + _warn( + f"{QUERY_DESCRIPTIONS.get('symbol_list_warning', '')} {v.split(',')[0].upper()}" + ) return v.split(",")[0].upper() if "," in v else v.upper() class BalanceSheetData(Data): """Balance Sheet Data.""" - symbol: Optional[str] = Field( - default=None, description=DATA_DESCRIPTIONS.get("symbol", "") + period_ending: dateType = Field(description="The end date of the reporting period.") + fiscal_period: Optional[str] = Field( + description="The fiscal period of the report.", default=None ) - date: dateType = Field(description=DATA_DESCRIPTIONS.get("date", "")) - cik: Optional[str] = Field( - default=None, - description=DATA_DESCRIPTIONS.get("cik", ""), + fiscal_year: Optional[int] = Field( + description="The fiscal year of the fiscal period.", default=None ) - currency: Optional[str] = Field(default=None, description="Reporting currency.") - filling_date: Optional[dateType] = Field(default=None, description="Filling date.") - accepted_date: Optional[datetime] = Field( - default=None, description="Accepted date." - ) - period: Optional[str] = Field( - default=None, description="Reporting period of the statement." - ) - - cash_and_cash_equivalents: Optional[StrictFloat] = Field( - default=None, description="Cash and cash equivalents" - ) - short_term_investments: Optional[StrictFloat] = Field( - default=None, description="Short-term investments" - ) - long_term_investments: Optional[StrictFloat] = Field( - default=None, description="Long-term investments" - ) - - inventory: Optional[StrictFloat] = Field(default=None, description="Inventory") - net_receivables: Optional[StrictFloat] = Field( - default=None, description="Receivables, net" - ) - - marketable_securities: Optional[StrictFloat] = Field( - default=None, description="Marketable securities" - ) - property_plant_equipment_net: Optional[StrictFloat] = Field( - default=None, description="Property, plant and equipment, net" - ) - goodwill: Optional[StrictFloat] = Field(default=None, description="Goodwill") - - assets: Optional[StrictFloat] = Field(default=None, description="Total assets") - current_assets: Optional[StrictFloat] = Field( - default=None, description="Total current assets" - ) - other_current_assets: Optional[StrictFloat] = Field( - default=None, description="Other current assets" - ) - intangible_assets: Optional[StrictFloat] = Field( - default=None, description="Intangible assets" - ) - tax_assets: Optional[StrictFloat] = Field( - default=None, description="Accrued income taxes" - ) - non_current_assets: Optional[StrictFloat] = Field( - default=None, description="Total non-current assets" - ) - other_non_current_assets: Optional[StrictFloat] = Field( - default=None, description="Other non-current assets" - ) - - account_payables: Optional[StrictFloat] = Field( - default=None, description="Accounts payable" - ) - tax_payables: Optional[StrictFloat] = Field( - default=None, description="Accrued income taxes" - ) - deferred_revenue: Optional[StrictFloat] = Field( - default=None, description="Accrued income taxes, other deferred revenue" - ) - other_assets: Optional[StrictFloat] = Field( - default=None, description="Other assets" - ) - total_assets: Optional[StrictFloat] = Field( - default=None, description="Total assets" - ) - - long_term_debt: Optional[StrictFloat] = Field( - default=None, - description="Long-term debt, Operating lease obligations, Long-term finance lease obligations", - ) - short_term_debt: Optional[StrictFloat] = Field( - default=None, - description="Short-term borrowings, Long-term debt due within one year, " - "Operating lease obligations due within one year, " - "Finance lease obligations due within one year", - ) - - liabilities: Optional[StrictFloat] = Field( - default=None, description="Total liabilities" - ) - other_current_liabilities: Optional[StrictFloat] = Field( - default=None, description="Other current liabilities" - ) - current_liabilities: Optional[StrictFloat] = Field( - default=None, description="Total current liabilities" - ) - total_liabilities_and_total_equity: Optional[StrictFloat] = Field( - default=None, description="Total liabilities and total equity" - ) - other_non_current_liabilities: Optional[StrictFloat] = Field( - default=None, description="Other non-current liabilities" - ) - non_current_liabilities: Optional[StrictFloat] = Field( - default=None, description="Total non-current liabilities" - ) - total_liabilities_and_stockholders_equity: Optional[StrictFloat] = Field( - default=None, description="Total liabilities and stockholders' equity" - ) - other_stockholder_equity: Optional[StrictFloat] = Field( - default=None, description="Other stockholders equity" - ) - total_stockholders_equity: Optional[StrictFloat] = Field( - default=None, description="Total stockholders' equity" - ) - other_liabilities: Optional[StrictFloat] = Field( - default=None, description="Other liabilities" - ) - total_liabilities: Optional[StrictFloat] = Field( - default=None, description="Total liabilities" - ) - - common_stock: Optional[StrictFloat] = Field( - default=None, description="Common stock" - ) - preferred_stock: Optional[StrictFloat] = Field( - default=None, description="Preferred stock" - ) - - accumulated_other_comprehensive_income_loss: Optional[StrictFloat] = Field( - default=None, description="Accumulated other comprehensive income (loss)" - ) - retained_earnings: Optional[StrictFloat] = Field( - default=None, description="Retained earnings" - ) - minority_interest: Optional[StrictFloat] = Field( - default=None, description="Minority interest" - ) - total_equity: Optional[StrictFloat] = Field( - default=None, description="Total equity" - ) - - @field_validator("symbol", mode="before", check_fields=False) - @classmethod - def upper_symbol(cls, v: Union[str, List[str], Set[str]]): - """Convert symbol to uppercase.""" - if isinstance(v, str): - return v.upper() - return ",".join([symbol.upper() for symbol in list(v)]) if v else None diff --git a/openbb_platform/core/openbb_core/provider/standard_models/cash_flow.py b/openbb_platform/core/openbb_core/provider/standard_models/cash_flow.py index 3a2f4bc1ae4..8e7cc2b40a4 100644 --- a/openbb_platform/core/openbb_core/provider/standard_models/cash_flow.py +++ b/openbb_platform/core/openbb_core/provider/standard_models/cash_flow.py @@ -1,24 +1,23 @@ """Cash Flow Statement Standard Model.""" - +import warnings from datetime import date as dateType -from typing import List, Literal, Optional, Set, Union +from typing import Optional -from pydantic import Field, NonNegativeInt, StrictFloat, field_validator +from pydantic import Field, NonNegativeInt, field_validator from openbb_core.provider.abstract.data import Data from openbb_core.provider.abstract.query_params import QueryParams -from openbb_core.provider.utils.descriptions import ( - DATA_DESCRIPTIONS, - QUERY_DESCRIPTIONS, -) +from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS + +_warn = warnings.warn class CashFlowStatementQueryParams(QueryParams): """Cash Flow Statement Query.""" symbol: str = Field(description=QUERY_DESCRIPTIONS.get("symbol", "")) - period: Optional[Literal["annual", "quarter"]] = Field( + period: str = Field( default="annual", description=QUERY_DESCRIPTIONS.get("period", ""), ) @@ -28,116 +27,22 @@ class CashFlowStatementQueryParams(QueryParams): @field_validator("symbol", mode="before", check_fields=False) @classmethod - def upper_symbol(cls, v: Union[str, List[str], Set[str]]): + def upper_symbol(cls, v: str): """Convert symbol to uppercase.""" + if "," in v: + _warn( + f"{QUERY_DESCRIPTIONS.get('symbol_list_warning', '')} {v.split(',')[0].upper()}" + ) return v.split(",")[0].upper() if "," in v else v.upper() class CashFlowStatementData(Data): """Cash Flow Statement Data.""" - symbol: Optional[str] = Field( - default=None, description=DATA_DESCRIPTIONS.get("symbol", "") + period_ending: dateType = Field(description="The end date of the reporting period.") + fiscal_period: Optional[str] = Field( + description="The fiscal period of the report.", default=None ) - date: dateType = Field(description=DATA_DESCRIPTIONS.get("date" "")) - period: Optional[str] = Field( - default=None, description="Reporting period of the statement." + fiscal_year: Optional[int] = Field( + description="The fiscal year of the fiscal period.", default=None ) - cik: Optional[str] = Field( - default=None, - description=DATA_DESCRIPTIONS.get("cik", ""), - ) - - net_income: Optional[StrictFloat] = Field(default=None, description="Net income.") - - depreciation_and_amortization: Optional[StrictFloat] = Field( - default=None, description="Depreciation and amortization." - ) - stock_based_compensation: Optional[StrictFloat] = Field( - default=None, description="Stock based compensation." - ) - deferred_income_tax: Optional[StrictFloat] = Field( - default=None, description="Deferred income tax." - ) - other_non_cash_items: Optional[StrictFloat] = Field( - default=None, description="Other non-cash items." - ) - changes_in_operating_assets_and_liabilities: Optional[StrictFloat] = Field( - default=None, description="Changes in operating assets and liabilities." - ) - - accounts_receivables: Optional[StrictFloat] = Field( - default=None, description="Accounts receivables." - ) - inventory: Optional[StrictFloat] = Field(default=None, description="Inventory.") - vendor_non_trade_receivables: Optional[StrictFloat] = Field( - default=None, description="Vendor non-trade receivables." - ) - other_current_and_non_current_assets: Optional[StrictFloat] = Field( - default=None, description="Other current and non-current assets." - ) - accounts_payables: Optional[StrictFloat] = Field( - default=None, description="Accounts payables." - ) - deferred_revenue: Optional[StrictFloat] = Field( - default=None, description="Deferred revenue." - ) - other_current_and_non_current_liabilities: Optional[StrictFloat] = Field( - default=None, description="Other current and non-current liabilities." - ) - net_cash_flow_from_operating_activities: Optional[StrictFloat] = Field( - default=None, description="Net cash flow from operating activities." - ) - - purchases_of_marketable_securities: Optional[StrictFloat] = Field( - default=None, description="Purchases of investments." - ) - sales_from_maturities_of_investments: Optional[StrictFloat] = Field( - default=None, description="Sales and maturities of investments." - ) - investments_in_property_plant_and_equipment: Optional[StrictFloat] = Field( - default=None, description="Investments in property, plant, and equipment." - ) - payments_from_acquisitions: Optional[StrictFloat] = Field( - default=None, description="Acquisitions, net of cash acquired, and other" - ) - other_investing_activities: Optional[StrictFloat] = Field( - default=None, description="Other investing activities" - ) - net_cash_flow_from_investing_activities: Optional[StrictFloat] = Field( - default=None, description="Net cash used for investing activities." - ) - - taxes_paid_on_net_share_settlement: Optional[StrictFloat] = Field( - default=None, description="Taxes paid on net share settlement of equity awards." - ) - dividends_paid: Optional[StrictFloat] = Field( - default=None, description="Payments for dividends and dividend equivalents" - ) - common_stock_repurchased: Optional[StrictFloat] = Field( - default=None, description="Payments related to repurchase of common stock" - ) - debt_proceeds: Optional[StrictFloat] = Field( - default=None, description="Proceeds from issuance of term debt" - ) - debt_repayment: Optional[StrictFloat] = Field( - default=None, description="Payments of long-term debt" - ) - other_financing_activities: Optional[StrictFloat] = Field( - default=None, description="Other financing activities, net" - ) - net_cash_flow_from_financing_activities: Optional[StrictFloat] = Field( - default=None, description="Net cash flow from financing activities." - ) - net_change_in_cash: Optional[StrictFloat] = Field( - default=None, - description="Net increase (decrease) in cash, cash equivalents, and restricted cash", - ) - - @field_validator("symbol", mode="before", check_fields=False) - @classmethod - def upper_symbol(cls, v: Union[str, List[str], Set[str]]): - """Convert symbol to uppercase.""" - if isinstance(v, str): - return v.upper() - return ",".join([symbol.upper() for symbol in list(v)]) if v else None diff --git a/openbb_platform/core/openbb_core/provider/standard_models/financial_ratios.py b/openbb_platform/core/openbb_core/provider/standard_models/financial_ratios.py index f8ee01ab31d..e34210ba489 100644 --- a/openbb_platform/core/openbb_core/provider/standard_models/financial_ratios.py +++ b/openbb_platform/core/openbb_core/provider/standard_models/financial_ratios.py @@ -1,7 +1,7 @@ """Financial Ratios Standard Model.""" - -from typing import List, Literal, Optional, Set, Union +import warnings +from typing import Optional from pydantic import Field, NonNegativeInt, field_validator @@ -12,12 +12,14 @@ from openbb_core.provider.utils.descriptions import ( QUERY_DESCRIPTIONS, ) +_warn = warnings.warn + class FinancialRatiosQueryParams(QueryParams): """Financial Ratios Query.""" symbol: str = Field(description=QUERY_DESCRIPTIONS.get("symbol", "")) - period: Literal["annual", "quarter"] = Field( + period: str = Field( default="annual", description=QUERY_DESCRIPTIONS.get("period", "") ) limit: NonNegativeInt = Field( @@ -25,166 +27,19 @@ class FinancialRatiosQueryParams(QueryParams): ) @field_validator("symbol", mode="before", check_fields=False) - def upper_symbol(cls, v: Union[str, List[str], Set[str]]): + @classmethod + def upper_symbol(cls, v: str): """Convert symbol to uppercase.""" - if isinstance(v, str): - return v.upper() - return ",".join([symbol.upper() for symbol in list(v)]) + if "," in v: + _warn( + f"{QUERY_DESCRIPTIONS.get('symbol_list_warning', '')} {v.split(',')[0].upper()}" + ) + return v.split(",")[0].upper() if "," in v else v.upper() class FinancialRatiosData(Data): """Financial Ratios Standard Model.""" - symbol: str = Field(description=DATA_DESCRIPTIONS.get("symbol", "")) - date: str = Field(description=DATA_DESCRIPTIONS.get("date", "")) - period: str = Field(description="Period of the financial ratios.") - current_ratio: Optional[float] = Field(default=None, description="Current ratio.") - quick_ratio: Optional[float] = Field(default=None, description="Quick ratio.") - cash_ratio: Optional[float] = Field(default=None, description="Cash ratio.") - days_of_sales_outstanding: Optional[float] = Field( - default=None, description="Days of sales outstanding." - ) - days_of_inventory_outstanding: Optional[float] = Field( - default=None, description="Days of inventory outstanding." - ) - operating_cycle: Optional[float] = Field( - default=None, description="Operating cycle." - ) - days_of_payables_outstanding: Optional[float] = Field( - default=None, description="Days of payables outstanding." - ) - cash_conversion_cycle: Optional[float] = Field( - default=None, description="Cash conversion cycle." - ) - gross_profit_margin: Optional[float] = Field( - default=None, description="Gross profit margin." - ) - operating_profit_margin: Optional[float] = Field( - default=None, description="Operating profit margin." - ) - pretax_profit_margin: Optional[float] = Field( - default=None, description="Pretax profit margin." - ) - net_profit_margin: Optional[float] = Field( - default=None, description="Net profit margin." - ) - effective_tax_rate: Optional[float] = Field( - default=None, description="Effective tax rate." - ) - return_on_assets: Optional[float] = Field( - default=None, description="Return on assets." - ) - return_on_equity: Optional[float] = Field( - default=None, description="Return on equity." - ) - return_on_capital_employed: Optional[float] = Field( - default=None, description="Return on capital employed." - ) - net_income_per_ebt: Optional[float] = Field( - default=None, description="Net income per EBT." - ) - ebt_per_ebit: Optional[float] = Field(default=None, description="EBT per EBIT.") - ebit_per_revenue: Optional[float] = Field( - default=None, description="EBIT per revenue." - ) - debt_ratio: Optional[float] = Field(default=None, description="Debt ratio.") - debt_equity_ratio: Optional[float] = Field( - default=None, description="Debt equity ratio." - ) - long_term_debt_to_capitalization: Optional[float] = Field( - default=None, description="Long term debt to capitalization." - ) - total_debt_to_capitalization: Optional[float] = Field( - default=None, description="Total debt to capitalization." - ) - interest_coverage: Optional[float] = Field( - default=None, description="Interest coverage." - ) - cash_flow_to_debt_ratio: Optional[float] = Field( - default=None, description="Cash flow to debt ratio." - ) - company_equity_multiplier: Optional[float] = Field( - default=None, description="Company equity multiplier." - ) - receivables_turnover: Optional[float] = Field( - default=None, description="Receivables turnover." - ) - payables_turnover: Optional[float] = Field( - default=None, description="Payables turnover." - ) - inventory_turnover: Optional[float] = Field( - default=None, description="Inventory turnover." - ) - fixed_asset_turnover: Optional[float] = Field( - default=None, description="Fixed asset turnover." - ) - asset_turnover: Optional[float] = Field(default=None, description="Asset turnover.") - operating_cash_flow_per_share: Optional[float] = Field( - default=None, description="Operating cash flow per share." - ) - free_cash_flow_per_share: Optional[float] = Field( - default=None, description="Free cash flow per share." - ) - cash_per_share: Optional[float] = Field(default=None, description="Cash per share.") - payout_ratio: Optional[float] = Field(default=None, description="Payout ratio.") - operating_cash_flow_sales_ratio: Optional[float] = Field( - default=None, description="Operating cash flow sales ratio." - ) - free_cash_flow_operating_cash_flow_ratio: Optional[float] = Field( - default=None, description="Free cash flow operating cash flow ratio." - ) - cash_flow_coverage_ratios: Optional[float] = Field( - default=None, description="Cash flow coverage ratios." - ) - short_term_coverage_ratios: Optional[float] = Field( - default=None, description="Short term coverage ratios." - ) - capital_expenditure_coverage_ratio: Optional[float] = Field( - default=None, description="Capital expenditure coverage ratio." - ) - dividend_paid_and_capex_coverage_ratio: Optional[float] = Field( - default=None, description="Dividend paid and capex coverage ratio." - ) - dividend_payout_ratio: Optional[float] = Field( - default=None, description="Dividend payout ratio." - ) - price_book_value_ratio: Optional[float] = Field( - default=None, description="Price book value ratio." - ) - price_to_book_ratio: Optional[float] = Field( - default=None, description="Price to book ratio." - ) - price_to_sales_ratio: Optional[float] = Field( - default=None, description="Price to sales ratio." - ) - price_earnings_ratio: Optional[float] = Field( - default=None, description="Price earnings ratio." - ) - price_to_free_cash_flows_ratio: Optional[float] = Field( - default=None, description="Price to free cash flows ratio." - ) - price_to_operating_cash_flows_ratio: Optional[float] = Field( - default=None, description="Price to operating cash flows ratio." - ) - price_cash_flow_ratio: Optional[float] = Field( - default=None, description="Price cash flow ratio." - ) - price_earnings_to_growth_ratio: Optional[float] = Field( - default=None, description="Price earnings to growth ratio." - ) - price_sales_ratio: Optional[float] = Field( - default=None, description="Price sales ratio." - ) - dividend_yield: Optional[float] = Field(default=None, description="Dividend yield.") - dividend_yield_percentage: Optional[float] = Field( - default=None, description="Dividend yield percentage." - ) - dividend_per_share: Optional[float] = Field( - default=None, description="Dividend per share." - ) - enterprise_value_multiple: Optional[float] = Field( - default=None, description="Enterprise value multiple." - ) - price_fair_value: Optional[float] = Field( - default=None, description="Price fair value." - ) + period_ending: str = Field(description=DATA_DESCRIPTIONS.get("date", "")) + fiscal_period: str = Field(description="Period of the financial ratios.") + fiscal_year: Optional[int] = Field(default=None, description="Fiscal year.") diff --git a/openbb_platform/core/openbb_core/provider/standard_models/income_statement.py b/openbb_platform/core/openbb_core/provider/standard_models/income_statement.py index 9eb5f84f882..ae6b7085d9c 100644 --- a/openbb_platform/core/openbb_core/provider/standard_models/income_statement.py +++ b/openbb_platform/core/openbb_core/provider/standard_models/income_statement.py @@ -1,24 +1,25 @@ """Income Statement Standard Model.""" - +import warnings from datetime import date as dateType -from typing import List, Literal, Optional, Set, Union +from typing import Optional -from pydantic import Field, NonNegativeInt, StrictFloat, field_validator +from pydantic import Field, NonNegativeInt, field_validator from openbb_core.provider.abstract.data import Data from openbb_core.provider.abstract.query_params import QueryParams from openbb_core.provider.utils.descriptions import ( - DATA_DESCRIPTIONS, QUERY_DESCRIPTIONS, ) +_warn = warnings.warn + class IncomeStatementQueryParams(QueryParams): """Income Statement Query.""" symbol: str = Field(description=QUERY_DESCRIPTIONS.get("symbol", "")) - period: Optional[Literal["annual", "quarter"]] = Field( + period: str = Field( default="annual", description=QUERY_DESCRIPTIONS.get("period", ""), ) @@ -28,129 +29,22 @@ class IncomeStatementQueryParams(QueryParams): @field_validator("symbol", mode="before", check_fields=False) @classmethod - def upper_symbol(cls, v: Union[str, List[str], Set[str]]): + def upper_symbol(cls, v: str): """Convert symbol to uppercase.""" + if "," in v: + _warn( + f"{QUERY_DESCRIPTIONS.get('symbol_list_warning', '')} {v.split(',')[0].upper()}" + ) return v.split(",")[0].upper() if "," in v else v.upper() class IncomeStatementData(Data): """Income Statement Data.""" - symbol: Optional[str] = Field( - default=None, description=DATA_DESCRIPTIONS.get("symbol", "") + period_ending: dateType = Field(description="The end date of the reporting period.") + fiscal_period: Optional[str] = Field( + description="The fiscal period of the report.", default=None ) - date: dateType = Field( - description=DATA_DESCRIPTIONS.get("date", "") - + " In this case, the date of the income statement." + fiscal_year: Optional[int] = Field( + description="The fiscal year of the fiscal period.", default=None ) - period: Optional[str] = Field( - default=None, description="Period of the income statement." - ) - cik: Optional[str] = Field( - default=None, - description=DATA_DESCRIPTIONS.get("cik", ""), - ) - - revenue: Optional[StrictFloat] = Field(default=None, description="Revenue.") - cost_of_revenue: Optional[StrictFloat] = Field( - default=None, description="Cost of revenue." - ) - gross_profit: Optional[StrictFloat] = Field( - default=None, description="Gross profit." - ) - cost_and_expenses: Optional[StrictFloat] = Field( - default=None, description="Cost and expenses." - ) - gross_profit_ratio: Optional[float] = Field( - default=None, description="Gross profit ratio." - ) - - research_and_development_expenses: Optional[StrictFloat] = Field( - default=None, description="Research and development expenses." - ) - general_and_administrative_expenses: Optional[StrictFloat] = Field( - default=None, description="General and administrative expenses." - ) - selling_and_marketing_expenses: Optional[float] = Field( - default=None, description="Selling and marketing expenses." - ) - selling_general_and_administrative_expenses: Optional[StrictFloat] = Field( - default=None, description="Selling, general and administrative expenses." - ) - other_expenses: Optional[StrictFloat] = Field( - default=None, description="Other expenses." - ) - operating_expenses: Optional[StrictFloat] = Field( - default=None, description="Operating expenses." - ) - - depreciation_and_amortization: Optional[StrictFloat] = Field( - default=None, description="Depreciation and amortization." - ) - ebit: Optional[StrictFloat] = Field( - default=None, - description="Earnings before interest, and taxes.", - ) - ebitda: Optional[StrictFloat] = Field( - default=None, - description="Earnings before interest, taxes, depreciation and amortization.", - ) - ebitda_ratio: Optional[float] = Field( - default=None, - description="Earnings before interest, taxes, depreciation and amortization ratio.", - ) - operating_income: Optional[StrictFloat] = Field( - default=None, description="Operating income." - ) - operating_income_ratio: Optional[float] = Field( - default=None, description="Operating income ratio." - ) - - interest_income: Optional[StrictFloat] = Field( - default=None, description="Interest income." - ) - interest_expense: Optional[StrictFloat] = Field( - default=None, description="Interest expense." - ) - total_other_income_expenses_net: Optional[StrictFloat] = Field( - default=None, description="Total other income expenses net." - ) - - income_before_tax: Optional[StrictFloat] = Field( - default=None, description="Income before tax." - ) - income_before_tax_ratio: Optional[float] = Field( - default=None, description="Income before tax ratio." - ) - income_tax_expense: Optional[StrictFloat] = Field( - default=None, description="Income tax expense." - ) - - net_income: Optional[StrictFloat] = Field(default=None, description="Net income.") - net_income_ratio: Optional[float] = Field( - default=None, description="Net income ratio." - ) - eps: Optional[float] = Field(default=None, description="Earnings per share.") - eps_diluted: Optional[float] = Field( - default=None, description="Earnings per share diluted." - ) - weighted_average_shares_outstanding: Optional[StrictFloat] = Field( - default=None, description="Weighted average shares outstanding." - ) - weighted_average_shares_outstanding_dil: Optional[StrictFloat] = Field( - default=None, description="Weighted average shares outstanding diluted." - ) - link: Optional[str] = Field( - default=None, description="Link to the income statement." - ) - final_link: Optional[str] = Field( - default=None, description="Final link to the income statement." - ) - - @field_validator("symbol", mode="before", check_fields=False) - @classmethod - def upper_symbol(cls, v: Union[str, List[str], Set[str]]): - """Convert symbol to uppercase.""" - if isinstance(v, str): - return v.upper() - return ",".join([symbol.upper() for symbol in list(v)]) if v else None diff --git a/openbb_platform/core/openbb_core/provider/standard_models/reported_financials.py b/openbb_platform/core/openbb_core/provider/standard_models/reported_financials.py new file mode 100644 index 00000000000..b390339a50e --- /dev/null +++ b/openbb_platform/core/openbb_core/provider/standard_models/reported_financials.py @@ -0,0 +1,66 @@ +"""Reported Financials.""" +import warnings +from datetime import date as dateType +from typing import Optional + +from pydantic import Field, field_validator, model_validator + +from openbb_core.provider.abstract.data import Data +from openbb_core.provider.abstract.query_params import QueryParams +from openbb_core.provider.utils.descriptions import ( + QUERY_DESCRIPTIONS, +) + +_warn = warnings.warn + + +class ReportedFinancialsQueryParams(QueryParams): + """Reported Financials Query Params.""" + + symbol: str = Field(description=QUERY_DESCRIPTIONS.get("symbol", "")) + period: str = Field( + default="annual", description=QUERY_DESCRIPTIONS.get("period", "") + ) + statement_type: str = Field( + default="balance", + description="The type of financial statement - i.e, balance, income, cash.", + ) + limit: Optional[int] = Field( + default=100, + description=( + QUERY_DESCRIPTIONS.get("limit", "") + + " Although the response object contains multiple results," + + " because of the variance in the fields, year-to-year and quarter-to-quarter," + + " it is recommended to view results in small chunks." + ), + ) + + @field_validator("symbol", mode="before", check_fields=False) + @classmethod + def upper_symbol(cls, v: str): + """Convert symbol to uppercase.""" + if "," in v: + _warn( + f"{QUERY_DESCRIPTIONS.get('symbol_list_warning', '')} {v.split(',')[0].upper()}" + ) + return v.split(",")[0].upper() if "," in v else v.upper() + + +class ReportedFinancialsData(Data): + """Reported Financials Data.""" + + period_ending: dateType = Field( + description="The ending date of the reporting period." + ) + fiscal_period: str = Field( + description="The fiscal period of the report (e.g. FY, Q1, etc.)." + ) + fiscal_year: Optional[int] = Field( + description="The fiscal year of the fiscal period.", default=None + ) + + @model_validator(mode="before") + @classmethod + def replace_zero(cls, values): # pylint: disable=no-self-argument + """Check for zero values and replace with None.""" + return {k: None if v == 0 else v for k, v in values.items()} diff --git a/openbb_platform/core/openbb_core/provider/utils/descriptions.py b/openbb_platform/core/openbb_core/provider/utils/descriptions.py index e60093215cf..2ad3aeca59e 100644 --- a/openbb_platform/core/openbb_core/provider/utils/descriptions.py +++ b/openbb_platform/core/openbb_core/provider/utils/descriptions.py @@ -11,6 +11,8 @@ QUERY_DESCRIPTIONS = { "countries": "The country or countries to get data.", "units": "The unit of measurement for the data.", "frequency": "The frequency of the data.", + "symbol_list_warning": "Lists of symbols are not allowed for this function. " + + "Multiple symbols will be ignored in favour of the first symbol.", } DATA_DESCRIPTIONS = { diff --git a/openbb_platform/extensions/equity/integration/test_equity_api.py b/openbb_platform/extensions/equity/integration/test_equity_api.py index 655716a85a6..bbd8e4eb1d6 100644 --- a/openbb_platform/extensions/equity/integration/test_equity_api.py +++ b/openbb_platform/extensions/equity/integration/test_equity_api.py @@ -29,7 +29,8 @@ def headers(): "provider": "intrinio", "symbol": "AAPL", "period": "annual", - "limit": 12, + "fiscal_year": None, + "limit": 2, } ), ( @@ -59,7 +60,6 @@ def headers(): "period": "annual", "limit": 12, "provider": "fmp", - "cik": "0000320193", } ), ( @@ -154,13 +154,13 @@ def test_equity_calendar_earnings(params, headers): @parametrize( "params", [ - ({"symbol": "AAPL", "period": "annual", "limit": 12, "provider": "fmp"}), ( { "provider": "intrinio", "symbol": "AAPL", - "period": "annual", - "limit": 12, + "period": "ttm", + "fiscal_year": 2015, + "limit": 4, } ), ( @@ -190,7 +190,6 @@ def test_equity_calendar_earnings(params, headers): "period": "annual", "limit": 12, "provider": "fmp", - "cik": "0000320193", } ), ( @@ -321,8 +320,9 @@ def test_equity_estimates_historical(params, headers): { "provider": "intrinio", "symbol": "AAPL", - "period": "annual", - "limit": 12, + "period": "ytd", + "fiscal_year": 2020, + "limit": 4, } ), ( @@ -352,7 +352,6 @@ def test_equity_estimates_historical(params, headers): "period": "annual", "limit": 12, "provider": "fmp", - "cik": "0000320193", } ), ( @@ -594,7 +593,18 @@ def test_equity_estimates_consensus(params, headers): @parametrize( "params", - [({"symbol": "AAPL", "period": "annual", "limit": 12})], + [ + ({"symbol": "AAPL", "period": "annual", "limit": 12, "provider": "fmp"}), + ( + { + "symbol": "AAPL", + "period": "ttm", + "fiscal_year": 2019, + "limit": 4, + "provider": "intrinio", + } + ), + ], ) @pytest.mark.integration def test_equity_fundamental_ratios(params, headers): @@ -1443,3 +1453,51 @@ def test_equity_fundamental_trailing_dividend_yield(params, headers): result = requests.get(url, headers=headers, timeout=10) assert isinstance(result, requests.Response) assert result.status_code == 200 + + +@parametrize( + "params", + [ + ( + { + "symbol": "AAPL", + "statement_type": "income", + "period": "quarter", + "limit": 5, + "fiscal_year": None, + "provider": "intrinio", + } + ), + ( + { + "symbol": "AAPL", + "statement_type": "cash", + "period": "annual", + "limit": 1, + "fiscal_year": 2015, + "provider": "intrinio", + } + ), + ( + { + "symbol": "AAPL", + "statement_type": "balance", + "period": "annual", + "fiscal_year": None, + "limit": 10, + "provider": "intrinio", + } + ), + ], +) +@pytest.mark.integration +def test_equity_fundamental_reported_financials(params, headers): + params = {p: v for p, v in params.items() if v} + + query_str = get_querystring(params, []) + url = ( + f"http://0.0.0.0:8000/api/v1/equity/fundamental/reported_financials?{query_str}" + ) + result = requests.get(url, headers=headers, timeout=10) + assert isinstance(result, requests.Response) + assert result.status_code == 200 diff --git a/openbb_platform/extensions/equity/integration/test_equity_python.py b/openbb_platform/extensions/equity/integration/test_equity_python.py index 9e84bea3066..fb83e7813b1 100644 --- a/openbb_platform/extensions/equity/integration/test_equity_python.py +++ b/openbb_platform/extensions/equity/integration/test_equity_python.py @@ -26,8 +26,9 @@ def obb(pytestconfig): { "provider": "intrinio", "symbol": "AAPL", - "period": "annual", - "limit": 12, + "period": "ttm", + "fiscal_year": 2014, + "limit": 2, } ), ( @@ -57,7 +58,6 @@ def obb(pytestconfig): "period": "annual", "limit": 12, "provider": "fmp", - "cik": "0000320193", } ), ( @@ -139,13 +139,13 @@ def test_equity_calendar_earnings(params, obb): @parametrize( "params", [ - ({"symbol": "AAPL", "period": "annual", "limit": 12}), ( { "provider": "intrinio", "symbol": "AAPL", "period": "annual", - "limit": 12, + "fiscal_year": None, + "limit": 2, } ), ( @@ -175,7 +175,6 @@ def test_equity_calendar_earnings(params, obb): "period": "annual", "limit": 12, "provider": "fmp", - "cik": "0000320193", } ), ( @@ -296,8 +295,9 @@ def test_equity_estimates_historical(params, obb): { "provider": "intrinio", "symbol": "AAPL", - "period": "annual", - "limit": 12, + "period": "quarter", + "fiscal_year": 2020, + "limit": 4, } ), ( @@ -327,7 +327,6 @@ def test_equity_estimates_historical(params, obb): "symbol": "AAPL", "limit": 12, "period": "annual", - "cik": "0000320193", } ), ( @@ -555,7 +554,16 @@ def test_equity_estimates_consensus(params, obb): @parametrize( "params", [ - ({"symbol": "AAPL", "period": "annual", "limit": 12}), + ({"symbol": "AAPL", "period": "annual", "limit": 12, "provider": "fmp"}), + ( + { + "symbol": "AAPL", + "period": "ttm", + "fiscal_year": None, + "limit": 12, + "provider": "intrinio", + } + ), ], ) @pytest.mark.integration @@ -1363,3 +1371,48 @@ def test_equity_fundamental_trailing_dividend_yield(params, obb): assert result assert isinstance(result, OBBject) assert len(result.results) > 0 + + +@parametrize( + "params", + [ + ( + { + "symbol": "AAPL", + "statement_type": "income", + "period": "quarter", + "limit": 5, + "fiscal_year": None, + "provider": "intrinio", + } + ), + ( + { + "symbol": "AAPL", + "statement_type": "cash", + "period": "annual", + "limit": 1, + "fiscal_year": 2015, + "provider": "intrinio", + } + ), + ( + { + "symbol": "AAPL", + "statement_type": "balance", + "period": "annual", + "fiscal_year": None, + "limit": 10, + "provider": "intrinio", + } + ), + ], +) +@pytest.mark.integration +def test_equity_fundamental_reported_financials(params, obb): + params = {p: v for p, v in params.items() if v} + + result = obb.equity.fundamental.reported_financials(**params) + assert result + assert isinstance(result, OBBject) + assert len(result.results) > 0 diff --git a/openbb_platform/extensions/equity/openbb_equity/fundamental/fundamental_router.py b/openbb_platform/extensions/equity/openbb_equity/fundamental/fundamental_router.py index c76fd639612..dbaddcb70ba 100644 --- a/openbb_platform/extensions/equity/openbb_equity/fundamental/fundamental_router.py +++ b/openbb_platform/extensions/equity/openbb_equity/fundamental/fundamental_router.py @@ -59,6 +59,17 @@ async def cash( return await OBBject.from_query(Query(**locals())) +@router.command(model="ReportedFinancials") +async def reported_financials( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject[BaseModel]: + """Financial statements, as-reported.""" + return await OBBject.from_query(Query(**locals())) + + @router.command(model="CashFlowStatementGrowth") async def cash_growth( cc: CommandContext, diff --git a/openbb_platform/providers/fmp/openbb_fmp/models/balance_sheet.py b/openbb_platform/providers/fmp/openbb_fmp/models/balance_sheet.py index f7a13237ace..a67d1089e10 100644 --- a/openbb_platform/providers/fmp/openbb_fmp/models/balance_sheet.py +++ b/openbb_platform/providers/fmp/openbb_fmp/models/balance_sheet.py @@ -1,15 +1,16 @@ """FMP Balance Sheet Model.""" - +from datetime import ( + date as dateType, + datetime, +) from typing import Any, Dict, List, Literal, Optional -from openbb_core.provider.abstract.data import ForceInt from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.balance_sheet import ( BalanceSheetData, BalanceSheetQueryParams, ) -from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS from openbb_fmp.utils.helpers import create_url, get_data_many from pydantic import Field, model_validator @@ -20,76 +21,75 @@ class FMPBalanceSheetQueryParams(BalanceSheetQueryParams): Source: https://financialmodelingprep.com/developer/docs/#Balance-Sheet """ - period: Optional[Literal["annual", "quarter"]] = Field( - default="quarter", - description=QUERY_DESCRIPTIONS.get("period", ""), - ) - cik: Optional[str] = Field( - default=None, - description="Central Index Key (CIK) of the company.", - ) - - @model_validator(mode="before") - @classmethod - def check_symbol_or_cik(cls, values): # pylint: disable=no-self-argument - """Check if symbol or cik is provided.""" - if values.get("symbol") is None and values.get("cik") is None: - raise ValueError("symbol or cik must be provided") - return values + period: Optional[Literal["annual", "quarter"]] = Field(default="annual") class FMPBalanceSheetData(BalanceSheetData): """FMP Balance Sheet Data.""" __alias_dict__ = { - "currency": "reportedCurrency", - "current_assets": "totalCurrentAssets", - "non_current_assets": "totalNonCurrentAssets", - "assets": "totalAssets", - "current_liabilities": "totalCurrentLiabilities", - "non_current_liabilities": "totalNonCurrentLiabilities", - "liabilities": "totalLiabilities", - "other_stockholder_equity": "othertotalStockholdersEquity", + "period_ending": "date", + "fiscal_period": "period", + "fiscal_year": "calendarYear", "filing_date": "fillingDate", + "accepted_date": "acceptedDate", + "currency": "reportedCurrency", + "cash_and_cash_equivalents": "cashAndCashEquivalents", + "short_term_investments": "shortTermInvestments", + "cash_and_short_term_investments": "cashAndShortTermInvestments", + "net_receivables": "netReceivables", + "inventory": "inventories", + "other_current_assets": "otherCurrentAssets", + "total_current_assets": "totalCurrentAssets", + "plant_property_equipment_net": "propertyPlantEquipmentNet", + "goodwill": "goodwill", + "intangible_assets": "intangibleAssets", + "goodwill_and_intangible_assets": "goodwillAndIntangibleAssets", + "long_term_investments": "longTermInvestments", + "tax_assets": "taxAssets", + "other_non_current_assets": "otherNonCurrentAssets", + "non_current_assets": "totalNonCurrentAssets", + "other_assets": "otherAssets", + "total_assets": "totalAssets", + "accounts_payable": "accountPayables", + "short_term_debt": "shortTermDebt", + "tax_payables": "taxPayables", + "current_deferred_revenue": "deferredRevenue", + "other_current_liabilities": "otherCurrentLiabilities", + "total_current_liabilities": "totalCurrentLiabilities", + "long_term_debt": "longTermDebt", + "deferred_revenue_non_current": "deferredRevenueNonCurrent", + "deferred_tax_liabilities_non_current": "deferredTaxLiabilitiesNonCurrent", + "other_non_current_liabilities": "otherNonCurrentLiabilities", + "total_non_current_liabilities": "totalNonCurrentLiabilities", + "other_liabilities": "otherLiabilities", + "capital_lease_obligations": "capitalLeaseObligations", + "total_liabilities": "totalLiabilities", + "preferred_stock": "preferredStock", + "common_stock": "commonStock", + "retained_earnings": "retainedEarnings", + "accumulated_other_comprehensive_income": "accumulatedOtherComprehensiveIncomeLoss", + "other_stock_holders_equity": "otherStockholdersEquity", + "other_total_stock_holders_equity": "othertotalStockholdersEquity", + "total_common_equity": "totalStockholdersEquity", + "total_equity_non_controlling_interests": "totalEquity", + "total_liabilities_shareholders_equity": "totalLiabilitiesAndStockholdersEquity", + "minority_interest": "minorityInterest", + "total_liabilities_and_total_equity": "totalLiabilitiesAndTotalEquity", + "total_investments": "totalInvestments", + "total_debt": "totalDebt", + "net_debt": "netDebt", + "link": "link", + "final_link": "finalLink", } - # Leftovers below - calendar_year: Optional[ForceInt] = Field(default=None, description="Calendar Year") - - cash_and_short_term_investments: Optional[ForceInt] = Field( - default=None, description="Cash and Short Term Investments" + filing_date: Optional[dateType] = Field( + default=None, + description="The date when the filing was made.", ) - goodwill_and_intangible_assets: Optional[ForceInt] = Field( - default=None, description="Goodwill and Intangible Assets" - ) - deferred_revenue_non_current: Optional[ForceInt] = Field( - default=None, description="Deferred Revenue Non Current" - ) - total_investments: Optional[ForceInt] = Field( - default=None, description="Total Investments" - ) - - capital_lease_obligations: Optional[ForceInt] = Field( - default=None, description="Capital Lease Obligations" - ) - deferred_tax_liabilities_non_current: Optional[ForceInt] = Field( - default=None, description="Deferred Tax Liabilities Non Current" - ) - capital_lease_obligations: Optional[ForceInt] = Field( - default=None, description="Capital lease obligations" - ) - total_investments: Optional[ForceInt] = Field( - default=None, description="Total investments" - ) - total_debt: Optional[ForceInt] = Field(default=None, description="Total debt") - net_debt: Optional[ForceInt] = Field(default=None, description="Net debt") - - total_debt: Optional[ForceInt] = Field(default=None, description="Total Debt") - net_debt: Optional[ForceInt] = Field(default=None, description="Net Debt") - - link: Optional[str] = Field(default=None, description="Link to the statement.") - final_link: Optional[str] = Field( - default=None, description="Link to the final statement." + accepted_date: Optional[datetime] = Field( + default=None, + description="The date and time when the filing was accepted.", ) @model_validator(mode="before") @@ -132,4 +132,7 @@ class FMPBalanceSheetFetcher( query: FMPBalanceSheetQueryParams, data: List[Dict], **kwargs: Any ) -> List[FMPBalanceSheetData]: """Return the transformed data.""" + for result in data: + result.pop("symbol", None) + result.pop("cik", None) return [FMPBalanceSheetData.model_validate(d) for d in data] diff --git a/openbb_platform/providers/fmp/openbb_fmp/models/cash_flow.py b/openbb_platform/providers/fmp/openbb_fmp/models/cash_flow.py index 637b5fb0483..e497b4aa6f8 100644 --- a/openbb_platform/providers/fmp/openbb_fmp/models/cash_flow.py +++ b/openbb_platform/providers/fmp/openbb_fmp/models/cash_flow.py @@ -7,13 +7,11 @@ from datetime import ( ) from typing import Any, Dict, List, Literal, Optional -from openbb_core.provider.abstract.data import ForceInt from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.cash_flow import ( CashFlowStatementData, CashFlowStatementQueryParams, ) -from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS from openbb_fmp.utils.helpers import create_url, get_data_many from pydantic import Field, model_validator @@ -24,80 +22,56 @@ class FMPCashFlowStatementQueryParams(CashFlowStatementQueryParams): Source: https://financialmodelingprep.com/developer/docs/#Cash-Flow-Statement """ - period: Optional[Literal["annual", "quarter"]] = Field( - default="quarter", - description=QUERY_DESCRIPTIONS.get("period", ""), - ) - cik: Optional[str] = Field( - default=None, description="Central Index Key (CIK) of the company." - ) - - @model_validator(mode="before") - @classmethod - def check_symbol_or_cik(cls, values): # pylint: disable=no-self-argument - """Validate that either a symbol or CIK is provided.""" - if values.get("symbol") is None and values.get("cik") is None: - raise ValueError("symbol or cik must be provided") - return values + period: Optional[Literal["annual", "quarter"]] = Field(default="annual") class FMPCashFlowStatementData(CashFlowStatementData): """FMP Cash Flow Statement Data.""" __alias_dict__ = { + "period_ending": "date", + "fiscal_period": "period", + "fiscal_year": "calendarYear", + "filing_date": "fillingDate", + "accepted_date": "acceptedDate", "reported_currency": "reportedCurrency", - "net_cash_used_for_investing_activities": "netCashUsedForInvestingActivites", - "other_financing_activities": "otherFinancingActivites", - "net_cash_flow_from_operating_activities": "netCashProvidedByOperatingActivities", - "purchases_of_marketable_securities": "purchasesOfInvestments", - "sales_from_maturities_of_investments": "salesMaturitiesOfInvestments", - "payments_from_acquisitions": "acquisitionsNet", - "net_cash_flow_from_investing_activities": "netCashUsedForInvestingActivites", - "net_cash_flow_from_financing_activities": "netCashUsedProvidedByFinancingActivities", + "net_income": "netIncome", + "depreciation_and_amortization": "depreciationAndAmortization", + "deferred_income_tax": "deferredIncomeTax", + "stock_based_compensation": "stockBasedCompensation", + "change_in_working_capital": "changeInWorkingCapital", + "changes_in_account_receivables": "accountsReceivables", + "changes_in_inventory": "inventory", + "change_in_account_payable": "accountsPayables", + "changes_in_other_working_capital": "otherWorkingCapital", + "changes_in_other_non_cash_items": "otherNonCashItems", + "net_cash_from_operating_activities": "netCashProvidedByOperatingActivities", + "purchase_of_property_plant_and_equipment": "investmentsInPropertyPlantAndEquipment", + "acquisitions": "acquisitionsNet", + "purchase_of_investment_securities": "purchasesOfInvestments", + "sale_and_maturity_of_investments": "salesMaturitiesOfInvestments", "other_investing_activities": "otherInvestingActivites", + "net_cash_from_investing_activities": "netCashUsedForInvestingActivites", + "repayment_of_debt": "debtRepayment", + "issuance_of_common_equity": "commonStockIssued", + "repurchase_of_common_equity": "commonStockRepurchased", + "payment_of_dividends": "dividendsPaid", + "other_financing_activities": "otherFinancingActivites", + "net_cash_from_financing_activities": "netCashUsedProvidedByFinancingActivities", + "effect_of_exchange_rate_changes_on_cash": "effectOfForexChangesOnCash", + "net_change_in_cash_and_equivalents": "netChangeInCash", + "cash_at_beginning_of_period": "cashAtBeginningOfPeriod", + "cash_at_end_of_period": "cashAtEndOfPeriod", + "operating_cash_flow": "operatingCashFlow", + "capital_expenditure": "capitalExpenditure", + "free_cash_flow": "freeCashFlow", + "link": "link", + "final_link": "finalLink", } - reported_currency: str = Field(description="Reported currency in the statement.") - filling_date: dateType = Field(description="Filling date.") - accepted_date: datetime = Field(description="Accepted date.") - calendar_year: Optional[ForceInt] = Field( - default=None, description="Calendar year." - ) - - change_in_working_capital: Optional[ForceInt] = Field( - default=None, description="Change in working capital." - ) - other_working_capital: Optional[ForceInt] = Field( - default=None, description="Other working capital." - ) - common_stock_issued: Optional[ForceInt] = Field( - default=None, description="Common stock issued." - ) - effect_of_forex_changes_on_cash: Optional[ForceInt] = Field( - default=None, description="Effect of forex changes on cash." - ) - - cash_at_beginning_of_period: Optional[ForceInt] = Field( - default=None, description="Cash at beginning of period." - ) - cash_at_end_of_period: Optional[ForceInt] = Field( - default=None, - description="Cash, cash equivalents, and restricted cash at end of period", - ) - operating_cash_flow: Optional[ForceInt] = Field( - default=None, description="Operating cash flow." - ) - capital_expenditure: Optional[ForceInt] = Field( - default=None, description="Capital expenditure." - ) - free_cash_flow: Optional[ForceInt] = Field( - default=None, description="Free cash flow." - ) - - link: Optional[str] = Field(default=None, description="Link to the statement.") - final_link: Optional[str] = Field( - default=None, description="Link to the final statement." - ) + fiscal_year: int = Field(description="The fiscal year of the fiscal period.") + filing_date: dateType = Field(description="The date of the filing.") + accepted_date: datetime = Field(description="The date the filing was accepted.") @model_validator(mode="before") @classmethod @@ -139,4 +113,7 @@ class FMPCashFlowStatementFetcher( query: FMPCashFlowStatementQueryParams, data: List[Dict], **kwargs: Any ) -> List[FMPCashFlowStatementData]: """Return the transformed data.""" + for result in data: + result.pop("symbol", None) + result.pop("cik", None) return [FMPCashFlowStatementData.model_validate(d) for d in data] diff --git a/openbb_platform/providers/fmp/openbb_fmp/models/financial_ratios.py b/openbb_platform/providers/fmp/openbb_fmp/models/financial_ratios.py index 93b15ad9d36..3b44dbffef5 100644 --- a/openbb_platform/providers/fmp/openbb_fmp/models/financial_ratios.py +++ b/openbb_platform/providers/fmp/openbb_fmp/models/financial_ratios.py @@ -8,14 +8,12 @@ from openbb_core.provider.standard_models.financial_ratios import ( FinancialRatiosData, FinancialRatiosQueryParams, ) +from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS from openbb_core.provider.utils.helpers import ( - ClientResponse, - ClientSession, amake_requests, + to_snake_case, ) -from pydantic import Field - -PeriodType = Literal["annual", "quarter"] +from pydantic import Field, model_validator class FMPFinancialRatiosQueryParams(FinancialRatiosQueryParams): @@ -24,8 +22,8 @@ class FMPFinancialRatiosQueryParams(FinancialRatiosQueryParams): Source: https://financialmodelingprep.com/developer/docs/#Company-Financial-Ratios """ - with_ttm: Optional[bool] = Field( - default=False, description="Include trailing twelve months (TTM) data." + period: Literal["annual", "quarter", "ttm"] = Field( + default="annual", description=QUERY_DESCRIPTIONS.get("period", "") ) @@ -33,14 +31,170 @@ class FMPFinancialRatiosData(FinancialRatiosData): """FMP Financial Ratios Data.""" __alias_dict__ = { - "net_income_per_ebt": "netIncomePerEBT", - "dividend_yield": "dividendYiel", - "dividend_yield_percentage": "dividendYieldPercentage", - "dividend_per_share": "dividendPerShare", - "research_and_developement_to_revenue": "researchAndDevelopementToRevenue", - "debt_to_market_cap": "debtToMarketCap", + "dividend_yield_ttm": "dividend_yiel_ttm", + "dividend_yield_ttm_percent": "dividend_yiel_percentage_ttm", + "period_ending": "date", + "fiscal_period": "period", + "fiscal_year": "calendar_year", } + current_ratio: Optional[float] = Field(default=None, description="Current ratio.") + quick_ratio: Optional[float] = Field(default=None, description="Quick ratio.") + cash_ratio: Optional[float] = Field(default=None, description="Cash ratio.") + days_of_sales_outstanding: Optional[float] = Field( + default=None, description="Days of sales outstanding." + ) + days_of_inventory_outstanding: Optional[float] = Field( + default=None, description="Days of inventory outstanding." + ) + operating_cycle: Optional[float] = Field( + default=None, description="Operating cycle." + ) + days_of_payables_outstanding: Optional[float] = Field( + default=None, description="Days of payables outstanding." + ) + cash_conversion_cycle: Optional[float] = Field( + default=None, description="Cash conversion cycle." + ) + gross_profit_margin: Optional[float] = Field( + default=None, description="Gross profit margin." + ) + operating_profit_margin: Optional[float] = Field( + default=None, description="Operating profit margin." + ) + pretax_profit_margin: Optional[float] = Field( + default=None, description="Pretax profit margin." + ) + net_profit_margin: Optional[float] = Field( + default=None, description="Net profit margin." + ) + effective_tax_rate: Optional[float] = Field( + default=None, description="Effective tax rate." + ) + return_on_assets: Optional[float] = Field( + default=None, description="Return on assets." + ) + return_on_equity: Optional[float] = Field( + default=None, description="Return on equity." + ) + return_on_capital_employed: Optional[float] = Field( + default=None, description="Return on capital employed." + ) + net_income_per_ebt: Optional[float] = Field( + default=None, description="Net income per EBT." + ) + ebt_per_ebit: Optional[float] = Field(default=None, description="EBT per EBIT.") + ebit_per_revenue: Optional[float] = Field( + default=None, description="EBIT per revenue." + ) + debt_ratio: Optional[float] = Field(default=None, description="Debt ratio.") + debt_equity_ratio: Optional[float] = Field( + default=None, description="Debt equity ratio." + ) + long_term_debt_to_capitalization: Optional[float] = Field( + default=None, description="Long term debt to capitalization." + ) + total_debt_to_capitalization: Optional[float] = Field( + default=None, description="Total debt to capitalization." + ) + interest_coverage: Optional[float] = Field( + default=None, description="Interest coverage." + ) + cash_flow_to_debt_ratio: Optional[float] = Field( + default=None, description="Cash flow to debt ratio." + ) + company_equity_multiplier: Optional[float] = Field( + default=None, description="Company equity multiplier." + ) + receivables_turnover: Optional[float] = Field( + default=None, description="Receivables turnover." + ) + payables_turnover: Optional[float] = Field( + default=None, description="Payables turnover." + ) + inventory_turnover: Optional[float] = Field( + default=None, description="Inventory turnover." + ) + fixed_asset_turnover: Optional[float] = Field( + default=None, description="Fixed asset turnover." + ) + asset_turnover: Optional[float] = Field(default=None, description="Asset turnover.") + operating_cash_flow_per_share: Optional[float] = Field( + default=None, description="Operating cash flow per share." + ) + free_cash_flow_per_share: Optional[float] = Field( + default=None, description="Free cash flow per share." + ) + cash_per_share: Optional[float] = Field(default=None, description="Cash per share.") + payout_ratio: Optional[float] = Field(default=None, description="Payout ratio.") + operating_cash_flow_sales_ratio: Optional[float] = Field( + default=None, description="Operating cash flow sales ratio." + ) + free_cash_flow_operating_cash_flow_ratio: Optional[float] = Field( + default=None, description="Free cash flow operating cash flow ratio." + ) + cash_flow_coverage_ratios: Optional[float] = Field( + default=None, description="Cash flow coverage ratios." + ) + short_term_coverage_ratios: Optional[float] = Field( + default=None, description="Short term coverage ratios." + ) + capital_expenditure_coverage_ratio: Optional[float] = Field( + default=None, description="Capital expenditure coverage ratio." + ) + dividend_paid_and_capex_coverage_ratio: Optional[float] = Field( + default=None, description="Dividend paid and capex coverage ratio." + ) + dividend_payout_ratio: Optional[float] = Field( + default=None, description="Dividend payout ratio." + ) + price_book_value_ratio: Optional[float] = Field( + default=None, description="Price book value ratio." + ) + price_to_book_ratio: Optional[float] = Field( + default=None, description="Price to book ratio." + ) + price_to_sales_ratio: Optional[float] = Field( + default=None, description="Price to sales ratio." + ) + price_earnings_ratio: Optional[float] = Field( + default=None, description="Price earnings ratio." + ) + price_to_free_cash_flows_ratio: Optional[float] = Field( + default=None, description="Price to free cash flows ratio." + ) + price_to_operating_cash_flows_ratio: Optional[float] = Field( + default=None, description="Price to operating cash flows ratio." + ) + price_cash_flow_ratio: Optional[float] = Field( + default=None, description="Price cash flow ratio." + ) + price_earnings_to_growth_ratio: Optional[float] = Field( + default=None, description="Price earnings to growth ratio." + ) + price_sales_ratio: Optional[float] = Field( + default=None, description="Price sales ratio." + ) + dividend_yield: Optional[float] = Field(default=None, description="Dividend yield.") + dividend_yield_percentage: Optional[float] = Field( + default=None, description="Dividend yield percentage." + ) + dividend_per_share: Optional[float] = Field( + default=None, description="Dividend per share." + ) + enterprise_value_multiple: Optional[float] = Field( + default=None, description="Enterprise value multiple." + ) + price_fair_value: Optional[float] = Field( + default=None, description="Price fair value." + ) + + @model_validator(mode="before") + @classmethod + def replace_zero(cls, values): # pylint: disable=no-self-argument + """Check for zero values and replace with None.""" + return {k: None if v == 0 else v for k, v in values.items()} + class FMPFinancialRatiosFetcher( Fetcher[ @@ -66,38 +220,32 @@ class FMPFinancialRatiosFetcher( base_url = "https://financialmodelingprep.com/api/v3" - async def response_callback( - response: ClientResponse, session: ClientSession - ) -> List[Dict]: - results = await response.json() - symbol = response.url.parts[-1] + ttm_url = f"{base_url}/ratios-ttm/{query.symbol}?&apikey={api_key}" - # TTM data - ttm_url = f"{base_url}/ratios-ttm/{symbol}?&apikey={api_key}" - if query.with_ttm and (ratios_ttm := await session.get_one(ttm_url)): - results.insert( - 0, - { - "symbol": symbol, - "period": "TTM", - "date": datetime.now().strftime("%Y-%m-%d"), - **{k.replace("TTM", ""): v for k, v in ratios_ttm.items()}, - }, - ) - - return results - - urls = [ - f"{base_url}/ratios/{symbol}?" + url = ( + f"{base_url}/ratios/{query.symbol}?" f"period={query.period}&limit={query.limit}&apikey={api_key}" - for symbol in query.symbol.split(",") - ] + if query.period != "ttm" + else ttm_url + ) + results = await amake_requests(url, **kwargs) - return await amake_requests(urls, response_callback=response_callback, **kwargs) + return results @staticmethod def transform_data( query: FMPFinancialRatiosQueryParams, data: List[Dict], **kwargs: Any ) -> List[FMPFinancialRatiosData]: """Return the transformed data.""" - return [FMPFinancialRatiosData.model_validate(d) for d in data] + results = [ + {to_snake_case(k).replace("ttm", ""): v for k, v in item.items()} + for item in data + ] + if query.period == "ttm": + results[0].update( + {"period": "TTM", "date": datetime.now().date().strftime("%Y-%m-%d")} + ) + for item in results: + item.pop("symbol", None) + item.pop("dividend_yiel_percentage", None) + return [FMPFinancialRatiosData.model_validate(d) for d in results] diff --git a/openbb_platform/providers/fmp/openbb_fmp/models/income_statement.py b/openbb_platform/providers/fmp/openbb_fmp/models/income_statement.py index b149d1b8596..ca015c0fb38 100644 --- a/openbb_platform/providers/fmp/openbb_fmp/models/income_statement.py +++ b/openbb_platform/providers/fmp/openbb_fmp/models/income_statement.py @@ -14,8 +14,6 @@ from openbb_core.provider.standard_models.income_statement import ( from openbb_fmp.utils.helpers import get_data_many from pydantic import Field, model_validator -PeriodType = Literal["annual", "quarter"] - class FMPIncomeStatementQueryParams(IncomeStatementQueryParams): """FMP Income Statement Query. @@ -23,103 +21,55 @@ class FMPIncomeStatementQueryParams(IncomeStatementQueryParams): Source: https://financialmodelingprep.com/developer/docs/#Income-Statement """ - cik: Optional[str] = Field( - default=None, description="The CIK of the company if no symbol is provided." - ) - - @model_validator(mode="before") - @classmethod - def check_symbol_or_cik(cls, values): # pylint: disable=no-self-argument - """Validate that either a symbol or CIK is provided.""" - if values.get("symbol") is None and values.get("cik") is None: - raise ValueError("symbol or cik must be provided") - return values + period: Optional[Literal["annual", "quarter"]] = Field(default="annual") class FMPIncomeStatementData(IncomeStatementData): """FMP Income Statement Data.""" __alias_dict__ = { + "period_ending": "date", + "fiscal_period": "period", + "fiscal_year": "calendarYear", + "filing_date": "fillingDate", + "accepted_date": "acceptedDate", "reported_currency": "reportedCurrency", - "ebitda_ratio": "ebitdaratio", - "eps_diluted": "epsdiluted", - "weighted_average_shares_outstanding": "weightedAverageShsOut", - "weighted_average_shares_outstanding_dil": "weightedAverageShsOutDil", - "filling_date": "fillingDate", + "revenue": "revenue", + "cost_of_revenue": "costOfRevenue", + "gross_profit": "grossProfit", + "gross_profit_ratio": "grossProfitRatio", + "general_and_admin_expense": "generalAndAdministrativeExpenses", + "research_and_development_expense": "researchAndDevelopmentExpenses", + "selling_and_marketing_expense": "sellingAndMarketingExpenses", + "selling_general_and_admin_expense": "sellingGeneralAndAdministrativeExpenses", + "other_expenses": "otherExpenses", + "total_operating_expenses": "operatingExpenses", + "cost_and_expenses": "costAndExpenses", + "interest_income": "interestIncome", + "interest_expense": "interestExpense", + "depreciation_and_amortization": "depreciationAndAmortization", + "ebitda": "ebitda", + "ebitda_margin": "ebitdaratio", + "operating_income": "operatingIncome", + "operating_income_ratio": "operatingIncomeRatio", + "total_other_income_expenses_net": "totalOtherIncomeExpensesNet", + "income_before_tax": "incomeBeforeTax", + "income_before_tax_ratio": "incomeBeforeTaxRatio", + "income_tax_expense": "incomeTaxExpense", + "consolidated_net_income": "netIncome", + "net_income_ratio": "netIncomeRatio", + "basic_earnings_per_share": "eps", + "diluted_earnings_per_share": "epsdiluted", + "weighted_average_basic_shares_outstanding": "weightedAverageShsOut", + "weighted_average_diluted_shares_outstanding": "weightedAverageShsOutDil", + "link": "link", + "final_link": "finalLink", } - reported_currency: Optional[str] = Field( - default=None, description="Reporting currency." - ) - filling_date: Optional[dateType] = Field(default=None, description="Filling date.") - accepted_date: Optional[datetime] = Field( - default=None, description="Accepted date." - ) - calendar_year: Optional[int] = Field(default=None, description="Calendar year.") - - cost_of_revenue: Optional[float] = Field( - default=None, description="Cost of revenue." - ) - gross_profit: Optional[float] = Field(default=None, description="Gross profit.") - gross_profit_ratio: Optional[float] = Field( - default=None, description="Gross profit ratio." - ) - research_and_development_expenses: Optional[float] = Field( - default=None, description="Research and development expenses." - ) - general_and_administrative_expenses: Optional[float] = Field( - default=None, description="General and administrative expenses." - ) - selling_and_marketing_expenses: Optional[float] = Field( - default=None, description="Selling and marketing expenses." - ) - selling_general_and_administrative_expenses: Optional[float] = Field( - default=None, description="Selling, general and administrative expenses." - ) - other_expenses: Optional[float] = Field(default=None, description="Other expenses.") - - operating_expenses: Optional[float] = Field( - default=None, description="Operating expenses." - ) - depreciation_and_amortization: Optional[float] = Field( - default=None, description="Depreciation and amortization." - ) - ebitda_ratio: Optional[float] = Field(default=None, description="EBIDTA ratio.") - operating_income: Optional[float] = Field( - default=None, description="Operating income." - ) - operating_income_ratio: Optional[float] = Field( - default=None, description="Operating income ratio." - ) - interest_income: Optional[float] = Field( - default=None, description="Interest income." - ) - interest_expense: Optional[float] = Field( - default=None, description="Interest expense." - ) - - total_other_income_expenses_net: Optional[float] = Field( - default=None, description="Total other income expenses net." - ) - income_before_tax: Optional[float] = Field( - default=None, description="Income before tax." - ) - income_before_tax_ratio: Optional[float] = Field( - default=None, description="Income before tax ratio." - ) - income_tax_expense: Optional[float] = Field( - default=None, description="Income tax expense." - ) - net_income: Optional[float] = Field(default=None, description="Net income.") - net_income_ratio: Optional[float] = Field( - default=None, description="Net income ratio." - ) - - link: Optional[str] = Field( - default=None, description="Link to the income statement." - ) - final_link: Optional[str] = Field( - default=None, description="Final link to the income statement." + filing_date: dateType = Field(description="The date of the filing.") + accepted_date: datetime = Field(description="The date the filing was accepted.") + reported_currency: str = Field( + description="The reported currency of the filing.", ) @model_validator(mode="before") @@ -166,4 +116,7 @@ class FMPIncomeStatementFetcher( query: FMPIncomeStatementQueryParams, data: List[Dict], **kwargs: Any ) -> List[FMPIncomeStatementData]: """Return the transformed data.""" + for result in data: + result.pop("symbol", None) + result.pop("cik", None) return [FMPIncomeStatementData.model_validate(d) for d in data] diff --git a/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_balance_sheet_fetcher.yaml b/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_balance_sheet_fetcher.yaml index 845a013985f..e33ec1bdc20 100644 --- a/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_balance_sheet_fetcher.yaml +++ b/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_balance_sheet_fetcher.yaml @@ -3,48 +3,48 @@ interactions: body: null headers: Accept: - - '*/*' + - application/json Accept-Encoding: - gzip, deflate Connection: - keep-alive method: GET - uri: https://financialmodelingprep.com/api/v3/balance-sheet-statement/AAPL?apikey=MOCK_API_KEY&limit=5&period=quarter + uri: https://financialmodelingprep.com/api/v3/balance-sheet-statement/AAPL?apikey=MOCK_API_KEY&limit=5&period=annual response: body: string: !!binary | - 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 - AAA= + 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 headers: Access-Control-Allow-Credentials: - 'true' @@ -64,9 +64,9 @@ interactions: Content-Type: - application/json; charset=utf-8 Date: - - Wed, 01 Nov 2023 12:45:37 GMT - ETag: - - W/"28b4-L6hksMhvbvGQ5TWHfJ35PTqW8cA" + - Sun, 10 Dec 2023 00:02:04 GMT + Etag: + - W/"28b6-7a512hsTD42HhTamtlOQffHMTLE" Server: - nginx/1.18.0 (Ubuntu) Transfer-Encoding: diff --git a/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_cash_flow_statement_fetcher.yaml b/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_cash_flow_statement_fetcher.yaml index a474de1fab4..9b0d1a1eb26 100644 --- a/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_cash_flow_statement_fetcher.yaml +++ b/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_cash_flow_statement_fetcher.yaml @@ -3,44 +3,46 @@ interactions: body: null headers: Accept: - - '*/*' + - application/json Accept-Encoding: - gzip, deflate Connection: - keep-alive method: GET - uri: https://financialmodelingprep.com/api/v3/cash-flow-statement/AAPL?apikey=MOCK_API_KEY&limit=5&period=quarter + uri: https://financialmodelingprep.com/api/v3/cash-flow-statement/AAPL?apikey=MOCK_API_KEY&limit=5&period=annual response: body: string: !!binary | - H4sIAAAAAAAAA72ZWW/jNhCA3/dXBHmu1rzEw2/ebBYIsN2ku10URdEHrUQnQmzKlZTDLfrfO5It - WzwsH01iJEBCDofkzHA+Dv3Hu7Ozf+D37Ow8S2p9Pj47J4jQCIkI4fOfVj3Vcv6jmDV9k8nN5661 - 1IuirHV28VCW2qTLpv/7t49dd5rfNy0IPpQgrGjXMc1ns9zcfrSmkxFinUCSpnoBij0JeoblGLEx - 2+hKk5k2WVL+rpOyE+36FrrMi6xp/WXTZnR9ZdJi3ujFSkqM2s+6N9OLUqd5UueFmZhsMof95X+3 - /4I8RTFxxKcatp6tNP6aPINQxJG0hKq6SO8/JBXYqZgvtKk6dYRjYUmmd4m51Vfmt6K8B/tcJIu8 - ThqrRzCtskTBQsWDqauvOtX5Y/JjpqtGDnZkq8zNozZ1US5bLSSo4yZZdgqoEsySKeo7XfrrCct9 - KcxFUt1d1XreKmPMXgzYvum/KYvHPNPZh+U1eAisYW4naZ0/5nXeLoJwurZgfxdVPYedVFcGhsOw - enkzS0wNTrr86yFfNH0rQynqbBK6q7wxefVFNzJdz+KhBINXurqeXm31N0qUiG1rVxBk1c9J/VC2 - a3QHYCJU7JtjJbTd3cpFMeIho3yH+PhUhMcwatsx0z/qr3qRLLtdi/Xs20gq5vPCfGsi76qqHnRz - CBRHZJcQaFtbI1uHEbfNmOWNy0wGwZK3IlQy20btlj/lJjGpu2XCqH0kenveBoM7Nu8GI2aP1tOp - TuvrKZhLP1+0Z6a6biOv591mivVxWvcQwe0Vp9A+qS9Ndj296TIFUVLJgNQHfZsbA4vrywpMHBt0 - 8dxM+WlWPAWjOV2do8tnSAZZDkGlg5E7LbXu62HEOduQQ9sEe1fXi2o8Gj09Pb2vdPr+tngcTcCb - OYTSSGe3STmCzJ6MVkl41GhY/UnaCYXoNUVNom0bo9xk+vn9XT3fpm2TzD6/2KRJsphFTbpGAuF2 - Hpjm32auII7Y2+Iohp9hHIEEa3FExzE5Ekcb+T6OCMPcjpRhHBE3VEM4OoBC0k5IOylEqA3LMINi - SmwxC0GChXX0GBRhxmUgt3jrwYgy5Ms5FAJ12E7Oh2JIxo47jsCQwrZRT8EQR8yG7D4MYSoPxhA+ - HkPgf9stHodixe0Vhzh0CH5iZevx8cM75PW3GsQPZdJWdhR9YkHs0SfSJ8ax7ZsgfTyiDNAHe3ew - EH28IN5BHzdgXfrE3AnGF6IPZwH6cPa69IFJt/Rhe+lDIkwi+pb0IVDqDNMHJEhLHzym6Ej6bHZi - 0UcpDyeD9HEj5jT6KOQci501EGbKvv+E+cOIsDVa/MEShZX0AcSRCORRn4d4zbJB/FB8UhHUoM3f - x2H0oUK6mzyePpCw7PvoHvoITu14GIKPcws4AD4whtn28OijuAP6U+nDHPf79BHcPipDxY9w/HgM - fmgcO4XYifiJQIutKMgfjykD/IHjaEdZiD9+GIf544Wswx+KCLZN/kL8QTzAH8Rflz8waccfguFa - tZc/SEEd/Fb8AdyhiMgB/qwkxJo/eLOyAH82lU6PPxt5iz9IkGMe44jkbj4IPMZhyW2lu0lEhFP4 - 7ySR8x6x4y0O6n77LPVBxGgc1NHDEFwY40BG9ZejuHO1DHEIC/vx50AMQU1K/BfFAzFEpPto6WIo - ws7T1kA1JJz8v4dHKo5tzw+9yakgo4d5RBywezwiwnnROY1HhDHiXMx8HjnJfTePGF5LnoIjwoV6 - kWooolKGQOPgyEPMAI6ke9KD5ZAXzjtw5IauWw4hSV8aR835xEhaOCLRqvHVcNRNusERUoTtxxGH - wvjtcIQE1KeDOGokZIsjPo75kTja8d0QHDvLw/twhPbjCHPn3jhAI+bkjp00AieGWeLwSMmBdznv - ucqvigBZgUtvoCpyEkywKgoXAHtpBMfSdsrhNILLhfv1l0cjW2A3iyRWzq1iz8tcjJ3XkwEYuVXM - ATBihNrqPRZ1Pvm/LMLercv/YggHuBtkEXZflI9ikXALwpNZhA/4XsjDywCKVFeqDKLIi+UdL3Nu - 3HooEsqe7WVQhATyUQSNr4qiZtItijiJNyh69+d/KZNed6kgAAA= + H4sIAAAAAAAAA72ZW2/bNhTH3/spgjzPNe8i/eamDRCga4J1xVAMe1AlOhFiS56kXLxh332HsmWb + R5Rlp00DBInJw9vhn+fHQ//55uzsX/g9OztP49qeT87OGWF8RMyIk/Nf1jXVavGtmLu66fTmY1ta + 2mVR1ja9eChLmycrV//l8/u2OsnuXQmBH84INbytmGXzeZbfvt8fjtIR2RrESWKX0HHHgp1RPSF6 + wqLtIPHc5mlcfrVx2Zq2dUtbZkXqSi+/tmW5ra/ypFi4fo0yRpLmZ1Ob2mVpkyyusyKf5ul0AevL + /mk+gj2lkhpkP7Ow9nTd5e/xM1iBjd9pVRfJ/bu4AkcVi6XNq21/RHPumSZ3cX5rr/I/ivIePHQR + L7M6dn4fKRlFnin4qHjI6+o3m9jsMf42t5Wzo0przy7LH21eF+VqXUt1sJebeLXrQmt/lUV9Z8vO + lDrrbMw+FflFXN1d1XbRdBYJxjwr2ABncFMWj1lq03era9gm8Eh+O03q7DGrs2YWlBIpfOe4lVT1 + AlZTXeXQHtrVq5t5nNewVR/+fsiWrq5ZATHSX0KcQH2VOcdXn6wzamuWDyV4vbLV9exqN4DrhRlJ + /RlUILbq17h+KJtp4hZCSiq6Llkb7Ra48TLn/oZuHPMFdHJZhBtBC6zXb/Vvdhmvtit3GvVMQJiL + Iv/sNHhVVQ/WnQfKNt0EjKC7jUfSZv8iiWzTzG1cnoJmssaESsICSrjM8jhP8LIVoUE9uGXvNIHb + ZhufES2QvO1sZpP6egYus88XzfGprhsJ7u2xG2NzsjY1MlLIA1A+rT/k6fXspg0bnERoj9ZW7+xt + lucwuz1bJgw6oEWrazfk5bx4Cqs6WR+oD88QGdIMpGXDCp6V1u71BJFL+1qDkNrE27u6XlaT8fjp + 6eltZZO3t8XjeAo7moGgxja9jcsxBPp4vI7JY9fD+l/mJkaJ2isaORA0haMsT+3z27t6sYvieTz/ + +MMGjePlfOSiNzGcNOPAMP+5sbp0Yo5OTPwsOjHYjhHTB+i0togaOtEJ3c4sQCd2NJ2MJr5UhuhE + iUD2XTrpY+FkCPdPWi+b2gM9iCbNugG9RRMVSM4BMhkh/CmFwTSKDAkADJHJuWvf5lguMYYj7Clc + igjmL+YS3LqUZ9IPqEgZdhKgVMSV3+AQoKLNVE8A1IgxLrEIEaJMJwIGCDUMJm0E8UnSBRNoyt+q + fjBx0o/jYS7Bxgpfci/kUhP4/WWFyNSlTT+ZuDQMHYcQmbq67iMT1jAiExwsgXb4+9HkXAL099DE + 1mjSr4amdtAWTYwYJgbQRBs0yZ+FJtqAxxxA09pCN2gSkx3FAmiiR6NJKBQbhtDE9DCaRiKKfKte + OEGE94Nkf+IkDAr0fXQiFN1ivcyJKcGC3ezxiTLO/Gn1AEqIzeE9BCgIX8GINEgouAUgdJ9AKNC7 + 74UQofzT3Q8oF8ykP5UBQsFNUOijEcVRqDyGUFRIMZBE6ag/PdrlUBTlYgdQJU3kazCAKqFQ+tCL + KtAF9+d3CqsM59J38EtRxfUxOVSHPgdIZSL88hAiVVffPaTqaBnnUJDh/2hQuX0GZXigomtQyVcD + VTtoCyo4d0wOgIo0oFI/C1TEYWj3oBgAFVmjrAGVmuwQGgDVtpshUMlIoOg/BCoiFbIPgAquSp5R + L6eUxuLv45RUG8PDmFKG+mHCf95j4TfC/dc9QZQfNMOMYiZkhhFlXkQoTRQC/fGAgtA39LI3opL5 + 3R8gFFx6xWmEYuQEQkUmmGUeJJRgKAp2X/lcVPVMQoTS6I524JEPsjbfCQFAEX1sLgX3IN677EFA + aTg0/sRfCiggBUeMDhGqQ51+QklIAtALb4BQXX2HAdXRMuJTxLny5//9fGp6M/4bHxmtC1+NT+2g + LZ/gA1OH+URNw6dtuvLKfILhHJ+2GVCXTxsL4vhE2YRvydnlE93mY4N8kqzDm4N8YhIlBUE+8Y36 + hvlEFLpJ9eZRHL+8hwHF0OXaT6I0jt2Bb5/wm1ZPDgVBPhCPMKBUOEMYIpQyHAXu4wkFUQe9sQYQ + pY4mFPAaBdMBQBkd4Rh14JGPRP6uHgEoIbXBosUZlO5PjrZ8ihBQ+vmklEY3jQCfKPpu9sCXUBAJ + /AWcwidDTOS3fiGfmODochrCUxc5/Xhi0qBvLEN46oq776UPCxnxSWoshO/mU7OHsJP7fHIoaApf + i0/bQWOI8PeuyDDt/mwR9eav/wEvdeGgJyEAAA== headers: Access-Control-Allow-Credentials: - 'true' @@ -60,9 +62,9 @@ interactions: Content-Type: - application/json; charset=utf-8 Date: - - Wed, 01 Nov 2023 12:45:57 GMT - ETag: - - W/"20a9-B6xBFLd1FTqSZktpJIvVWUiCr+4" + - Mon, 11 Dec 2023 21:05:09 GMT + Etag: + - W/"2127-YHnC3gzOL0ZmKxkvuy3sFSaiOkc" Server: - nginx/1.18.0 (Ubuntu) Transfer-Encoding: diff --git a/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_income_statement_fetcher.yaml b/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_income_statement_fetcher.yaml index 998bdf2ce2f..cb4a3018d4e 100644 --- a/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_income_statement_fetcher.yaml +++ b/openbb_platform/providers/fmp/tests/record/http/test_fmp_fetchers/test_fmp_income_statement_fetcher.yaml @@ -3,7 +3,7 @@ interactions: body: null headers: Accept: - - '*/*' + - application/json Accept-Encoding: - gzip, deflate Connection: @@ -13,35 +13,35 @@ interactions: response: body: string: !!binary | - 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 - /uqf/wGZk7CFRh0AAA== + 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 + AeXdaJ1JHQAA headers: Access-Control-Allow-Credentials: - 'true' @@ -61,9 +61,9 @@ interactions: Content-Type: - application/json; charset=utf-8 Date: - - Wed, 01 Nov 2023 12:46:27 GMT - ETag: - - W/"1d46-yN2VjutbEgBJgPk7toO8f583lwY" + - Sun, 10 Dec 2023 00:02:05 GMT + Etag: + - W/"1d49-94qP+StcNwmpUfrQNBC/ePRH2UU" Server: - nginx/1.18.0 (Ubuntu) Transfer-Encoding: diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/__init__.py b/openbb_platform/providers/intrinio/openbb_intrinio/__init__.py index ace8efafc28..4dc357efc2d 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/__init__.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/__init__.py @@ -11,6 +11,7 @@ from openbb_intrinio.models.equity_historical import IntrinioEquityHistoricalFet from openbb_intrinio.models.equity_info import IntrinioEquityInfoFetcher from openbb_intrinio.models.equity_quote import IntrinioEquityQuoteFetcher from openbb_intrinio.models.equity_search import IntrinioEquitySearchFetcher +from openbb_intrinio.models.financial_ratios import IntrinioFinancialRatiosFetcher from openbb_intrinio.models.fred_series import IntrinioFredSeriesFetcher from openbb_intrinio.models.historical_attributes import ( IntrinioHistoricalAttributesFetcher, @@ -28,6 +29,7 @@ from openbb_intrinio.models.latest_attributes import IntrinioLatestAttributesFet from openbb_intrinio.models.market_indices import IntrinioMarketIndicesFetcher from openbb_intrinio.models.options_chains import IntrinioOptionsChainsFetcher from openbb_intrinio.models.options_unusual import IntrinioOptionsUnusualFetcher +from openbb_intrinio.models.reported_financials import IntrinioReportedFinancialsFetcher from openbb_intrinio.models.search_attributes import ( IntrinioSearchAttributesFetcher, ) @@ -51,6 +53,7 @@ intrinio_provider = Provider( "EquityInfo": IntrinioEquityInfoFetcher, "EquityQuote": IntrinioEquityQuoteFetcher, "EquitySearch": IntrinioEquitySearchFetcher, + "FinancialRatios": IntrinioFinancialRatiosFetcher, "FredSeries": IntrinioFredSeriesFetcher, "HistoricalAttributes": IntrinioHistoricalAttributesFetcher, "HistoricalDividends": IntrinioHistoricalDividendsFetcher, @@ -62,6 +65,7 @@ intrinio_provider = Provider( "MarketIndices": IntrinioMarketIndicesFetcher, "OptionsChains": IntrinioOptionsChainsFetcher, "OptionsUnusual": IntrinioOptionsUnusualFetcher, + "ReportedFinancials": IntrinioReportedFinancialsFetcher, "SearchAttributes": IntrinioSearchAttributesFetcher, "ShareStatistics": IntrinioShareStatisticsFetcher, "WorldNews": IntrinioWorldNewsFetcher, diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/models/balance_sheet.py b/openbb_platform/providers/intrinio/openbb_intrinio/models/balance_sheet.py index ed8c4ff5a71..402bcaf140c 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/models/balance_sheet.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/models/balance_sheet.py @@ -1,7 +1,7 @@ """Intrinio Balance Sheet Model.""" - -from typing import Any, Dict, List, Optional +import warnings +from typing import Any, Dict, List, Literal, Optional from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.balance_sheet import ( @@ -10,7 +10,9 @@ from openbb_core.provider.standard_models.balance_sheet import ( ) from openbb_core.provider.utils.helpers import ClientResponse, amake_requests from openbb_intrinio.utils.helpers import get_data_one -from pydantic import Field +from pydantic import Field, field_validator, model_validator + +_warn = warnings.warn class IntrinioBalanceSheetQueryParams(BalanceSheetQueryParams): @@ -20,79 +22,375 @@ class IntrinioBalanceSheetQueryParams(BalanceSheetQueryParams): Source: https://docs.intrinio.com/documentation/web_api/get_fundamental_standardized_financials_v2 """ + period: Literal["annual", "quarter"] = Field(default="annual") + fiscal_year: Optional[int] = Field( + default=None, + description="The specific fiscal year. Reports do not go beyond 2008.", + ) + + @field_validator("period", mode="after", check_fields=False) + @classmethod + def validate_period(cls, v): + """Validate period.""" + v = "FY" if v == "annual" else "QTR" + return v + + @field_validator("symbol", mode="after", check_fields=False) + @classmethod + def handle_symbol(cls, v) -> str: + """Handle symbols with a dash and replace it with a dot for Intrinio.""" + return v.replace("-", ".") + class IntrinioBalanceSheetData(BalanceSheetData): """Intrinio Balance Sheet Data.""" __alias_dict__ = { "cash_and_cash_equivalents": "cashandequivalents", + "restricted_cash": "restrictedcash", "short_term_investments": "shortterminvestments", + "federal_funds_sold": "fedfundssold", + "note_and_lease_receivable": "notereceivable", + "interest_bearing_deposits_at_other_banks": "interestbearingdepositsatotherbanks", "accounts_receivable": "accountsreceivable", - "net_inventory": "netinventory", + "time_deposits_placed_and_other_short_term_investments": "timedepositsplaced", + "inventories": "netinventory", + "trading_account_securities": "tradingaccountsecurities", + "prepaid_expenses": "prepaidexpenses", + "loans_and_leases": "loansandleases", + "allowance_for_loan_and_lease_losses": "allowanceforloanandleaselosses", + "current_deferred_refundable_income_taxes": "currentdeferredtaxassets", "other_current_assets": "othercurrentassets", + "loans_and_leases_net_of_allowance": "netloansandleases", + "other_current_non_operating_assets": "othercurrentnonoperatingassets", + "loans_held_for_sale": "loansheldforsale", "total_current_assets": "totalcurrentassets", + "accrued_investment_income": "accruedinvestmentincome", + "plant_property_equipment_gross": "grossppe", + "customer_and_other_receivables": "customerandotherreceivables", + "accumulated_depreciation": "accumulateddepreciation", + "premises_and_equipment_net": "netpremisesandequipment", + "plant_property_equipment_net": "netppe", + "mortgage_servicing_rights": "mortgageservicingrights", "long_term_investments": "longterminvestments", - "other_noncurrent_assets": "othernoncurrentassets", + "unearned_premiums_asset": "unearnedpremiumsdebit", + "non_current_note_lease_receivables": "noncurrentnotereceivables", + "deferred_acquisition_cost": "deferredacquisitioncost", + "goodwill": "goodwill", + "separate_account_business_assets": "separateaccountbusinessassets", + "intangible_assets": "intangibleassets", + "non_current_deferred_refundable_income_taxes": "noncurrentdeferredtaxassets", + "employee_benefit_assets": "employeebenefitassets", + "other_assets": "otherassets", + "other_non_current_operating_assets": "othernoncurrentassets", "total_assets": "totalassets", + "other_non_current_non_operating_assets": "othernoncurrentnonoperatingassets", + "non_interest_bearing_deposits": "noninterestbearingdeposits", + "interest_bearing_deposits": "interestbearingdeposits", + "total_non_current_assets": "totalnoncurrentassets", + "federal_funds_purchased_and_securities_sold": "fedfundspurchased", "short_term_debt": "shorttermdebt", + "bankers_acceptance_out_standing": "bankersacceptances", + "accrued_interest_payable": "accruedinterestpayable", "accounts_payable": "accountspayable", - "other_current_liabilities": "othercurrentliabilities", - "total_current_liabilities": "totalcurrentliabilities", + "accrued_expenses": "accruedexpenses", + "other_short_term_payables": "othershorttermpayables", "long_term_debt": "longtermdebt", + "customer_deposits": "customerdeposits", + "capital_lease_obligations": "capitalleaseobligations", + "dividends_payable": "dividendspayable", + "claims_and_claim_expense": "claimsandclaimexpenses", + "current_deferred_revenue": "currentdeferredrevenue", + "future_policy_benefits": "futurepolicybenefits", + "current_deferred_payable_income_tax_liabilities": "currentdeferredtaxliabilities", + "current_employee_benefit_liabilities": "currentemployeebenefitliabilities", + "unearned_premiums_liability": "unearnedpremiumscredit", + "other_taxes_payable": "othertaxespayable", + "policy_holder_funds": "policyholderfunds", + "other_current_liabilities": "othercurrentliabilities", + "participating_policy_holder_equity": "participatingpolicyholderequity", + "other_current_non_operating_liabilities": "othercurrentnonoperatingliabilities", + "separate_account_business_liabilities": "separateaccountbusinessliabilities", + "total_current_liabilities": "totalcurrentliabilities", + "other_long_term_liabilities": "otherlongtermliabilities", "total_liabilities": "totalliabilities", + "commitments_contingencies": "commitmentsandcontingencies", + "asset_retirement_reserve_litigation_obligation": "assetretirementandlitigationobligation", + "redeemable_non_controlling_interest": "redeemablenoncontrollinginterest", + "non_current_deferred_revenue": "noncurrentdeferredrevenue", + "preferred_stock": "totalpreferredequity", "common_stock": "commonequity", + "non_current_deferred_payable_income_tax_liabilities": "noncurrentdeferredtaxliabilities", + "non_current_employee_benefit_liabilities": "noncurrentemployeebenefitliabilities", "retained_earnings": "retainedearnings", - "total_equity": "totalequity", + "other_non_current_operating_liabilities": "othernoncurrentliabilities", + "treasury_stock": "treasurystock", + "accumulated_other_comprehensive_income": "aoci", + "other_non_current_non_operating_liabilities": "othernoncurrentnonoperatingliabilities", + "other_equity_adjustments": "otherequity", + "total_non_current_liabilities": "totalnoncurrentliabilities", + "total_common_equity": "totalcommonequity", + "total_preferred_common_equity": "totalequity", + "non_controlling_interest": "noncontrollinginterests", + "total_equity_non_controlling_interests": "totalequityandnoncontrollinginterests", + "total_liabilities_shareholders_equity": "totalliabilitiesandequity", } - note_receivable: Optional[float] = Field( - default=None, alias="notereceivable", description="Notes and lease receivable." + + cash_and_cash_equivalents: Optional[int] = Field( + description="Cash and cash equivalents.", default=None ) - net_ppe: Optional[float] = Field( - default=None, alias="netppe", description="Plant, property, and equipment, net." + cash_and_due_from_banks: Optional[int] = Field( + description="Cash and due from banks.", default=None ) - total_noncurrent_assets: Optional[float] = Field( + restricted_cash: Optional[int] = Field(description="Restricted cash.", default=None) + short_term_investments: Optional[int] = Field( + description="Short term investments.", default=None + ) + federal_funds_sold: Optional[int] = Field( + description="Federal funds sold.", default=None + ) + accounts_receivable: Optional[int] = Field( + description="Accounts receivable.", default=None + ) + note_and_lease_receivable: Optional[int] = Field( + description="Note and lease receivable. (Vendor non-trade receivables)", default=None, - alias="totalnoncurrentassets", - description="Total noncurrent assets.", ) - current_deferred_revenue: Optional[float] = Field( + inventories: Optional[int] = Field(description="Net Inventories.", default=None) + customer_and_other_receivables: Optional[int] = Field( + description="Customer and other receivables.", default=None + ) + interest_bearing_deposits_at_other_banks: Optional[int] = Field( + description="Interest bearing deposits at other banks.", default=None + ) + time_deposits_placed_and_other_short_term_investments: Optional[int] = Field( + description="Time deposits placed and other short term investments.", default=None, - alias="currentdeferredrevenue", - description="Current deferred revenue.", ) - other_noncurrent_liabilities: Optional[float] = Field( - default=None, - alias="othernoncurrentliabilities", - description="Other noncurrent operating liabilities.", + trading_account_securities: Optional[int] = Field( + description="Trading account securities.", default=None ) - total_noncurrent_liabilities: Optional[float] = Field( - default=None, - alias="totalnoncurrentliabilities", - description="Total noncurrent liabilities.", + loans_and_leases: Optional[int] = Field( + description="Loans and leases.", default=None ) - commitments_and_contingencies: Optional[float] = Field( - default=None, - alias="commitmentsandcontingencies", - description="Commitments and contingencies.", + allowance_for_loan_and_lease_losses: Optional[int] = Field( + description="Allowance for loan and lease losses.", default=None ) - aoci: Optional[float] = Field( - default=None, - alias="aoci", - description="Accumulated other comprehensive income / (loss).", + current_deferred_refundable_income_taxes: Optional[int] = Field( + description="Current deferred refundable income taxes.", default=None ) - total_common_equity: Optional[float] = Field( - default=None, alias="totalcommonequity", description="Total common equity." + other_current_assets: Optional[int] = Field( + description="Other current assets.", default=None ) - total_equity_and_noncontrolling_interests: Optional[float] = Field( - default=None, - alias="totalequityandnoncontrollinginterests", - description="Total equity & noncontrolling interests.", + loans_and_leases_net_of_allowance: Optional[int] = Field( + description="Loans and leases net of allowance.", default=None ) - total_liabilities_and_equity: Optional[float] = Field( - default=None, - alias="totalliabilitiesandequity", - description="Total liabilities & shareholders' equity.", + accrued_investment_income: Optional[int] = Field( + description="Accrued investment income.", default=None ) + other_current_non_operating_assets: Optional[int] = Field( + description="Other current non-operating assets.", default=None + ) + loans_held_for_sale: Optional[int] = Field( + description="Loans held for sale.", default=None + ) + prepaid_expenses: Optional[int] = Field( + description="Prepaid expenses.", default=None + ) + total_current_assets: Optional[int] = Field( + description="Total current assets.", default=None + ) + plant_property_equipment_gross: Optional[int] = Field( + description="Plant property equipment gross.", default=None + ) + accumulated_depreciation: Optional[int] = Field( + description="Accumulated depreciation.", default=None + ) + premises_and_equipment_net: Optional[int] = Field( + description="Net premises and equipment.", default=None + ) + plant_property_equipment_net: Optional[int] = Field( + description="Net plant property equipment.", default=None + ) + long_term_investments: Optional[int] = Field( + description="Long term investments.", default=None + ) + mortgage_servicing_rights: Optional[int] = Field( + description="Mortgage servicing rights.", default=None + ) + unearned_premiums_asset: Optional[int] = Field( + description="Unearned premiums asset.", default=None + ) + non_current_note_lease_receivables: Optional[int] = Field( + description="Non-current note lease receivables.", default=None + ) + deferred_acquisition_cost: Optional[int] = Field( + description="Deferred acquisition cost.", default=None + ) + goodwill: Optional[int] = Field(description="Goodwill.", default=None) + separate_account_business_assets: Optional[int] = Field( + description="Separate account business assets.", default=None + ) + non_current_deferred_refundable_income_taxes: Optional[int] = Field( + description="Noncurrent deferred refundable income taxes.", default=None + ) + intangible_assets: Optional[int] = Field( + description="Intangible assets.", default=None + ) + employee_benefit_assets: Optional[int] = Field( + description="Employee benefit assets.", default=None + ) + other_assets: Optional[int] = Field(description="Other assets.", default=None) + other_non_current_operating_assets: Optional[int] = Field( + description="Other noncurrent operating assets.", default=None + ) + other_non_current_non_operating_assets: Optional[int] = Field( + description="Other noncurrent non-operating assets.", default=None + ) + interest_bearing_deposits: Optional[int] = Field( + description="Interest bearing deposits.", default=None + ) + total_non_current_assets: Optional[int] = Field( + description="Total noncurrent assets.", default=None + ) + total_assets: Optional[int] = Field(description="Total assets.", default=None) + non_interest_bearing_deposits: Optional[int] = Field( + description="Non interest bearing deposits.", default=None + ) + federal_funds_purchased_and_securities_sold: Optional[int] = Field( + description="Federal funds purchased and securities sold.", default=None + ) + bankers_acceptance_outstanding: Optional[int] = Field( + description="Bankers acceptance outstanding.", default=None + ) + short_term_debt: Optional[int] = Field(description="Short term debt.", default=None) + accounts_payable: Optional[int] = Field( + description="Accounts payable.", default=None + ) + current_deferred_revenue: Optional[int] = Field( + description="Current deferred revenue.", default=None + ) + current_deferred_payable_income_tax_liabilities: Optional[int] = Field( + description="Current deferred payable income tax liabilities.", default=None + ) + accrued_interest_payable: Optional[int] = Field( + description="Accrued interest payable.", default=None + ) + accrued_expenses: Optional[int] = Field( + description="Accrued expenses.", default=None + ) + other_short_term_payables: Optional[int] = Field( + description="Other short term payables.", default=None + ) + customer_deposits: Optional[int] = Field( + description="Customer deposits.", default=None + ) + dividends_payable: Optional[int] = Field( + description="Dividends payable.", default=None + ) + claims_and_claim_expense: Optional[int] = Field( + description="Claims and claim expense.", default=None + ) + future_policy_benefits: Optional[int] = Field( + description="Future policy benefits.", default=None + ) + current_employee_benefit_liabilities: Optional[int] = Field( + description="Current employee benefit liabilities.", default=None + ) + unearned_premiums_liability: Optional[int] = Field( + description="Unearned premiums liability.", default=None + ) + other_taxes_payable: Optional[int] = Field( + description="Other taxes payable.", default=None + ) + policy_holder_funds: Optional[int] = Field( + description="Policy holder funds.", default=None + ) + other_current_liabilities: Optional[int] = Field( + description="Other current liabilities.", default=None + ) + other_current_non_operating_liabilities: Optional[int] = Field( + description="Other current non-operating liabilities.", default=None + ) + separate_account_business_liabilities: Optional[int] = Field( + description="Separate account business liabilities.", default=None + ) + total_current_liabilities: Optional[int] = Field( + description="Total current liabilities.", default=None + ) + long_term_debt: Optional[int] = Field(description="Long term debt.", default=None) + other_long_term_liabilities: Optional[int] = Field( + description="Other long term liabilities.", default=None + ) + non_current_deferred_revenue: Optional[int] = Field( + description="Non-current deferred revenue.", default=None + ) + non_current_deferred_payable_income_tax_liabilities: Optional[int] = Field( + description="Non-current deferred payable income tax liabilities.", default=None + ) + non_current_employee_benefit_liabilities: Optional[int] = Field( + description="Non-current employee benefit liabilities.", default=None + ) + other_non_current_operating_liabilities: Optional[int] = Field( + description="Other non-current operating liabilities.", default=None + ) + other_non_current_non_operating_liabilities: Optional[int] = Field( + description="Other non-current, non-operating liabilities.", default=None + ) + total_non_current_liabilities: Optional[int] = Field( + description="Total non-current liabilities.", default=None + ) + capital_lease_obligations: Optional[int] = Field( + description="Capital lease obligations.", default=None + ) + asset_retirement_reserve_litigation_obligation: Optional[int] = Field( + description="Asset retirement reserve litigation obligation.", default=None + ) + total_liabilities: Optional[int] = Field( + description="Total liabilities.", default=None + ) + commitments_contingencies: Optional[int] = Field( + description="Commitments contingencies.", default=None + ) + redeemable_non_controlling_interest: Optional[int] = Field( + description="Redeemable non-controlling interest.", default=None + ) + preferred_stock: Optional[int] = Field(description="Preferred stock.", default=None) + common_stock: Optional[int] = Field(description="Common stock.", default=None) + retained_earnings: Optional[int] = Field( + description="Retained earnings.", default=None + ) + treasury_stock: Optional[int] = Field(description="Treasury stock.", default=None) + accumulated_other_comprehensive_income: Optional[int] = Field( + description="Accumulated other comprehensive income.", default=None + ) + participating_policy_holder_equity: Optional[int] = Field( + description="Participating policy holder equity.", default=None + ) + other_equity_adjustments: Optional[int] = Field( + description="Other equity adjustments.", default=None + ) + total_common_equity: Optional[int] = Field( + description="Total common equity.", default=None + ) + total_preferred_common_equity: Optional[int] = Field( + description="Total preferred common equity.", default=None + ) + non_controlling_interest: Optional[int] = Field( + description="Non-controlling interest.", default=None + ) + total_equity_non_controlling_interests: Optional[int] = Field( + description="Total equity non-controlling interests.", default=None + ) + total_liabilities_shareholders_equity: Optional[int] = Field( + description="Total liabilities and shareholders equity.", default=None + ) + + @model_validator(mode="before") + @classmethod + def replace_zero(cls, values): # pylint: disable=no-self-argument + """Check for zero values and replace with None.""" + return {k: None if v == 0 else v for k, v in values.items()} class IntrinioBalanceSheetFetcher( @@ -117,14 +415,19 @@ class IntrinioBalanceSheetFetcher( """Return the raw data from the Intrinio endpoint.""" api_key = credentials.get("intrinio_api_key") if credentials else "" statement_code = "balance_sheet_statement" - period_type = "FY" if query.period == "annual" else "QTR" + fundamentals_data: Dict = {} base_url = "https://api-v2.intrinio.com" - fundamentals_url = ( f"{base_url}/companies/{query.symbol}/fundamentals?" - f"statement_code={statement_code}&type={period_type}&api_key={api_key}" + f"statement_code={statement_code}&type={query.period}" ) + if query.fiscal_year is not None: + if query.fiscal_year < 2008: + _warn("Financials data is only available from 2008 and later.") + query.fiscal_year = 2008 + fundamentals_url = fundamentals_url + f"&fiscal_year={query.fiscal_year}" + fundamentals_url = fundamentals_url + f"&api_key={api_key}" fundamentals_data = (await get_data_one(fundamentals_url, **kwargs)).get( "fundamentals", [] ) @@ -139,8 +442,9 @@ class IntrinioBalanceSheetFetcher( """Return the response.""" statement_data = await response.json() return { - "date": statement_data["fundamental"]["end_date"], - "period": statement_data["fundamental"]["fiscal_period"], + "period_ending": statement_data["fundamental"]["end_date"], + "fiscal_year": statement_data["fundamental"]["fiscal_year"], + "fiscal_period": statement_data["fundamental"]["fiscal_period"], "financials": statement_data["standardized_financials"], } @@ -163,14 +467,19 @@ class IntrinioBalanceSheetFetcher( for sub_item in item["financials"]: field_name = sub_item["data_tag"]["tag"] - sub_dict[field_name] = float(sub_item["value"]) + sub_dict[field_name] = ( + float(sub_item["value"]) + if sub_item["value"] and sub_item["value"] != 0 + else None + ) - sub_dict["date"] = item["date"] - sub_dict["period"] = item["period"] + sub_dict["period_ending"] = item["period_ending"] + sub_dict["fiscal_year"] = item["fiscal_year"] + sub_dict["fiscal_period"] = item["fiscal_period"] # Intrinio does not return Q4 data but FY data instead - if query.period == "quarter" and item["period"] == "FY": - sub_dict["period"] = "Q4" + if query.period == "QTR" and item["fiscal_period"] == "FY": + sub_dict["fiscal_period"] = "Q4" transformed_data.append(IntrinioBalanceSheetData(**sub_dict)) diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/models/cash_flow.py b/openbb_platform/providers/intrinio/openbb_intrinio/models/cash_flow.py index d349f339e8a..5be657439f4 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/models/cash_flow.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/models/cash_flow.py @@ -1,7 +1,7 @@ """Intrinio Cash Flow Statement Model.""" - -from typing import Any, Dict, List, Optional +import warnings +from typing import Any, Dict, List, Literal, Optional from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.cash_flow import ( @@ -10,7 +10,9 @@ from openbb_core.provider.standard_models.cash_flow import ( ) from openbb_core.provider.utils.helpers import ClientResponse, amake_requests from openbb_intrinio.utils.helpers import get_data_one -from pydantic import Field +from pydantic import Field, field_validator, model_validator + +_warn = warnings.warn class IntrinioCashFlowStatementQueryParams(CashFlowStatementQueryParams): @@ -20,76 +22,202 @@ class IntrinioCashFlowStatementQueryParams(CashFlowStatementQueryParams): Source: https://docs.intrinio.com/documentation/web_api/get_fundamental_standardized_financials_v2 """ + period: Literal["annual", "quarter", "ttm", "ytd"] = Field(default="annual") + fiscal_year: Optional[int] = Field( + default=None, + description="The specific fiscal year. Reports do not go beyond 2008.", + ) + + @field_validator("symbol", mode="after", check_fields=False) + @classmethod + def handle_symbol(cls, v) -> str: + """Handle symbols with a dash and replace it with a dot for Intrinio.""" + return v.replace("-", ".") + class IntrinioCashFlowStatementData(CashFlowStatementData): """Intrinio Cash Flow Statement Data.""" __alias_dict__ = { + "cash_and_equivalents": "cashandequivalents", + "acquisitions": "acquisitions", + "amortization_expense": "amortizationexpense", + "cash_income_taxes_paid": "cashincometaxespaid", + "cash_interest_paid": "cashinterestpaid", + "cash_interest_received": "cashinterestreceived", + "depreciation_expense": "depreciationexpense", + "divestitures": "divestitures", + "effect_of_exchange_rate_changes": "effectofexchangeratechanges", + "changes_in_operating_assets_and_liabilities": "increasedecreaseinoperatingcapital", + "issuance_of_common_equity": "issuanceofcommonequity", + "issuance_of_debt": "issuanceofdebt", + "issuance_of_preferred_equity": "issuanceofpreferredequity", + "loans_held_for_sale": "loansheldforsalenet", + "net_cash_from_continuing_financing_activities": "netcashfromcontinuingfinancingactivities", + "net_cash_from_continuing_investing_activities": "netcashfromcontinuinginvestingactivities", + "net_cash_from_continuing_operating_activities": "netcashfromcontinuingoperatingactivities", + "net_cash_from_discontinued_financing_activities": "netcashfromdiscontinuedfinancingactivities", + "net_cash_from_discontinued_investing_activities": "netcashfromdiscontinuedinvestingactivities", + "net_cash_from_discontinued_operating_activities": "netcashfromdiscontinuedoperatingactivities", + "net_cash_from_financing_activities": "netcashfromfinancingactivities", + "net_cash_from_investing_activities": "netcashfrominvestingactivities", + "net_cash_from_operating_activities": "netcashfromoperatingactivities", + "net_change_in_cash_and_equivalents": "netchangeincash", + "net_change_in_deposits": "netchangeindeposits", "net_income": "netincome", - "depreciation_and_amortization": "depreciationexpense", - "other_non_cash_items": "noncashadjustmentstonetincome", - "accounts_receivables": "IncreaseDecreaseInAccountsReceivable", - "inventory": "IncreaseDecreaseInInventories", - "vendor_non_trade_receivables": "IncreaseDecreaseInOtherReceivables", - "other_current_and_non_current_assets": "IncreaseDecreaseInOtherOperatingAssets", - "accounts_payables": "IncreaseDecreaseInAccountsPayable", - "deferred_revenue": "IncreaseDecreaseInContractWithCustomerLiability", - "other_current_and_non_current_liabilities": "IncreaseDecreaseInOtherOperatingLiabilities", - "net_cash_flow_from_operating_activities": "netcashfromoperatingactivities", - "purchases_of_marketable_securities": "purchaseofinvestments", - "sales_from_maturities_of_investments": "saleofinvestments", - "investments_in_property_plant_and_equipment": "purchaseofplantpropertyandequipment", - "payments_from_acquisitions": "acquisitions", - "other_investing_activities": "otherinvestingactivitiesnet", - "net_cash_flow_from_investing_activities": "netcashfrominvestingactivities", - "dividends_paid": "paymentofdividends", - "common_stock_repurchased": "repurchaseofcommonequity", - "debt_proceeds": "issuanceofdebt", - "debt_repayment": "repaymentofdebt", + "net_income_continuing_operations": "netincomecontinuing", + "net_income_discontinued_operations": "netincomediscontinued", + "net_increase_in_fed_funds_sold": "netincreaseinfedfundssold", + "non_cash_adjustments_to_reconcile_net_income": "noncashadjustmentstonetincome", "other_financing_activities": "otherfinancingactivitiesnet", - "net_cash_flow_from_financing_activities": "netcashfromfinancingactivities", - "net_change_in_cash": "netchangeincash", + "other_investing_activities": "otherinvestingactivitiesnet", + "other_net_changes_in_cash": "othernetchangesincash", + "payment_of_dividends": "paymentofdividends", + "provision_for_loan_losses": "provisionforloanlosses", + "purchase_of_investments": "purchaseofinvestments", + "purchase_of_investment_securities": "purchaseofinvestments", + "purchase_of_property_plant_and_equipment": "purchaseofplantpropertyandequipment", + "repayment_of_debt": "repaymentofdebt", + "repurchase_of_common_equity": "repurchaseofcommonequity", + "repurchase_of_preferred_equity": "repurchaseofpreferredequity", + "sale_and_maturity_of_investments": "saleofinvestments", + "sale_of_property_plant_and_equipment": "saleofplantpropertyandequipment", } - changes_in_operating_assets_and_liabilities: Optional[float] = Field( - None, - alias="increasedecreaseinoperatingcapital", - description="Changes in operating assets and liabilities.", + net_income: Optional[float] = Field( + default=None, description="Consolidated Net Income." ) - - net_income_continuing: Optional[float] = Field( - default=None, - alias="netincomecontinuing", - description="Net income from continuing operations.", + provision_for_loan_losses: Optional[float] = Field( + default=None, description="Provision for Loan Losses" + ) + provision_for_credit_losses: Optional[float] = Field( + default=None, description="Provision for credit losses" + ) + depreciation_expense: Optional[float] = Field( + default=None, description="Depreciation Expense." + ) + amortization_expense: Optional[float] = Field( + default=None, description="Amortization Expense." + ) + share_based_compensation: Optional[float] = Field( + default=None, description="Share-based compensation." + ) + non_cash_adjustments_to_reconcile_net_income: Optional[float] = Field( + default=None, description="Non-Cash Adjustments to Reconcile Net Income." + ) + changes_in_operating_assets_and_liabilities: Optional[float] = Field( + default=None, description="Changes in Operating Assets and Liabilities (Net)" ) net_cash_from_continuing_operating_activities: Optional[float] = Field( - default=None, - alias="netcashfromcontinuingoperatingactivities", - description="Net cash from continuing operating activities.", + default=None, description="Net Cash from Continuing Operating Activities" + ) + net_cash_from_discontinued_operating_activities: Optional[float] = Field( + default=None, description="Net Cash from Discontinued Operating Activities" + ) + net_income_continuing_operations: Optional[float] = Field( + default=None, description="Net Income (Continuing Operations)" + ) + net_income_discontinued_operations: Optional[float] = Field( + default=None, description="Net Income (Discontinued Operations)" + ) + net_cash_from_operating_activities: Optional[float] = Field( + default=None, description="Net Cash from Operating Activities" + ) + divestitures: Optional[float] = Field(default=None, description="Divestitures") + sale_of_property_plant_and_equipment: Optional[float] = Field( + default=None, description="Sale of Property, Plant, and Equipment" + ) + acquisitions: Optional[float] = Field(default=None, description="Acquisitions") + purchase_of_investments: Optional[float] = Field( + default=None, description="Purchase of Investments" + ) + purchase_of_investment_securities: Optional[float] = Field( + default=None, description="Purchase of Investment Securities" + ) + sale_and_maturity_of_investments: Optional[float] = Field( + default=None, description="Sale and Maturity of Investments" + ) + loans_held_for_sale: Optional[float] = Field( + default=None, description="Loans Held for Sale (Net)" + ) + purchase_of_property_plant_and_equipment: Optional[float] = Field( + default=None, description="Purchase of Property, Plant, and Equipment" + ) + other_investing_activities: Optional[float] = Field( + default=None, description="Other Investing Activities (Net)" ) net_cash_from_continuing_investing_activities: Optional[float] = Field( - default=None, - alias="netcashfromcontinuinginvestingactivities", - description="Net cash from continuing investing activities.", + default=None, description="Net Cash from Continuing Investing Activities" ) - net_cash_from_continuing_financing_activities: Optional[float] = Field( - default=None, - alias="netcashfromcontinuingfinancingactivities", - description="Net cash from continuing financing activities.", + net_cash_from_discontinued_investing_activities: Optional[float] = Field( + default=None, description="Net Cash from Discontinued Investing Activities" ) - cash_interest_paid: Optional[float] = Field( - default=None, alias="cashinterestpaid", description="Cash paid for interest." + net_cash_from_investing_activities: Optional[float] = Field( + default=None, description="Net Cash from Investing Activities" ) - cash_income_taxes_paid: Optional[float] = Field( - default=None, - alias="cashincometaxespaid", - description="Cash paid for income taxes.", + payment_of_dividends: Optional[float] = Field( + default=None, description="Payment of Dividends" + ) + repurchase_of_common_equity: Optional[float] = Field( + default=None, description="Repurchase of Common Equity" + ) + repurchase_of_preferred_equity: Optional[float] = Field( + default=None, description="Repurchase of Preferred Equity" ) issuance_of_common_equity: Optional[float] = Field( - default=None, - alias="issuanceofcommonequity", - description="Issuance of common equity.", + default=None, description="Issuance of Common Equity" ) + issuance_of_preferred_equity: Optional[float] = Field( + default=None, description="Issuance of Preferred Equity" + ) + issuance_of_debt: Optional[float] = Field( + default=None, description="Issuance of Debt" + ) + repayment_of_debt: Optional[float] = Field( + default=None, description="Repayment of Debt" + ) + other_financing_activities: Optional[float] = Field( + default=None, description="Other Financing Activities (Net)" + ) + cash_interest_received: Optional[float] = Field( + default=None, description="Cash Interest Received" + ) + net_change_in_deposits: Optional[float] = Field( + default=None, description="Net Change in Deposits" + ) + net_increase_in_fed_funds_sold: Optional[float] = Field( + default=None, description="Net Increase in Fed Funds Sold" + ) + net_cash_from_continuing_financing_activities: Optional[float] = Field( + default=None, description="Net Cash from Continuing Financing Activities" + ) + net_cash_from_discontinued_financing_activities: Optional[float] = Field( + default=None, description="Net Cash from Discontinued Financing Activities" + ) + net_cash_from_financing_activities: Optional[float] = Field( + default=None, description="Net Cash from Financing Activities" + ) + effect_of_exchange_rate_changes: Optional[float] = Field( + default=None, description="Effect of Exchange Rate Changes" + ) + other_net_changes_in_cash: Optional[float] = Field( + default=None, description="Other Net Changes in Cash" + ) + net_change_in_cash_and_equivalents: Optional[float] = Field( + default=None, description="Net Change in Cash and Equivalents" + ) + cash_income_taxes_paid: Optional[float] = Field( + default=None, description="Cash Income Taxes Paid" + ) + cash_interest_paid: Optional[float] = Field( + default=None, description="Cash Interest Paid" + ) + + @model_validator(mode="before") + @classmethod + def replace_zero(cls, values): # pylint: disable=no-self-argument + """Check for zero values and replace with None.""" + return {k: None if v == 0 else v for k, v in values.items()} class IntrinioCashFlowStatementFetcher( @@ -112,16 +240,25 @@ class IntrinioCashFlowStatementFetcher( **kwargs: Any, ) -> List[Dict]: """Return the raw data from the Intrinio endpoint.""" + api_key = credentials.get("intrinio_api_key") if credentials else "" statement_code = "cash_flow_statement" - period_type = "FY" if query.period == "annual" else "QTR" + if query.period in ["quarter", "annual"]: + period_type = "FY" if query.period == "annual" else "QTR" + if query.period in ["ttm", "ytd"]: + period_type = query.period.upper() base_url = "https://api-v2.intrinio.com" - fundamentals_url = ( f"{base_url}/companies/{query.symbol}/fundamentals?" - f"statement_code={statement_code}&type={period_type}&api_key={api_key}" + f"statement_code={statement_code}&type={period_type}" ) + if query.fiscal_year is not None: + if query.fiscal_year < 2008: + _warn("Financials data is only available from 2008 and later.") + query.fiscal_year = 2008 + fundamentals_url = fundamentals_url + f"&fiscal_year={query.fiscal_year}" + fundamentals_url = fundamentals_url + f"&api_key={api_key}" fundamentals_data = (await get_data_one(fundamentals_url, **kwargs)).get( "fundamentals", [] ) @@ -136,8 +273,9 @@ class IntrinioCashFlowStatementFetcher( """Return the response.""" statement_data = await response.json() return { - "date": statement_data["fundamental"]["end_date"], - "period": statement_data["fundamental"]["fiscal_period"], + "period_ending": statement_data["fundamental"]["end_date"], + "fiscal_period": statement_data["fundamental"]["fiscal_period"], + "fiscal_year": statement_data["fundamental"]["fiscal_year"], "financials": statement_data["standardized_financials"], } @@ -155,20 +293,20 @@ class IntrinioCashFlowStatementFetcher( ) -> List[IntrinioCashFlowStatementData]: """Return the transformed data.""" transformed_data: List[IntrinioCashFlowStatementData] = [] - for item in data: sub_dict: Dict[str, Any] = {} for sub_item in item["financials"]: field_name = sub_item["data_tag"]["tag"] - sub_dict[field_name] = float(sub_item["value"]) + sub_dict[field_name] = ( + float(sub_item["value"]) + if sub_item["value"] and sub_item["value"] != 0 + else None + ) - sub_dict["date"] = item["date"] - sub_dict["period"] = item["period"] - - # Intrinio does not return Q4 data but FY data instead - if query.period == "quarter" and item["period"] == "FY": - sub_dict["period"] = "Q4" + sub_dict["period_ending"] = item["period_ending"] + sub_dict["fiscal_year"] = item["fiscal_year"] + sub_dict["fiscal_period"] = item["fiscal_period"] transformed_data.append(IntrinioCashFlowStatementData(**sub_dict)) diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/models/financial_ratios.py b/openbb_platform/providers/intrinio/openbb_intrinio/models/financial_ratios.py new file mode 100644 index 00000000000..28cba446a2e --- /dev/null +++ b/openbb_platform/providers/intrinio/openbb_intrinio/models/financial_ratios.py @@ -0,0 +1,315 @@ +"""Intrinio Financial Ratios Model.""" + +import warnings +from typing import Any, Dict, List, Literal, Optional + +from openbb_core.provider.abstract.fetcher import Fetcher +from openbb_core.provider.standard_models.financial_ratios import ( + FinancialRatiosData, + FinancialRatiosQueryParams, +) +from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS +from openbb_core.provider.utils.helpers import ClientResponse, amake_requests +from openbb_intrinio.utils.helpers import get_data_one +from pydantic import Field, field_validator + +_warn = warnings.warn + + +class IntrinioFinancialRatiosQueryParams(FinancialRatiosQueryParams): + """Intrinio Financial Ratios Query. + + Source: https://docs.intrinio.com/documentation/web_api/get_company_fundamentals_v2 + Source: https://docs.intrinio.com/documentation/web_api/get_fundamental_standardized_financials_v2 + """ + + period: Literal["annual", "quarter", "ttm", "ytd"] = Field( + default="annual", + description=QUERY_DESCRIPTIONS.get("period", ""), + ) + fiscal_year: Optional[int] = Field( + default=None, + description="The specific fiscal year. Reports do not go beyond 2008.", + ) + + @field_validator("symbol", mode="after", check_fields=False) + @classmethod + def handle_symbol(cls, v) -> str: + """Handle symbols with a dash and replace it with a dot for Intrinio.""" + return v.replace("-", ".") + + +class IntrinioFinancialRatiosData(FinancialRatiosData): + """Intrinio Financial Ratios Data.""" + + __alias_dict__ = { + "net_operating_profit_after_tax_margin": "nopatmargin", + "invested_capital_turnover": "investedcapitalturnover", + "book_value_per_share": "bookvaluepershare", + "tangible_book_value": "tangiblebookvaluepershare", + "price_to_book_ratio": "pricetobook", + "price_to_tangible_book_ratio": "pricetotangiblebook", + "price_to_revenue": "pricetorevenue", + "price_to_earnings": "pricetoearnings", + "dividend_yield": "dividendyield", + "earnings_yield": "earningsyield", + "ev_to_invested_capital": "evtoinvestedcapital", + "ev_to_sales": "evtorevenue", + "ev_to_ebitda": "evtoebitda", + "ev_to_ebit": "evtoebit", + "ev_to_nopat": "evtonopat", + "ev_to_operating_cash_flow": "evtoocf", + "ev_to_free_cash_flow": "evtofcff", + "gross_margin": "grossmargin", + "ebitda_margin": "ebitdamargin", + "operating_margin": "operatingmargin", + "ebit_margin": "ebitmargin", + "net_profit_margin": "profitmargin", + "cost_of_rev_to_revenue": "costofrevtorevenue", + "sga_expense_to_revenue": "sgaextorevenue", + "rd_expense_to_revenue": "rdextorevenue", + "op_expense_to_revenue": "opextorevenue", + "tax_burden_percent": "taxburdenpct", + "interest_burden_percent": "interestburdenpct", + "effective_tax_rate": "efftaxrate", + "asset_turnover": "assetturnover", + "receivables_turnover": "arturnover", + "inventory_turnover": "invturnover", + "fixed_asset_turnover": "faturnover", + "payables_turnover": "apturnover", + "days_of_sales_outstanding": "dso", + "days_of_inventory_outstanding": "dio", + "days_payable_outstanding": "dpo", + "cash_conversion_cycle": "ccc", + "financial_leverage": "finleverage", + "leverage_ratio": "leverageratio", + "compound_leverage_factor": "compoundleveragefactor", + "long_term_debt_equity_ratio": "ltdebttoequity", + "debt_equity_ratio": "debttoequity", + "return_on_invested_capital": "roic", + "net_non_operating_expense_percent": "nnep", + "roic_nnep_spread": "roicnnepspread", + "return_on_net_non_operating_assets": "rnnoa", + "return_on_equity": "roe", + "cash_returned_on_invested_capitals": "croic", + "operating_return_on_assets": "oroa", + "return_on_assets": "roa", + "non_controlling_interest_sharing_ratio": "noncontrollinginterestsharingratio", + "return_on_common_equity": "roce", + "dividend_payout_ratio": "divpayoutratio", + "augmented_payout_ratio": "augmentedpayoutratio", + "operating_cash_flow_to_capex": "ocftocapex", + "short_term_debt_to_capitalization": "stdebttocap", + "long_term_debt_to_capitalization": "ltdebttocap", + "debt_to_capitalization": "debttototalcapital", + "preferred_equity_to_capitalization": "preferredtocap", + "non_controlling_interests_to_capitalization": "noncontrolinttocap", + "equity_to_capitalization": "commontocap", + "debt_to_ebitda": "debttoebitda", + "net_debt_to_ebitda": "netdebttoebitda", + "long_term_debt_to_ebita": "ltdebttoebitda", + "debt_to_nopat": "debttonopat", + "net_debt_to_nopat": "netdebttonopat", + "long_term_debt_to_nopat": "ltdebttonopat", + "altman_z_score": "altmanzscore", + "ebit_to_interest_expense": "ebittointerestex", + "nopat_to_intersest_expense": "nopattointerestex", + "ebit_less_capex_to_interest_expense": "ebitlesscapextointerestex", + "nopat_less_capex_to_interest_expense": "nopatlesscapextointex", + "operating_cash_flow_to_interest_expense": "ocftointerestex", + "operating_cash_flow_less_capex_to_interest_expense": "ocflesscapextointerestex", + "free_cash_flow_to_interest_expense": "fcfftointerestex", + "current_ratio": "curratio", + "quick_ratio": "quickratio", + "debt_free_cash_free_nwc_to_revenue": "dfcfnwctorev", + "debt_free_nwc_to_revenue": "dfnwctorev", + "net_working_capital_to_revenue": "nwctorev", + "normalized_nopat_margin": "normalizednopatmargin", + "pre_tax_income_margin": "pretaxincomemargin", + "adjusted_basic_eps": "adjbasiceps", + "adjusted_diluted_eps": "adjdilutedeps", + "adjusted_basic_diluted_eps": "adjbasicdilutedeps", + "return_on_equity_simple": "roe_simple", + } + + +class IntrinioFinancialRatiosFetcher( + Fetcher[ + IntrinioFinancialRatiosQueryParams, + List[IntrinioFinancialRatiosData], + ] +): + """Transform the query, extract and transform the data from the Intrinio endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> IntrinioFinancialRatiosQueryParams: + """Transform the query params.""" + return IntrinioFinancialRatiosQueryParams(**params) + + @staticmethod + async def aextract_data( + query: IntrinioFinancialRatiosQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the Intrinio endpoint.""" + + api_key = credentials.get("intrinio_api_key") if credentials else "" + statement_code = "calculations" + if query.period in ["quarter", "annual"]: + period_type = "FY" if query.period == "annual" else "QTR" + if query.period in ["ttm", "ytd"]: + period_type = query.period.upper() + + fundamentals_data: Dict = {} + + base_url = "https://api-v2.intrinio.com" + fundamentals_url = ( + f"{base_url}/companies/{query.symbol}/fundamentals?" + f"statement_code={statement_code}&type={period_type}" + ) + if query.fiscal_year is not None: + if query.fiscal_year < 2008: + _warn("Financials data is only available from 2008 and later.") + query.fiscal_year = 2008 + fundamentals_url = fundamentals_url + f"&fiscal_year={query.fiscal_year}" + fundamentals_url = fundamentals_url + f"&api_key={api_key}" + fundamentals_data = (await get_data_one(fundamentals_url, **kwargs)).get( + "fundamentals", [] + ) + ids = [item["id"] for item in fundamentals_data] + ids = ids[: query.limit] + + async def callback(response: ClientResponse, _: Any) -> Dict: + """Return the response.""" + statement_data = await response.json() + return { + "period_ending": statement_data["fundamental"]["end_date"], + "fiscal_year": statement_data["fundamental"]["fiscal_year"], + "fiscal_period": statement_data["fundamental"]["fiscal_period"], + "calculations": statement_data["standardized_financials"], + } + + urls = [ + f"https://api-v2.intrinio.com/fundamentals/{id}/standardized_financials?api_key={api_key}" + for id in ids + ] + + return await amake_requests(urls, callback, **kwargs) + + @staticmethod + def transform_data( + query: IntrinioFinancialRatiosQueryParams, data: List[Dict], **kwargs: Any + ) -> List[IntrinioFinancialRatiosData]: + """Return the transformed data.""" + transformed_data: List[IntrinioFinancialRatiosData] = [] + + tags = [ + "nopatmargin", + "investedcapitalturnover", + "bookvaluepershare", + "tangiblebookvaluepershare", + "pricetobook", + "pricetotangiblebook", + "pricetorevenue", + "pricetoearnings", + "dividendyield", + "earningsyield", + "evtoinvestedcapital", + "evtorevenue", + "evtoebitda", + "evtoebit", + "evtonopat", + "evtoocf", + "evtofcff", + "grossmargin", + "ebitdamargin", + "operatingmargin", + "ebitmargin", + "profitmargin", + "costofrevtorevenue", + "sgaextorevenue", + "rdextorevenue", + "opextorevenue", + "taxburdenpct", + "interestburdenpct", + "efftaxrate", + "assetturnover", + "arturnover", + "invturnover", + "faturnover", + "apturnover", + "dso", + "dio", + "dpo", + "ccc", + "finleverage", + "leverageratio", + "compoundleveragefactor", + "ltdebttoequity", + "debttoequity", + "roic", + "nnep", + "roicnnepspread", + "rnnoa", + "roe", + "croic", + "oroa", + "roa", + "noncontrollinginterestsharingratio", + "roce", + "divpayoutratio", + "augmentedpayoutratio", + "ocftocapex", + "stdebttocap", + "ltdebttocap", + "debttototalcapital", + "preferredtocap", + "noncontrolinttocap", + "commontocap", + "debttoebitda", + "netdebttoebitda", + "ltdebttoebitda", + "debttonopat", + "netdebttonopat", + "ltdebttonopat", + "altmanzscore", + "ebittointerestex", + "nopattointerestex", + "ebitlesscapextointerestex", + "nopatlesscapextointex", + "ocftointerestex", + "ocflesscapextointerestex", + "fcfftointerestex", + "curratio", + "quickratio", + "dfcfnwctorev", + "dfnwctorev", + "nwctorev", + "normalizednopatmargin", + "pretaxincomemargin", + "adjbasiceps", + "adjdilutedeps", + "adjbasicdilutedeps", + "roe_simple", + ] + + for item in data: + sub_dict: Dict[str, Any] = {} + + for sub_item in item["calculations"]: + field_name = sub_item["data_tag"]["tag"] + if field_name in tags: + sub_dict[field_name] = ( + float(sub_item["value"]) + if sub_item["value"] and sub_item["value"] != 0 + else None + ) + + sub_dict["period_ending"] = item["period_ending"] + sub_dict["fiscal_year"] = item["fiscal_year"] + sub_dict["fiscal_period"] = item["fiscal_period"] + + transformed_data.append(IntrinioFinancialRatiosData(**sub_dict)) + + return transformed_data diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/models/income_statement.py b/openbb_platform/providers/intrinio/openbb_intrinio/models/income_statement.py index d7001c8dc27..280a4087c91 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/models/income_statement.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/models/income_statement.py @@ -1,7 +1,7 @@ """Intrinio Income Statement Model.""" - -from typing import Any, Dict, List, Optional +import warnings +from typing import Any, Dict, List, Literal, Optional from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.income_statement import ( @@ -14,7 +14,9 @@ from openbb_core.provider.utils.helpers import ( amake_requests, ) from openbb_intrinio.utils.helpers import get_data_one -from pydantic import Field +from pydantic import Field, field_validator + +_warn = warnings.warn class IntrinioIncomeStatementQueryParams(IncomeStatementQueryParams): @@ -24,72 +26,343 @@ class IntrinioIncomeStatementQueryParams(IncomeStatementQueryParams): Source: https://docs.intrinio.com/documentation/web_api/get_fundamental_standardized_financials_v2 """ + period: Literal["annual", "quarter", "ttm", "ytd"] = Field(default="annual") + fiscal_year: Optional[int] = Field( + default=None, + description="The specific fiscal year. Reports do not go beyond 2008.", + ) + + @field_validator("symbol", mode="after", check_fields=False) + @classmethod + def handle_symbol(cls, v) -> str: + """Handle symbols with a dash and replace it with a dot for Intrinio.""" + return v.replace("-", ".") + class IntrinioIncomeStatementData(IncomeStatementData): """Intrinio Income Statement Data.""" __alias_dict__ = { - "revenue": "totalrevenue", + "amortization_expense": "amortizationexpense", + "amortizationof_deferred_policy_acquisition_costs": "amortizationofdeferredpolicyacquisitioncosts", + "basic_and_diluted_earnings_per_share": "basicdilutedeps", + "basic_earnings_per_share": "basiceps", + "capitalized_lease_obligations_interest_expense": "capitalizedleaseobligationinterestexpense", + "cash_dividends_to_common_per_share": "cashdividendspershare", + "current_and_future_benefits": "currentandfuturebenefits", + "depletion_expense": "depletionexpense", + "deposits_interest_expense": "depositsinterestexpense", + "deposits_and_money_market_investments_interest_income": "depositsinterestincome", + "depreciation_expense": "depreciationexpense", + "diluted_earnings_per_share": "dilutedeps", + "exploration_expense": "explorationexpense", + "extraordinary_income": "extraordinaryincome", + "federal_funds_purchased_and_securities_sold_interest_expense": "fedfundsandrepointerestexpense", + "federal_funds_sold_and_securities_borrowed_interest_income": "fedfundsandrepointerestincome", + "impairment_charge": "impairmentexpense", + "income_tax_expense": "incometaxexpense", + "pre_tax_income_margin": "pretaxincomemargin", + "investment_banking_income": "investmentbankingincome", + "investment_securities_interest_income": "investmentsecuritiesinterestincome", + "loans_and_leases_interest_income": "loansandleaseinterestincome", + "long_term_debt_interest_expense": "longtermdebtinterestexpense", + "marketing_expense": "marketingexpense", + "consolidated_net_income": "netincome", + "net_income_continuing_operations": "netincomecontinuing", + "net_income_discontinued_operations": "netincomediscontinued", + "net_income_attributable_to_common_shareholders": "netincometocommon", + "net_income_attributable_to_noncontrolling_interest": "netincometononcontrollinginterest", + "net_interest_income": "netinterestincome", + "net_occupancy_and_equipment_expense": "netoccupancyequipmentexpense", + "net_realized_and_unrealized_capital_gains_on_investments": "netrealizedcapitalgains", + "non_operating_income": "nonoperatingincome", + "operating_revenue": "operatingrevenue", + "operating_cost_of_revenue": "operatingcostofrevenue", + "other_adjustments_to_consolidated_net_income": "otheradjustmentstoconsolidatednetincome", + "other_adjustments_to_net_income_attributable_to_common_shareholders": "otheradjustmentstonetincometocommon", + "other_adjustment_to_net_income_attributable_to_common_shareholders": "otheradjustmentstonetincometocommon", + "other_cost_of_revenue": "othercostofrevenue", + "other_gains": "othergains", + "other_income": "otherincome", + "other_interest_expense": "otherinterestexpense", + "other_interest_income": "otherinterestincome", + "other_non_interest_income": "othernoninterestincome", + "other_operating_expenses": "otheroperatingexpenses", + "other_revenue": "otherrevenue", + "other_service_charges": "otherservicechargeincome", + "other_special_charges": "otherspecialcharges", + "insurance_policy_acquisition_costs": "policyacquisitioncosts", + "preferred_stock_dividends_declared": "preferreddividends", + "premiums_earned": "premiumsearned", + "property_and_liability_insurance_claims": "propertyliabilityinsuranceclaims", + "provision_for_credit_losses": "provisionforcreditlosses", + "research_and_development_expense": "rdexpense", + "restructuring_charge": "restructuringcharge", + "salaries_and_employee_benefits": "salariesandemployeebenefitsexpense", + "service_charges_on_deposit_accounts": "servicechargesondepositsincome", + "selling_general_and_admin_expense": "sgaexpense", + "short_term_borrowings_interest_expense": "shorttermborrowinginterestexpense", "cost_of_revenue": "totalcostofrevenue", "gross_profit": "totalgrossprofit", - "research_and_development_expenses": "rdexpense", - "selling_general_and_administrative_expenses": "sgaexpense", - "operating_expenses": "totaloperatingexpenses", - "operating_income": "totaloperatingincome", - "interest_expense": "interestexpense", - "income_before_tax": "totalpretaxincome", - "income_tax_expense": "incometaxexpense", - "net_income": "netincome", - "eps": "basiceps", - "eps_diluted": "dilutedeps", - "weighted_average_shares_outstanding": "weightedavebasicsharesos", + "gross_profit_ratio": "grossmargin", + "total_interest_expense": "totalinterestexpense", + "interest_and_investment_income": "totalinterestincome", + "total_non_interest_expense": "totalnoninterestexpense", + "total_non_interest_income": "totalnoninterestincome", + "total_operating_expenses": "totaloperatingexpenses", + "total_operating_income": "totaloperatingincome", + "total_other_income": "totalotherincome", + "total_pre_tax_income": "totalpretaxincome", + "revenue": "totalrevenue", + "trading_account_interest_income": "tradingaccountinterestincome", + "trust_fees_by_commissions": "trustfeeincome", "ebit": "ebit", "ebitda": "ebitda", + "ebitda_margin": "ebitdamargin", + "weighted_average_basic_and_diluted_shares_outstanding": "weightedavebasicdilutedsharesos", + "weighted_average_basic_shares_outstanding": "weightedavebasicsharesos", + "weighted_average_diluted_shares_outstanding": "weightedavedilutedsharesos", } - # Intrinio-specific fields that don't have a direct mapping to the standard model + + revenue: Optional[float] = Field(default=None, description="Total revenue") operating_revenue: Optional[float] = Field( - default=None, alias="operatingrevenue", description="Operating revenue." + default=None, description="Total operating revenue" + ) + cost_of_revenue: Optional[float] = Field( + default=None, description="Total cost of revenue" ) operating_cost_of_revenue: Optional[float] = Field( + default=None, description="Total operating cost of revenue" + ) + gross_profit: Optional[float] = Field( + default=None, description="Total gross profit" + ) + gross_profit_ratio: Optional[float] = Field( + default=None, description="Gross margin ratio." + ) + provision_for_credit_losses: Optional[float] = Field( default=None, - alias="operatingcostofrevenue", - description="Operating cost of revenue.", + description="Provision for credit losses", ) - total_other_income_expenses_net: Optional[float] = Field( + research_and_development_expense: Optional[float] = Field( + default=None, description="Research and development expense" + ) + selling_general_and_admin_expense: Optional[float] = Field( + default=None, description="Selling, general, and admin expense" + ) + salaries_and_employee_benefits: Optional[float] = Field( + default=None, description="Salaries and employee benefits" + ) + marketing_expense: Optional[float] = Field( + default=None, description="Marketing expense" + ) + net_occupancy_and_equipment_expense: Optional[float] = Field( + default=None, description="Net occupancy and equipment expense" + ) + other_operating_expenses: Optional[float] = Field( + default=None, description="Other operating expenses" + ) + depreciation_expense: Optional[float] = Field( + default=None, description="Depreciation expense" + ) + amortization_expense: Optional[float] = Field( + default=None, description="Amortization expense" + ) + amortization_of_deferred_policy_acquisition_costs: Optional[float] = Field( + default=None, description="Amortization of deferred policy acquisition costs" + ) + exploration_expense: Optional[float] = Field( + default=None, description="Exploration expense" + ) + depletion_expense: Optional[float] = Field( + default=None, description="Depletion expense" + ) + total_operating_expenses: Optional[float] = Field( + default=None, description="Total operating expenses" + ) + total_operating_income: Optional[float] = Field( + default=None, description="Total operating income" + ) + deposits_and_money_market_investments_interest_income: Optional[float] = Field( default=None, - alias="totalotherincome", - description="Total other income/expenses net.", + description="Deposits and money market investments interest income", ) - net_income_continuing: Optional[float] = Field( + federal_funds_sold_and_securities_borrowed_interest_income: Optional[float] = Field( default=None, - alias="netincomecontinuing", - description="Net income from continuing operations.", + description="Federal funds sold and securities borrowed interest income", ) - net_income_to_common: Optional[float] = Field( + investment_securities_interest_income: Optional[float] = Field( + default=None, description="Investment securities interest income" + ) + loans_and_leases_interest_income: Optional[float] = Field( + default=None, description="Loans and leases interest income" + ) + trading_account_interest_income: Optional[float] = Field( + default=None, description="Trading account interest income" + ) + other_interest_income: Optional[float] = Field( + default=None, description="Other interest income" + ) + total_non_interest_income: Optional[float] = Field( + default=None, description="Total non-interest income" + ) + interest_and_investment_income: Optional[float] = Field( + default=None, description="Interest and investment income" + ) + short_term_borrowings_interest_expense: Optional[float] = Field( + default=None, description="Short-term borrowings interest expense" + ) + long_term_debt_interest_expense: Optional[float] = Field( + default=None, description="Long-term debt interest expense" + ) + capitalized_lease_obligations_interest_expense: Optional[float] = Field( + default=None, description="Capitalized lease obligations interest expense" + ) + deposits_interest_expense: Optional[float] = Field( + default=None, description="Deposits interest expense" + ) + federal_funds_purchased_and_securities_sold_interest_expense: Optional[ + float + ] = Field( default=None, - alias="netincometocommon", - description="Net income to common shareholders.", + description="Federal funds purchased and securities sold interest expense", ) - weighted_average_shares_outstanding_dil: Optional[float] = Field( + other_interest_expense: Optional[float] = Field( + default=None, description="Other interest expense" + ) + total_interest_expense: Optional[float] = Field( + default=None, description="Total interest expense" + ) + net_interest_income: Optional[float] = Field( + default=None, description="Net interest income" + ) + other_non_interest_income: Optional[float] = Field( + default=None, description="Other non-interest income" + ) + investment_banking_income: Optional[float] = Field( + default=None, description="Investment banking income" + ) + trust_fees_by_commissions: Optional[float] = Field( + default=None, description="Trust fees by commissions" + ) + premiums_earned: Optional[float] = Field( + default=None, description="Premiums earned" + ) + insurance_policy_acquisition_costs: Optional[float] = Field( + default=None, description="Insurance policy acquisition costs" + ) + current_and_future_benefits: Optional[float] = Field( + default=None, description="Current and future benefits" + ) + property_and_liability_insurance_claims: Optional[float] = Field( + default=None, description="Property and liability insurance claims" + ) + total_non_interest_expense: Optional[float] = Field( + default=None, description="Total non-interest expense" + ) + net_realized_and_unrealized_capital_gains_on_investments: Optional[float] = Field( default=None, - alias="weightedavedilutedsharesos", - description="Weighted average diluted shares outstanding.", + description="Net realized and unrealized capital gains on investments", ) - cash_dividends_per_share: Optional[float] = Field( + other_gains: Optional[float] = Field(default=None, description="Other gains") + non_operating_income: Optional[float] = Field( + default=None, description="Non-operating income" + ) + other_income: Optional[float] = Field(default=None, description="Other income") + other_revenue: Optional[float] = Field(default=None, description="Other revenue") + + extraordinary_income: Optional[float] = Field( + default=None, description="Extraordinary income" + ) + total_other_income: Optional[float] = Field( + default=None, description="Total other income" + ) + ebitda: Optional[float] = Field( default=None, - alias="cashdividendspershare", - description="Cash dividends per share.", + description="Earnings Before Interest, Taxes, Depreciation and Amortization.", ) - ebitda_ratio: Optional[float] = Field( - default=None, alias="ebitdamargin", description="EBITDA margin." - ) - other_income: Optional[float] = Field( - default=None, alias="otherincome", description="Other income." - ) - weighted_ave_basic_diluted_shares_os: Optional[float] = Field( + ebitda_margin: Optional[float] = Field( default=None, - alias="weightedavebasicdilutedsharesos", - description="Weighted average basic and diluted shares outstanding.", + description="Margin on Earnings Before Interest, Taxes, Depreciation and Amortization.", + ) + total_pre_tax_income: Optional[float] = Field( + default=None, description="Total pre-tax income" + ) + ebit: Optional[float] = Field( + default=None, description="Earnings Before Interest and Taxes." + ) + pre_tax_income_margin: Optional[float] = Field( + default=None, description="Pre-Tax Income Margin." + ) + income_tax_expense: Optional[float] = Field( + default=None, description="Income tax expense" + ) + impairment_charge: Optional[float] = Field( + default=None, description="Impairment charge" + ) + restructuring_charge: Optional[float] = Field( + default=None, description="Restructuring charge" + ) + service_charges_on_deposit_accounts: Optional[float] = Field( + default=None, description="Service charges on deposit accounts" + ) + other_service_charges: Optional[float] = Field( + default=None, description="Other service charges" + ) + other_special_charges: Optional[float] = Field( + default=None, description="Other special charges" + ) + other_cost_of_revenue: Optional[float] = Field( + default=None, description="Other cost of revenue" + ) + net_income_continuing_operations: Optional[float] = Field( + default=None, description="Net income (continuing operations)" + ) + net_income_discontinued_operations: Optional[float] = Field( + default=None, description="Net income (discontinued operations)" + ) + consolidated_net_income: Optional[float] = Field( + default=None, description="Consolidated net income" + ) + other_adjustments_to_consolidated_net_income: Optional[float] = Field( + default=None, description="Other adjustments to consolidated net income" + ) + other_adjustment_to_net_income_attributable_to_common_shareholders: Optional[ + float + ] = Field( + default=None, + description="Other adjustment to net income attributable to common shareholders", + ) + net_income_attributable_to_noncontrolling_interest: Optional[float] = Field( + default=None, description="Net income attributable to noncontrolling interest" + ) + net_income_attributable_to_common_shareholders: Optional[float] = Field( + default=None, description="Net income attributable to common shareholders" + ) + basic_earnings_per_share: Optional[float] = Field( + default=None, description="Basic earnings per share" + ) + diluted_earnings_per_share: Optional[float] = Field( + default=None, description="Diluted earnings per share" + ) + basic_and_diluted_earnings_per_share: Optional[float] = Field( + default=None, description="Basic and diluted earnings per share" + ) + cash_dividends_to_common_per_share: Optional[float] = Field( + default=None, description="Cash dividends to common per share" + ) + preferred_stock_dividends_declared: Optional[float] = Field( + default=None, description="Preferred stock dividends declared" + ) + weighted_average_basic_shares_outstanding: Optional[float] = Field( + default=None, description="Weighted average basic shares outstanding" + ) + weighted_average_diluted_shares_outstanding: Optional[float] = Field( + default=None, description="Weighted average diluted shares outstanding" + ) + weighted_average_basic_and_diluted_shares_outstanding: Optional[float] = Field( + default=None, + description="Weighted average basic and diluted shares outstanding", ) @@ -115,16 +388,32 @@ class IntrinioIncomeStatementFetcher( """Return the raw data from the Intrinio endpoint.""" api_key = credentials.get("intrinio_api_key") if credentials else "" statement_code = "income_statement" + if query.period in ["quarter", "annual"]: + period_type = "FY" if query.period == "annual" else "QTR" + if query.period in ["ttm", "ytd"]: + period_type = query.period.upper() + data_tags = [ + "ebit", + "ebitda", + "ebitdamargin", + "pretaxincomemargin", + "grossmargin", + ] - period_type = "FY" if query.period == "annual" else "QTR" - data_tags = ["ebit", "ebitda", "ebitdamargin"] + fundamentals_data: Dict = {} base_url = "https://api-v2.intrinio.com" fundamentals_url = ( f"{base_url}/companies/{query.symbol}/fundamentals?" - f"statement_code={statement_code}&type={period_type}&api_key={api_key}" + f"statement_code={statement_code}&type={period_type}" ) + if query.fiscal_year is not None: + if query.fiscal_year < 2008: + _warn("Financials data is only available from 2008 and later.") + query.fiscal_year = 2008 + fundamentals_url = fundamentals_url + f"&fiscal_year={query.fiscal_year}" + fundamentals_url = fundamentals_url + f"&api_key={api_key}" fundamentals_data = (await get_data_one(fundamentals_url, **kwargs)).get( "fundamentals", [] ) @@ -151,8 +440,9 @@ class IntrinioIncomeStatementFetcher( ] return { - "date": statement_data["fundamental"]["end_date"], - "period": statement_data["fundamental"]["fiscal_period"], + "period_ending": statement_data["fundamental"]["end_date"], + "fiscal_period": statement_data["fundamental"]["fiscal_period"], + "fiscal_year": statement_data["fundamental"]["fiscal_year"], "financials": statement_data["standardized_financials"] + calculations_data, } @@ -177,14 +467,15 @@ class IntrinioIncomeStatementFetcher( for sub_item in item["financials"]: field_name = sub_item["data_tag"]["tag"] - sub_dict[field_name] = float(sub_item["value"]) + sub_dict[field_name] = ( + float(sub_item["value"]) + if sub_item["value"] and sub_item["value"] != 0 + else None + ) - sub_dict["date"] = item["date"] - sub_dict["period"] = item["period"] - - # Intrinio does not return Q4 data but FY data instead - if query.period == "quarter" and item["period"] == "FY": - sub_dict["period"] = "Q4" + sub_dict["period_ending"] = item["period_ending"] + sub_dict["fiscal_year"] = item["fiscal_year"] + sub_dict["fiscal_period"] = item["fiscal_period"] transformed_data.append(IntrinioIncomeStatementData(**sub_dict)) diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/models/reported_financials.py b/openbb_platform/providers/intrinio/openbb_intrinio/models/reported_financials.py new file mode 100644 index 00000000000..6b60ab9c289 --- /dev/null +++ b/openbb_platform/providers/intrinio/openbb_intrinio/models/reported_financials.py @@ -0,0 +1,142 @@ +"""Intrinio Reported Financials Model.""" + +import warnings +from typing import Any, Dict, List, Literal, Optional + +from openbb_core.provider.abstract.fetcher import Fetcher +from openbb_core.provider.standard_models.reported_financials import ( + ReportedFinancialsData, + ReportedFinancialsQueryParams, +) +from openbb_core.provider.utils.helpers import ( + ClientResponse, + amake_requests, + to_snake_case, +) +from openbb_intrinio.utils.helpers import get_data_one +from pandas import DataFrame +from pydantic import Field + +_warn = warnings.warn + +STATEMENT_DICT = { + "balance": "balance_sheet_statement", + "income": "income_statement", + "cash": "cash_flow_statement", +} + + +class IntrinioReportedFinancialsQueryParams(ReportedFinancialsQueryParams): + """Intrinio Reported Financials Query. + + Source: https://docs.intrinio.com/documentation/web_api/get_company_fundamentals_v2 + Source: https://docs.intrinio.com/documentation/web_api/get_fundamental_reported_financials_v2 + """ + + statement_type: Literal["balance", "income", "cash"] = Field( + default="income", + description="Cash flow statements are reported as YTD, Q4 is the same as FY.", + ) + period: Literal["annual", "quarter"] = Field(default="annual") + fiscal_year: Optional[int] = Field( + default=None, + description="The specific fiscal year. Reports do not go beyond 2008.", + ) + + +class IntrinioReportedFinancialsData(ReportedFinancialsData): + """ + Intrinio Reported Financials Data. + + The fields for this model are generated dynamically from the XBRL tags in the Intrinio response. + """ + + +class IntrinioReportedFinancialsFetcher( + Fetcher[ + IntrinioReportedFinancialsQueryParams, + List[IntrinioReportedFinancialsData], + ] +): + """Transform the query, extract and transform the data from the Intrinio endpoints.""" + + @staticmethod + def transform_query( + params: Dict[str, Any] + ) -> IntrinioReportedFinancialsQueryParams: + """Transform the query params.""" + return IntrinioReportedFinancialsQueryParams(**params) + + @staticmethod + async def aextract_data( + query: IntrinioReportedFinancialsQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the Intrinio endpoint.""" + period_type = "" + api_key = credentials.get("intrinio_api_key") if credentials else "" + statement_code = STATEMENT_DICT[query.statement_type] + period_type = "FY" if query.period == "annual" else "Q" + ids = [] + ids_url = f"https://api-v2.intrinio.com/companies/{query.symbol}/fundamentals?reported_only=true&statement_code={statement_code}" + if query.fiscal_year is not None: + if query.fiscal_year < 2008: + _warn("Financials data is only available from 2008 and later.") + query.fiscal_year = 2008 + ids_url = ids_url + f"&fiscal_year={query.fiscal_year}" + ids_url = ids_url + f"&page_size=10000&api_key={api_key}" + + fundamentals_ids = await get_data_one(ids_url, **kwargs) + filings = DataFrame(fundamentals_ids["fundamentals"]) + + _period = "" if query.period is None else period_type + _statement = "" if statement_code is None else statement_code + if len(filings) > 0: + filings = filings[filings["statement_code"].str.contains(_statement)] + if query.period == "annual": + filings = filings[filings["fiscal_period"].str.contains(_period)] + ids = filings.iloc[: query.limit]["id"].to_list() + + if ids == []: + raise RuntimeError("No reports found.") + + async def callback(response: ClientResponse, _: Any) -> Dict: + """Return the response.""" + statement_data = await response.json() + return { + "period_ending": statement_data["fundamental"]["end_date"], + "fiscal_year": statement_data["fundamental"]["fiscal_year"], + "fiscal_period": statement_data["fundamental"]["fiscal_period"], + "financials": statement_data["reported_financials"], + } + + urls = [ + f"https://api-v2.intrinio.com/fundamentals/{id}/reported_financials?api_key={api_key}" + for id in ids + ] + + return await amake_requests(urls, callback, **kwargs) + + @staticmethod + def transform_data( + query: IntrinioReportedFinancialsQueryParams, data: List[Dict], **kwargs: Any + ) -> List[IntrinioReportedFinancialsData]: + """Return the transformed data.""" + transformed_data: List[IntrinioReportedFinancialsData] = [] + data_tag = "xbrl_tag" + for item in data: + sub_dict: Dict[str, Any] = {} + + for sub_item in item["financials"]: + field_name = to_snake_case(sub_item[data_tag]["tag"]) + if sub_item["value"] and sub_item["value"] != 0: + sub_dict[field_name] = float(sub_item["value"]) + + sub_dict["period_ending"] = item["period_ending"] + sub_dict["fiscal_year"] = item["fiscal_year"] + sub_dict["fiscal_period"] = item["fiscal_period"] + + transformed_data.append(IntrinioReportedFinancialsData(**sub_dict)) + + return transformed_data diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/utils/helpers.py b/openbb_platform/providers/intrinio/openbb_intrinio/utils/helpers.py index 6112514abf1..51fdd8dd11f 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/utils/helpers.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/utils/helpers.py @@ -39,8 +39,8 @@ def request(url: str) -> BasicResponse: """ Request function for PyScript. Pass in Method and make sure to await. - Parameters: - ----------- + Parameters + ---------- url: str URL to make request to @@ -79,7 +79,7 @@ async def response_callback( async def get_data(url: str, **kwargs: Any) -> Union[list, dict]: - """Get data from FMP endpoint.""" + """Get data from Intrinio endpoint.""" return await amake_request(url, response_callback=response_callback, **kwargs) @@ -88,15 +88,15 @@ async def get_data_many( ) -> List[dict]: """Get data from Intrinio endpoint and convert to list of schemas. - Parameters: - ----------- + Parameters + ---------- url: str The URL to get the data from. sub_dict: Optional[str] The sub-dictionary to use. - Returns: - -------- + Returns + ------- List[dict] Dictionary of data. """ @@ -133,6 +133,7 @@ def get_weekday(date: dateType) -> str: async def async_get_data_one( url: str, limit: int = 1, sleep: float = 1, **kwargs: Any ) -> Union[list, dict]: + """Get data from Intrinio endpoint and convert to schema.""" if limit > 100: await asyncio.sleep(sleep) diff --git a/openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_balance_sheet_fetcher.yaml b/openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_balance_sheet_fetcher.yaml index 461d2287cfc..fd85df10916 100644 --- a/openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_balance_sheet_fetcher.yaml +++ b/openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_balance_sheet_fetcher.yaml @@ -9,7 +9,7 @@ interactions: Connection: - keep-alive method: GET - uri: https://api-v2.intrinio.com/companies/AAPL/fundamentals?api_key=MOCK_API_KEY&statement_code=balance_sheet_statement&type=FY + uri: https://api-v2.intrinio.com/companies/AAPL/fundamentals?api_key=MOCK_API_KEY&statement_code=balance_sheet_statement&type=annual response: body: string: !!binary | diff --git a/openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_financial_ratios_fetcher.yaml b/openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_financial_ratios_fetcher.yaml new file mode 100644 index 00000000000..02d0b67ce4d --- /dev/null +++ b/openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_financial_ratios_fetcher.yaml @@ -0,0 +1,241 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Connection: + - keep-alive + method: GET + uri: https://api-v2.intrinio.com/companies/AAPL/fundamentals?api_key=MOCK_API_KEY&statement_code=calculations&type=FY + response: + body: + string: !!binary | + H4sIAKrLZ2UAA6yXXW+iQBSG/8pmri2ZDxgG7jS17kerrmmj7WZjEKmhpYCK60fT/74HJaaO9MKT + IdxwzszIkzfn5fWdPK/SafAWpUWQLIn/553EU+KX1XHLbU9616RBlkVQROWScZhNI+iGQRKukqCI + s3QJ/ed4CZXxNgoWxOeUi2MpjxZxVp538wjrim0Ou9NVkuzPXBTjKRwMXdjDr6h3xR1YFaXTT3VR + 1gXd/0oSp7OqdTgkXo7hLaJlQfxisYoaZJWX7dP9jMF9Tx0fbiEs6fEn8tH4xJklvcU6QXByBCfb + c8ozzgO/bYiTu5bNlMY5H+TdSQvByRCcdM/jnnGyo85GOJXl2LbG+XPCbycSwUkv52Tensc746RH + nQ3pKTjTOLcTt+k+Xc7JPASnOs7hCWfFr8zpyaiu52zjbGgXwakQnO4VA+nYGac66myCkyrLk1Lj + 3M1v8yFiPpmL4JT1fgv8Jv0W9LRtoevZnQdDjJ4SwenU+1DFb8Zvbd+RllRU4xzJFzlfIzgdBKd9 + nMNTTse0Dyml67n7J7w7hN8yG8Ep6v224ndN6elYzNH9dhZ12vvJuJQTkYcY/8JvhWm/FWfzOQp6 + w80tghORhxj7woe4Qb8FPcFvmZ77Zi+i+3iH4ETkIUbrc1/Fbyz3KQvO1OezvVm3GYITkYeo94Xf + UoO5D/SEHG/r+Xb2O2OD7HJOishDVNX7bcVvxm+B07Wo8HTO63zdnyI4EXmIuvU+VPEb81tpefws + J/DO4g3xXaGIPERlfe478JvzIddiouT82yBh9pYH6Zb4FTI8j7sj2dn1yleNw9cIaEiz2S+tOIW/ + 6OVTnifRtx9pCKUkiqHyffjQ/zWgd/3eg7rpjFr3wivNJIxfoUnhEmVIF+Tj4z8AAAD//wMA52lC + QesPAAA= + headers: + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Type: + - application/json + Date: + - Wed, 29 Nov 2023 23:39:22 GMT + Transfer-Encoding: + - chunked + Vary: + - Origin,Accept-Encoding + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Connection: + - keep-alive + method: GET + uri: https://api-v2.intrinio.com/fundamentals/fun_B7EbOD/standardized_financials?api_key=MOCK_API_KEY + response: + body: + string: !!binary | + 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 + headers: + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Type: + - application/json + Date: + - Wed, 29 Nov 2023 23:39:22 GMT + Transfer-Encoding: + - chunked + Vary: + - Origin,Accept-Encoding + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Connection: + - keep-alive + method: GET + uri: https://api-v2.intrinio.com/fundamentals/fun_olOrwl/standardized_financials?api_key=MOCK_API_KEY + response: + body: + string: !!binary | + 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 + 69evPwEAAP//AwChnFlucV4AAA== + headers: + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Type: + - application/json + Date: + - Wed, 29 Nov 2023 23:39:23 GMT + Transfer-Encoding: + - chunked + Vary: + - Origin,Accept-Encoding + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_reported_financials_fetcher.yaml b/openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_reported_financials_fetcher.yaml new file mode 100644 index 00000000000..f67182401ab --- /dev/null +++ b/openbb_platform/providers/intrinio/tests/record/http/test_intrinio_fetchers/test_intrinio_reported_financials_fetcher.yaml @@ -0,0 +1,128 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api-v2.intrinio.com/companies/AAPL/fundamentals?api_key=MOCK_API_KEY&page_size=10000&reported_only=true&statement_code=cash_flow_statement + response: + body: + string: !!binary | + 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 + headers: + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Type: + - application/json + Date: + - Mon, 11 Dec 2023 20:55:19 GMT + Transfer-Encoding: + - chunked + Vary: + - Origin,Accept-Encoding + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + method: GET + uri: https://api-v2.intrinio.com/fundamentals/fun_VbvBln/reported_financials?api_key=MOCK_API_KEY + response: + body: + string: !!binary | + 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 + headers: + Connection: + - keep-alive + Content-Encoding: + - gzip + Content-Type: + - application/json + Date: + - Mon, 11 Dec 2023 20:55:20 GMT + Transfer-Encoding: + - chunked + Vary: + - Origin,Accept-Encoding + status: + code: 200 + message: OK +version: 1 diff --git a/openbb_platform/providers/intrinio/tests/test_intrinio_fetchers.py b/openbb_platform/providers/intrinio/tests/test_intrinio_fetchers.py index 49e4d46aa94..227ff1ac9d6 100644 --- a/openbb_platform/providers/intrinio/tests/test_intrinio_fetchers.py +++ b/openbb_platform/providers/intrinio/tests/test_intrinio_fetchers.py @@ -13,6 +13,7 @@ from openbb_intrinio.models.equity_historical import IntrinioEquityHistoricalFet from openbb_intrinio.models.equity_info import IntrinioEquityInfoFetcher from openbb_intrinio.models.equity_quote import IntrinioEquityQuoteFetcher from openbb_intrinio.models.equity_search import IntrinioEquitySearchFetcher +from openbb_intrinio.models.financial_ratios import IntrinioFinancialRatiosFetcher from openbb_intrinio.models.fred_series import IntrinioFredSeriesFetcher from openbb_intrinio.models.historical_attributes import ( IntrinioHistoricalAttributesFetcher, @@ -30,6 +31,7 @@ from openbb_intrinio.models.latest_attributes import IntrinioLatestAttributesFet from openbb_intrinio.models.market_indices import IntrinioMarketIndicesFetcher from openbb_intrinio.models.options_chains import IntrinioOptionsChainsFetcher from openbb_intrinio.models.options_unusual import IntrinioOptionsUnusualFetcher +from openbb_intrinio.models.reported_financials import IntrinioReportedFinancialsFetcher from openbb_intrinio.models.search_attributes import ( IntrinioSearchAttributesFetcher, ) @@ -315,3 +317,26 @@ def test_intrinio_equity_search_fetcher(credentials=test_credentials): fetcher = IntrinioEquitySearchFetcher() result = fetcher.test(params, credentials) assert result is None + + +@pytest.mark.record_http +def test_intrinio_financial_ratios_fetcher(credentials=test_credentials): + params = {"symbol": "AAPL", "period": "annual", "limit": 2, "use_cache": False} + + fetcher = IntrinioFinancialRatiosFetcher() + result = fetcher.test(params, credentials) + assert result is None + + +@pytest.mark.record_http +def test_intrinio_reported_financials_fetcher(credentials=test_credentials): + params = { + "symbol": "AAPL", + "statement_type": "cash", + "period": "quarter", + "limit": 1, + } + + fetcher = IntrinioReportedFinancialsFetcher() + result = fetcher.test(params, credentials) + assert result is None diff --git a/openbb_platform/providers/polygon/openbb_polygon/models/balance_sheet.py b/openbb_platform/providers/polygon/openbb_polygon/models/balance_sheet.py index f4485f3a695..ecd6691f37a 100644 --- a/openbb_platform/providers/polygon/openbb_polygon/models/balance_sheet.py +++ b/openbb_platform/providers/polygon/openbb_polygon/models/balance_sheet.py @@ -10,7 +10,7 @@ from openbb_core.provider.standard_models.balance_sheet import ( ) from openbb_core.provider.utils.helpers import get_querystring from openbb_polygon.utils.helpers import get_data_many -from pydantic import Field, field_validator +from pydantic import Field class PolygonBalanceSheetQueryParams(BalanceSheetQueryParams): @@ -21,6 +21,7 @@ class PolygonBalanceSheetQueryParams(BalanceSheetQueryParams): __alias_dict__ = {"symbol": "ticker", "period": "timeframe"} + period: Literal["annual", "quarter", "ttm"] = Field(default="annual") filing_date: Optional[date] = Field( default=None, description="Filing date of the financial statement." ) @@ -58,8 +59,8 @@ class PolygonBalanceSheetQueryParams(BalanceSheetQueryParams): default=None, description="Period of report date greater than or equal to the given date.", ) - include_sources: Optional[bool] = Field( - default=None, + include_sources: bool = Field( + default=True, description="Whether to include the sources of the financial statement.", ) order: Optional[Literal["asc", "desc"]] = Field( @@ -75,31 +76,100 @@ class PolygonBalanceSheetData(BalanceSheetData): __alias_dict__ = { "date": "start_date", - "total_liabilities_and_stockholders_equity": "liabilities_and_equity", + "total_liabilities_and_stock_holders_equity": "liabilities_and_equity", "minority_interest": "equity_attributable_to_noncontrolling_interest", "total_current_assets": "current_assets", "marketable_securities": "fixed_assets", "property_plant_equipment_net": "public_utilities_property_plant_and_equipment_net", - "other_non_current_assets": "other_noncurrent_assets_of_regulated_entity", + "other_non_current_assets": "other_noncurrent_assets", "total_non_current_assets": "noncurrent_assets", "total_assets": "assets", "total_current_liabilities": "current_liabilities", - "other_non_current_liabilities": "other _noncurrent_liabilities_of_regulated_entity", + "other_non_current_liabilities": "other_noncurrent_liabilities", "total_non_current_liabilities": "noncurrent_liabilities", "total_liabilities": "liabilities", - "preferred_stock": "temporary_equity", - "total_shareholder_equity": "temporary_equity_attributable_to_parent", + "total_stock_holders_equity": "equity_attributable_to_parent", "total_equity": "equity", - "total_liabilities_and_shareholders_equity": "liabilities_and_equity", + "employee_wages": "wages", + "redeemable_non_controlling_interest": "redeemable_noncontrolling_interest", + "redeemable_non_controlling_interest_other": "redeemable_noncontrolling_interest_other", } - @field_validator("symbol", mode="before", check_fields=False) - @classmethod - def symbol_from_tickers(cls, v): - """Return a list of symbols as a list.""" - if isinstance(v, list): - return ",".join(v) - return v + accounts_receivable: Optional[int] = Field( + description="Accounts receivable", default=None + ) + marketable_securities: Optional[int] = Field( + description="Marketable securities", default=None + ) + prepaid_expenses: Optional[int] = Field( + description="Prepaid expenses", default=None + ) + other_current_assets: Optional[int] = Field( + description="Other current assets", default=None + ) + total_current_assets: Optional[int] = Field( + description="Total current assets", default=None + ) + property_plant_equipment_net: Optional[int] = Field( + description="Property plant and equipment net", default=None + ) + inventory: Optional[int] = Field(description="Inventory", default=None) + other_non_current_assets: Optional[int] = Field( + description="Other non-current assets", default=None + ) + total_non_current_assets: Optional[int] = Field( + description="Total non-current assets", default=None + ) + intangible_assets: Optional[int] = Field( + description="Intangible assets", default=None + ) + total_assets: Optional[int] = Field(description="Total assets", default=None) + accounts_payable: Optional[int] = Field( + description="Accounts payable", default=None + ) + employee_wages: Optional[int] = Field(description="Employee wages", default=None) + other_current_liabilities: Optional[int] = Field( + description="Other current liabilities", default=None + ) + total_current_liabilities: Optional[int] = Field( + description="Total current liabilities", default=None + ) + other_non_current_liabilities: Optional[int] = Field( + description="Other non-current liabilities", default=None + ) + total_non_current_liabilities: Optional[int] = Field( + description="Total non-current liabilities", default=None + ) + long_term_debt: Optional[int] = Field(description="Long term debt", default=None) + total_liabilities: Optional[int] = Field( + description="Total liabilities", default=None + ) + minority_interest: Optional[int] = Field( + description="Minority interest", default=None + ) + temporary_equity_attributable_to_parent: Optional[int] = Field( + description="Temporary equity attributable to parent", default=None + ) + equity_attributable_to_parent: Optional[int] = Field( + description="Equity attributable to parent", default=None + ) + temporary_equity: Optional[int] = Field( + description="Temporary equity", default=None + ) + preferred_stock: Optional[int] = Field(description="Preferred stock", default=None) + redeemable_non_controlling_interest: Optional[int] = Field( + description="Redeemable non-controlling interest", default=None + ) + redeemable_non_controlling_interest_other: Optional[int] = Field( + description="Redeemable non-controlling interest other", default=None + ) + total_stock_holders_equity: Optional[int] = Field( + description="Total stock holders equity", default=None + ) + total_liabilities_and_stock_holders_equity: Optional[int] = Field( + description="Total liabilities and stockholders equity", default=None + ) + total_equity: Optional[int] = Field(description="Total equity", default=None) class PolygonBalanceSheetFetcher( @@ -120,20 +190,20 @@ class PolygonBalanceSheetFetcher( query: PolygonBalanceSheetQueryParams, credentials: Optional[Dict[str, str]], **kwargs: Any, - ) -> dict: + ) -> Dict: """Return the raw data from the Intrinio endpoint.""" api_key = credentials.get("polygon_api_key") if credentials else "" base_url = "https://api.polygon.io/vX/reference/financials" period = "quarterly" if query.period == "quarter" else query.period query_string = get_querystring( - query.model_dump(by_alias=True), ["ticker", "period"] + query.model_dump(by_alias=True), ["ticker", "timeframe"] ) if query.symbol.isdigit(): - query_string = f"cik={query.symbol}&period={period}&{query_string}" + query_string = f"cik={query.symbol}&timeframe={period}&{query_string}" else: - query_string = f"ticker={query.symbol}&period={period}&{query_string}" + query_string = f"ticker={query.symbol}&timeframe={period}&{query_string}" request_url = f"{base_url}?{query_string}&apiKey={api_key}" @@ -142,21 +212,20 @@ class PolygonBalanceSheetFetcher( @staticmethod def transform_data( query: PolygonBalanceSheetQueryParams, - data: dict, + data: Dict, **kwargs: Any, ) -> List[PolygonBalanceSheetData]: """Return the transformed data.""" transformed_data = [] for item in data: - sub_data = { - key: value["value"] - for key, value in item["financials"]["balance_sheet"].items() - } - sub_data["date"] = item["start_date"] - sub_data["cik"] = item["cik"] - sub_data["symbol"] = item["tickers"] - sub_data["period"] = item["fiscal_period"] - transformed_data.append(PolygonBalanceSheetData(**sub_data)) + if "balance_sheet" in item["financials"]: + sub_data = { + key: value["value"] + for key, value in item["financials"]["balance_sheet"].items() + } + sub_data["period_ending"] = item["end_date"] + sub_data["fiscal_period"] = item["fiscal_period"] + transformed_data.append(PolygonBalanceSheetData(**sub_data)) return transformed_data diff --git a/openbb_platform/providers/polygon/openbb_polygon/models/cash_flow.py b/openbb_platform/providers/polygon/openbb_polygon/models/cash_flow.py index 566a342cdb4..c0d6b366f85 100644 --- a/openbb_platform/providers/polygon/openbb_polygon/models/cash_flow.py +++ b/openbb_platform/providers/polygon/openbb_polygon/models/cash_flow.py @@ -1,6 +1,6 @@ """Polygon Cash Flow Statement Model.""" -from datetime import date +from datetime import date as dateType from typing import Any, Dict, List, Literal, Optional from openbb_core.provider.abstract.fetcher import Fetcher @@ -10,7 +10,7 @@ from openbb_core.provider.standard_models.cash_flow import ( ) from openbb_core.provider.utils.helpers import get_querystring from openbb_polygon.utils.helpers import get_data_many -from pydantic import Field, field_validator +from pydantic import Field class PolygonCashFlowStatementQueryParams(CashFlowStatementQueryParams): @@ -21,51 +21,53 @@ class PolygonCashFlowStatementQueryParams(CashFlowStatementQueryParams): __alias_dict__ = {"symbol": "ticker", "period": "timeframe"} - filing_date: Optional[date] = Field( + period: Literal["annual", "quarter"] = Field(default="annual") + + filing_date: Optional[dateType] = Field( default=None, description="Filing date of the financial statement." ) - filing_date_lt: Optional[date] = Field( + filing_date_lt: Optional[dateType] = Field( default=None, description="Filing date less than the given date." ) - filing_date_lte: Optional[date] = Field( + filing_date_lte: Optional[dateType] = Field( default=None, description="Filing date less than or equal to the given date.", ) - filing_date_gt: Optional[date] = Field( + filing_date_gt: Optional[dateType] = Field( default=None, description="Filing date greater than the given date.", ) - filing_date_gte: Optional[date] = Field( + filing_date_gte: Optional[dateType] = Field( default=None, description="Filing date greater than or equal to the given date.", ) - period_of_report_date: Optional[date] = Field( + period_of_report_date: Optional[dateType] = Field( default=None, description="Period of report date of the financial statement." ) - period_of_report_date_lt: Optional[date] = Field( + period_of_report_date_lt: Optional[dateType] = Field( default=None, description="Period of report date less than the given date.", ) - period_of_report_date_lte: Optional[date] = Field( + period_of_report_date_lte: Optional[dateType] = Field( default=None, description="Period of report date less than or equal to the given date.", ) - period_of_report_date_gt: Optional[date] = Field( + period_of_report_date_gt: Optional[dateType] = Field( default=None, description="Period of report date greater than the given date.", ) - period_of_report_date_gte: Optional[date] = Field( + period_of_report_date_gte: Optional[dateType] = Field( default=None, description="Period of report date greater than or equal to the given date.", ) - include_sources: Optional[bool] = Field( - default=None, + include_sources: bool = Field( + default=False, description="Whether to include the sources of the financial statement.", ) - order: Optional[Literal["asc", "desc"]] = Field( + order: Literal[None, "asc", "desc"] = Field( default=None, description="Order of the financial statement." ) - sort: Optional[Literal["filing_date", "period_of_report_date"]] = Field( + sort: Literal[None, "filing_date", "period_of_report_date"] = Field( default=None, description="Sort of the financial statement." ) @@ -73,15 +75,46 @@ class PolygonCashFlowStatementQueryParams(CashFlowStatementQueryParams): class PolygonCashFlowStatementData(CashFlowStatementData): """Polygon Cash Flow Statement Data.""" - __alias_dict__ = {"date": "start_date"} - - @field_validator("symbol", mode="before", check_fields=False) - @classmethod - def symbol_from_tickers(cls, v): - """Return a list of symbols as a list.""" - if isinstance(v, list): - return ",".join(v) - return v + net_cash_flow_from_operating_activities_continuing: Optional[int] = Field( + description="Net cash flow from operating activities continuing.", default=None + ) + net_cash_flow_from_operating_activities_discontinued: Optional[int] = Field( + description="Net cash flow from operating activities discontinued.", + default=None, + ) + net_cash_flow_from_operating_activities: Optional[int] = Field( + description="Net cash flow from operating activities.", default=None + ) + net_cash_flow_from_investing_activities_continuing: Optional[int] = Field( + description="Net cash flow from investing activities continuing.", default=None + ) + net_cash_flow_from_investing_activities_discontinued: Optional[int] = Field( + description="Net cash flow from investing activities discontinued.", + default=None, + ) + net_cash_flow_from_investing_activities: Optional[int] = Field( + description="Net cash flow from investing activities.", default=None + ) + net_cash_flow_from_financing_activities_continuing: Optional[int] = Field( + description="Net cash flow from financing activities continuing.", default=None + ) + net_cash_flow_from_financing_activities_discontinued: Optional[int] = Field( + description="Net cash flow from financing activities discontinued.", + default=None, + ) + net_cash_flow_from_financing_activities: Optional[int] = Field( + description="Net cash flow from financing activities.", default=None + ) + net_cash_flow_continuing: Optional[int] = Field( + description="Net cash flow continuing.", default=None + ) + net_cash_flow_discontinued: Optional[int] = Field( + description="Net cash flow discontinued.", default=None + ) + exchange_gains_losses: Optional[int] = Field( + description="Exchange gains losses.", default=None + ) + net_cash_flow: Optional[int] = Field(description="Net cash flow.", default=None) class PolygonCashFlowStatementFetcher( @@ -107,15 +140,19 @@ class PolygonCashFlowStatementFetcher( api_key = credentials.get("polygon_api_key") if credentials else "" base_url = "https://api.polygon.io/vX/reference/financials" - period = "quarterly" if query.period == "quarter" else query.period + period_dict = { + "annual": "annual", + "quarter": "quarterly", + "ttm": "ttm", + } query_string = get_querystring( - query.model_dump(by_alias=True), ["ticker", "period"] + query.model_dump(by_alias=True), ["ticker", "timeframe"] ) if query.symbol.isdigit(): - query_string = f"cik={query.symbol}&period={period}&{query_string}" + query_string = f"cik={query.symbol}&timeframe={period_dict[query.period]}&{query_string}" else: - query_string = f"ticker={query.symbol}&period={period}&{query_string}" + query_string = f"ticker={query.symbol}&timeframe={period_dict[query.period]}&{query_string}" request_url = f"{base_url}?{query_string}&apiKey={api_key}" @@ -135,10 +172,8 @@ class PolygonCashFlowStatementFetcher( key: value["value"] for key, value in item["financials"]["cash_flow_statement"].items() } - sub_data["date"] = item["start_date"] - sub_data["cik"] = item["cik"] - sub_data["symbol"] = item["tickers"] - sub_data["period"] = item["fiscal_period"] + sub_data["period_ending"] = item["end_date"] + sub_data["fiscal_period"] = item["fiscal_period"] transformed_data.append(PolygonCashFlowStatementData(**sub_data)) return transformed_data diff --git a/openbb_platform/providers/polygon/openbb_polygon/models/income_statement.py b/openbb_platform/providers/polygon/openbb_polygon/models/income_statement.py index ffa360280fb..daa52031caf 100644 --- a/openbb_platform/providers/polygon/openbb_polygon/models/income_statement.py +++ b/openbb_platform/providers/polygon/openbb_polygon/models/income_statement.py @@ -3,7 +3,6 @@ from datetime import date from typing import Any, Dict, List, Literal, Optional -from openbb_core.provider.abstract.data import ForceInt from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.income_statement import ( IncomeStatementData, @@ -11,7 +10,7 @@ from openbb_core.provider.standard_models.income_statement import ( ) from openbb_core.provider.utils.helpers import get_querystring from openbb_polygon.utils.helpers import get_data_many -from pydantic import Field, field_validator +from pydantic import Field, model_validator class PolygonIncomeStatementQueryParams(IncomeStatementQueryParams): @@ -22,6 +21,7 @@ class PolygonIncomeStatementQueryParams(IncomeStatementQueryParams): __alias_dict__ = {"symbol": "ticker", "period": "timeframe"} + period: Literal["annual", "quarter", "ttm"] = Field(default="annual") filing_date: Optional[date] = Field( default=None, description="Filing date of the financial statement." ) @@ -75,60 +75,171 @@ class PolygonIncomeStatementData(IncomeStatementData): """Polygon Income Statement Data.""" __alias_dict__ = { - "date": "start_date", - "accepted_date": "acceptance_datetime", - "period": "fiscal_period", + # pylint: disable=line-too-long "revenue": "revenues", + "provisions_for_loan_lease_and_other_losses": "provision_for_loan_lease_and_other_losses", + "income_tax_expense_benefit_current": "income_tax_expense_benefit_current", + "deferred_tax_benefit": "income_tax_expense_benefit_deferred", "operating_income": "operating_income_loss", + "non_operating_income": "nonoperating_income_loss", + "income_before_equity_method_investments": "income_loss_before_equity_method_investments", + "income_from_equity_method_investments": "income_loss_from_equity_method_investments", "income_before_tax": "income_loss_from_continuing_operations_before_tax", "income_tax_expense": "income_tax_expense_benefit", + "interest_and_debt_expense": "interest_and_debt_expense", "net_income": "net_income_loss", "eps": "basic_earnings_per_share", "eps_diluted": "diluted_earnings_per_share", + "interest_and_dividend_income": "interest_and_dividend_income_operating", "interest_expense": "interest_expense_operating", - "symbol": "tickers", + "interest_income_after_provision_for_losses": "interest_income_expense_after_provision_for_losses", + "interest_income_net": "interest_income_expense_operating_net", + "non_interest_income": "noninterest_income", + "non_interest_expense": "noninterest_expense", + "income_after_tax": "income_loss_from_continuing_operations_after_tax", + "income_from_discontinued_operations_net_of_tax_on_disposal": "income_loss_from_discontinued_operations_net_of_tax_gain_loss_on_disposal", # type: ignore # noqa: E501 + "income_from_discontinued_operations_net_of_tax": "income_loss_from_discontinued_operations_net_of_tax", + "net_income_attributable_minority_interest": "net_income_loss_attributable_to_noncontrolling_interest", + "net_income_attributable_to_parent": "net_income_loss_attributable_to_parent", + "net_income_available_to_stock_holders": "net_income_loss_available_to_common_stockholders_basic", + "participating_securities_earnings": "participating_securities_distributed_and_undistributed_earnings_loss_basic", + "undistributed_earnings_allocated_to_participating_securities": "undistributed_earnings_loss_allocated_to_participating_securities_basic", # type: ignore # noqa: E501 } - income_loss_from_continuing_operations_before_tax: Optional[float] = Field( - default=None, description="Income/Loss From Continuing Operations After Tax" + revenue: Optional[float] = Field(default=None, description="Total Revenue") + cost_of_revenue_goods: Optional[float] = Field( + default=None, description="Cost of Revenue - Goods" ) - income_loss_from_continuing_operations_after_tax: Optional[float] = Field( - default=None, description="Income (loss) from continuing operations after tax" + cost_of_revenue_services: Optional[float] = Field( + default=None, description="Cost of Revenue - Services" + ) + cost_of_revenue: Optional[float] = Field( + default=None, description="Cost of Revenue" + ) + gross_profit: Optional[float] = Field(default=None, description="Gross Profit") + provisions_for_loan_lease_and_other_losses: Optional[float] = Field( + default=None, description="Provisions for loan lease and other losses" + ) + depreciation_and_amortization: Optional[float] = Field( + default=None, description="Depreciation and Amortization" + ) + income_tax_expense_benefit_current: Optional[float] = Field( + default=None, description="Income tax expense benefit current" + ) + deferred_tax_benefit: Optional[float] = Field( + default=None, description="Deferred tax benefit" ) benefits_costs_expenses: Optional[float] = Field( default=None, description="Benefits, costs and expenses" ) - net_income_loss_attributable_to_noncontrolling_interest: Optional[ForceInt] = Field( + selling_general_and_administrative_expenses: Optional[float] = Field( + default=None, description="Selling, general and administrative expenses" + ) + research_and_development: Optional[float] = Field( + default=None, description="Research and development" + ) + costs_and_expenses: Optional[float] = Field( + default=None, description="Costs and expenses" + ) + other_operating_expenses: Optional[float] = Field( + default=None, description="Other Operating Expenses" + ) + operating_expenses: Optional[float] = Field( + default=None, description="Operating expenses" + ) + operating_income: Optional[float] = Field( + default=None, description="Operating Income/Loss" + ) + non_operating_income: Optional[float] = Field( + default=None, description="Non Operating Income/Loss" + ) + interest_and_dividend_income: Optional[float] = Field( + default=None, description="Interest and Dividend Income" + ) + interest_expense: Optional[float] = Field( + default=None, description="Interest Expense" + ) + interest_and_debt_expense: Optional[float] = Field( + default=None, description="Interest and Debt Expense" + ) + interest_income_net: Optional[float] = Field( + default=None, description="Interest Income Net" + ) + interest_income_after_provision_for_losses: Optional[float] = Field( + default=None, description="Interest Income After Provision for Losses" + ) + non_interest_expense: Optional[float] = Field( + default=None, description="Non-Interest Expense" + ) + non_interest_income: Optional[float] = Field( + default=None, description="Non-Interest Income" + ) + income_from_discontinued_operations_net_of_tax_on_disposal: Optional[float] = Field( + default=None, + description="Income From Discontinued Operations Net of Tax on Disposal", + ) + income_from_discontinued_operations_net_of_tax: Optional[float] = Field( + default=None, description="Income From Discontinued Operations Net of Tax" + ) + income_before_equity_method_investments: Optional[float] = Field( + default=None, description="Income Before Equity Method Investments" + ) + income_from_equity_method_investments: Optional[float] = Field( + default=None, description="Income From Equity Method Investments" + ) + income_before_tax: Optional[float] = Field( + default=None, description="Income Before Tax" + ) + income_tax_expense: Optional[float] = Field( + default=None, description="Income Tax Expense" + ) + income_after_tax: Optional[float] = Field( + default=None, description="Income After Tax" + ) + net_income: Optional[float] = Field(default=None, description="Net Income/Loss") + net_income_attributable_minority_interest: Optional[float] = Field( default=None, description="Net income (loss) attributable to noncontrolling interest", ) - net_income_loss_attributable_to_parent: Optional[float] = Field( + net_income_attributable_to_parent: Optional[float] = Field( default=None, description="Net income (loss) attributable to parent" ) - net_income_loss_available_to_common_stockholders_basic: Optional[float] = Field( + net_income_available_to_stock_holders: Optional[float] = Field( default=None, description="Net Income/Loss Available To Common Stockholders Basic", ) - participating_securities_distributed_and_undistributed_earnings_loss_basic: Optional[ - float - ] = Field( + participating_securities_earnings: Optional[float] = Field( default=None, description="Participating Securities Distributed And Undistributed Earnings Loss Basic", ) - nonoperating_income_loss: Optional[float] = Field( - default=None, description="Nonoperating Income Loss" + undistributed_earnings_allocated_to_participating_securities: Optional[ + float + ] = Field( + default=None, + description="Undistributed Earnings Allocated To Participating Securities", + ) + common_stock_dividends: Optional[float] = Field( + default=None, description="Common Stock Dividends" ) preferred_stock_dividends_and_other_adjustments: Optional[float] = Field( default=None, description="Preferred stock dividends and other adjustments" ) + basic_average_shares: Optional[float] = Field( + default=None, description="Basic Average Shares" + ) + diluted_average_shares: Optional[float] = Field( + default=None, description="Diluted Average Shares" + ) + eps: Optional[float] = Field(default=None, description="Earnings Per Share") + diluted_eps: Optional[float] = Field( + default=None, description="Diluted Earnings Per Share" + ) - @field_validator("symbol", mode="before", check_fields=False) + @model_validator(mode="before") @classmethod - def symbol_from_tickers(cls, v): - """Return a list of symbols as a list.""" - if isinstance(v, list): - return ",".join(v) - return v + def replace_zero(cls, values): # pylint: disable=no-self-argument + """Check for zero values and replace with None.""" + return {k: None if v == 0 else v for k, v in values.items()} class PolygonIncomeStatementFetcher( @@ -149,7 +260,7 @@ class PolygonIncomeStatementFetcher( query: PolygonIncomeStatementQueryParams, credentials: Optional[Dict[str, str]], **kwargs: Any, - ) -> dict: + ) -> Dict: """Return the raw data from the Intrinio endpoint.""" api_key = credentials.get("polygon_api_key") if credentials else "" @@ -160,9 +271,9 @@ class PolygonIncomeStatementFetcher( ) if query.symbol.isdigit(): - query_string = f"cik={query.symbol}&period={period}&{query_string}" + query_string = f"cik={query.symbol}&timeframe={period}&{query_string}" else: - query_string = f"ticker={query.symbol}&period={period}&{query_string}" + query_string = f"ticker={query.symbol}&timeframe={period}&{query_string}" request_url = f"{base_url}?{query_string}&apiKey={api_key}" @@ -171,7 +282,7 @@ class PolygonIncomeStatementFetcher( @staticmethod def transform_data( query: PolygonIncomeStatementQueryParams, - data: dict, + data: Dict, **kwargs: Any, ) -> List[PolygonIncomeStatementData]: """Return the transformed data.""" @@ -182,10 +293,8 @@ class PolygonIncomeStatementFetcher( key: value["value"] for key, value in item["financials"]["income_statement"].items() } - sub_data["date"] = item["start_date"] - sub_data["cik"] = item["cik"] - sub_data["symbol"] = item["tickers"] - sub_data["period"] = item["fiscal_period"] + sub_data["period_ending"] = item["end_date"] + sub_data["fiscal_period"] = item["fiscal_period"] transformed_data.append(PolygonIncomeStatementData(**sub_data)) return transformed_data diff --git a/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_balance_sheet_fetcher.yaml b/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_balance_sheet_fetcher.yaml index dc2b01d3515..d464b256eaf 100644 --- a/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_balance_sheet_fetcher.yaml +++ b/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_balance_sheet_fetcher.yaml @@ -3,89 +3,226 @@ interactions: body: null headers: Accept: - - '*/*' + - application/json Accept-Encoding: - - gzip, deflate, br + - gzip, deflate Connection: - keep-alive method: GET - uri: https://api.polygon.io/vX/reference/financials?apiKey=MOCK_API_KEY&limit=5&period=annual&ticker=AAPL&timeframe=annual + uri: https://api.polygon.io/vX/reference/financials?apiKey=MOCK_API_KEY&include_sources=True&limit=5&ticker=AAPL&timeframe=annual response: body: string: !!binary | - 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 - A5lff3i5ukl+u725cL//bwAAAP///IE69BSKAAA= + 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 + b6DO50b1W9i7b4XFy7//TwAAAP//UECe1fpqAQA= headers: Connection: - keep-alive @@ -94,9 +231,9 @@ interactions: Content-Type: - application/json Date: - - Thu, 02 Nov 2023 19:05:12 GMT + - Sun, 10 Dec 2023 00:00:13 GMT Link: - - ; + - ; rel="next" Server: - nginx/1.19.2 @@ -109,7 +246,7 @@ interactions: X-Item-Count: - '5' X-Request-Id: - - 89eab7fe2e1943a9c86a50e0d6721d4c + - 907a54ae5eab0bdd9ce68ab1ec24b2f4 status: code: 200 message: OK diff --git a/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_cash_flow_statement_fetcher.yaml b/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_cash_flow_statement_fetcher.yaml index 84c104b98de..c448dd9582f 100644 --- a/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_cash_flow_statement_fetcher.yaml +++ b/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_cash_flow_statement_fetcher.yaml @@ -3,89 +3,89 @@ interactions: body: null headers: Accept: - - '*/*' + - application/json Accept-Encoding: - - gzip, deflate, br + - gzip, deflate Connection: - keep-alive method: GET - uri: https://api.polygon.io/vX/reference/financials?apiKey=MOCK_API_KEY&limit=5&period=annual&ticker=AAPL&timeframe=annual + uri: https://api.polygon.io/vX/reference/financials?apiKey=MOCK_API_KEY&include_sources=False&limit=5&ticker=AAPL&timeframe=annual response: body: string: !!binary | - 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 headers: Connection: - keep-alive @@ -94,9 +94,9 @@ interactions: Content-Type: - application/json Date: - - Thu, 02 Nov 2023 19:06:56 GMT + - Sun, 10 Dec 2023 00:00:14 GMT Link: - - ; + - ; rel="next" Server: - nginx/1.19.2 @@ -109,7 +109,7 @@ interactions: X-Item-Count: - '5' X-Request-Id: - - b30089cc708a8ca63f6ff53489e8a883 + - 0622c6e0b74959a13b90beafbbfeec5c status: code: 200 message: OK diff --git a/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_income_statement_fetcher.yaml b/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_income_statement_fetcher.yaml index 2e9c5135f00..b27757b2a71 100644 --- a/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_income_statement_fetcher.yaml +++ b/openbb_platform/providers/polygon/tests/record/http/test_polygon_fetchers/test_polygon_income_statement_fetcher.yaml @@ -3,88 +3,90 @@ interactions: body: null headers: Accept: - - '*/*' + - application/json Accept-Encoding: - - gzip, deflate, br + - gzip, deflate Connection: - keep-alive method: GET - uri: https://api.polygon.io/vX/reference/financials?apiKey=MOCK_API_KEY&limit=5&period=annual&ticker=AAPL&timeframe=annual + uri: https://api.polygon.io/vX/reference/financials?apiKey=MOCK_API_KEY&limit=5&ticker=AAPL&timeframe=annual&timeframe=annual response: body: string: !!binary | - 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 headers: Connection: - keep-alive @@ -93,9 +95,9 @@ interactions: Content-Type: - application/json Date: - - Thu, 02 Nov 2023 19:06:41 GMT + - Sun, 10 Dec 2023 00:00:13 GMT Link: - - ; + - ; rel="next" Server: - nginx/1.19.2 @@ -108,7 +110,7 @@ interactions: X-Item-Count: - '5' X-Request-Id: - - d9dd692f21d982102da810b8a45d5585 + - 19e7d9c4ce7750f96caaa9c0498cb3bd status: code: 200 message: OK diff --git a/openbb_platform/providers/yfinance/openbb_yfinance/models/balance_sheet.py b/openbb_platform/providers/yfinance/openbb_yfinance/models/balance_sheet.py index 03fe0f8edc8..4137a052381 100644 --- a/openbb_platform/providers/yfinance/openbb_yfinance/models/balance_sheet.py +++ b/openbb_platform/providers/yfinance/openbb_yfinance/models/balance_sheet.py @@ -10,8 +10,8 @@ from openbb_core.provider.standard_models.balance_sheet import ( BalanceSheetData, BalanceSheetQueryParams, ) -from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.helpers import to_snake_case from pydantic import Field, field_validator from yfinance import Ticker @@ -22,18 +22,24 @@ class YFinanceBalanceSheetQueryParams(BalanceSheetQueryParams): Source: https://finance.yahoo.com/ """ - period: Optional[Literal["annual", "quarter"]] = Field( - default="quarter", - description=QUERY_DESCRIPTIONS.get("period", ""), - ) + period: Optional[Literal["annual", "quarter"]] = Field(default="annual") class YFinanceBalanceSheetData(BalanceSheetData): """Yahoo Finance Balance Sheet Data.""" - # TODO: Standardize the fields + __alias_dict__ = { + "short_term_investments": "other_short_term_investments", + "net_receivables": "receivables", + "inventories": "inventory", + "total_current_assets": "current_assets", + "plant_property_equipment_gross": "gross_ppe", + "plant_property_equipment_net": "net_ppe", + "total_common_equity": "stockholders_equity", + "total_equity_non_controlling_interests": "total_equity_gross_minority_interest", + } - @field_validator("date", mode="before", check_fields=False) + @field_validator("period_ending", mode="before", check_fields=False) @classmethod def date_validate(cls, v): # pylint: disable=E0213 """Return datetime object from string.""" @@ -52,27 +58,28 @@ class YFinanceBalanceSheetFetcher( @staticmethod def transform_query(params: Dict[str, Any]) -> YFinanceBalanceSheetQueryParams: + """Transform the query parameters.""" return YFinanceBalanceSheetQueryParams(**params) @staticmethod def extract_data( + # pylint: disable=unused-argument query: YFinanceBalanceSheetQueryParams, credentials: Optional[Dict[str, str]], **kwargs: Any, ) -> List[Dict]: + """Extract the data from the Yahoo Finance endpoints.""" period = "yearly" if query.period == "annual" else "quarterly" # type: ignore data = Ticker(query.symbol).get_balance_sheet( as_dict=False, pretty=False, freq=period ) if data is None: raise EmptyDataError() + data.index = [to_snake_case(i) for i in data.index] + data = data.reset_index().sort_index(ascending=False).set_index("index") + data = data.convert_dtypes().fillna(0).replace(0, None).to_dict() + data = [{"period_ending": str(key), **value} for key, value in data.items()] - data = data.convert_dtypes().fillna(0).to_dict() - - data = [{"date": str(key), **value} for key, value in data.items()] - # To match standardization - for d in data: - d["Symbol"] = query.symbol data = json.loads(json.dumps(data)) return data @@ -83,4 +90,5 @@ class YFinanceBalanceSheetFetcher( data: List[Dict], **kwargs: Any, ) -> List[YFinanceBalanceSheetData]: + """Transform the data.""" return [YFinanceBalanceSheetData.model_validate(d) for d in data] diff --git a/openbb_platform/providers/yfinance/openbb_yfinance/models/cash_flow.py b/openbb_platform/providers/yfinance/openbb_yfinance/models/cash_flow.py index 64f933369a8..afc8da5f716 100644 --- a/openbb_platform/providers/yfinance/openbb_yfinance/models/cash_flow.py +++ b/openbb_platform/providers/yfinance/openbb_yfinance/models/cash_flow.py @@ -9,8 +9,8 @@ from openbb_core.provider.standard_models.cash_flow import ( CashFlowStatementData, CashFlowStatementQueryParams, ) -from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.helpers import to_snake_case from pydantic import Field, field_validator from yfinance import Ticker @@ -21,18 +21,21 @@ class YFinanceCashFlowStatementQueryParams(CashFlowStatementQueryParams): Source: https://finance.yahoo.com/ """ - period: Optional[Literal["annual", "quarter"]] = Field( - default="quarter", - description=QUERY_DESCRIPTIONS.get("period", ""), - ) + period: Optional[Literal["annual", "quarter"]] = Field(default="annual") class YFinanceCashFlowStatementData(CashFlowStatementData): """Yahoo Finance Cash Flow Statement Data.""" - # TODO: Standardize the fields + __alias_dict__ = { + "investments_in_property_plant_and_equipment": "purchase_of_ppe", + "issuance_of_common_equity": "common_stock_issuance", + "repurchase_of_common_equity": "common_stock_payments", + "cash_dividends_paid": "payment_of_dividends", + "net_change_in_cash_and_equivalents": "changes_in_cash", + } - @field_validator("date", mode="before", check_fields=False) + @field_validator("period_ending", mode="before", check_fields=False) @classmethod def date_validate(cls, v): # pylint: disable=E0213 """Return datetime object from string.""" @@ -51,14 +54,17 @@ class YFinanceCashFlowStatementFetcher( @staticmethod def transform_query(params: Dict[str, Any]) -> YFinanceCashFlowStatementQueryParams: + """Transform the query parameters.""" return YFinanceCashFlowStatementQueryParams(**params) @staticmethod def extract_data( + # pylint: disable=unused-argument query: YFinanceCashFlowStatementQueryParams, credentials: Optional[Dict[str, str]], **kwargs: Any, ) -> List[YFinanceCashFlowStatementData]: + """Extract the data from the Yahoo Finance endpoints.""" period = "yearly" if query.period == "annual" else "quarterly" # type: ignore data = Ticker(query.symbol).get_cash_flow( as_dict=False, pretty=False, freq=period @@ -67,20 +73,21 @@ class YFinanceCashFlowStatementFetcher( if data is None: raise EmptyDataError() - data = data.fillna(0).to_dict() + data.index = [to_snake_case(i) for i in data.index] + data = data.reset_index().sort_index(ascending=False).set_index("index") + data = data.convert_dtypes().fillna(0).replace(0, None).to_dict() + data = [{"period_ending": str(key), **value} for key, value in data.items()] - data = [{"date": str(key), **value} for key, value in data.items()] - # To match standardization - for d in data: - d["Symbol"] = query.symbol data = json.loads(json.dumps(data)) return data @staticmethod def transform_data( + # pylint: disable=unused-argument query: YFinanceCashFlowStatementQueryParams, data: List[Dict], **kwargs: Any, ) -> List[YFinanceCashFlowStatementData]: + """Transform the data.""" return [YFinanceCashFlowStatementData.model_validate(d) for d in data] diff --git a/openbb_platform/providers/yfinance/openbb_yfinance/models/income_statement.py b/openbb_platform/providers/yfinance/openbb_yfinance/models/income_statement.py index 97afbb84931..68c282aa21b 100644 --- a/openbb_platform/providers/yfinance/openbb_yfinance/models/income_statement.py +++ b/openbb_platform/providers/yfinance/openbb_yfinance/models/income_statement.py @@ -2,14 +2,16 @@ import json from datetime import datetime -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Literal, Optional from openbb_core.provider.abstract.fetcher import Fetcher from openbb_core.provider.standard_models.income_statement import ( IncomeStatementData, IncomeStatementQueryParams, ) -from pydantic import field_validator +from openbb_core.provider.utils.errors import EmptyDataError +from openbb_core.provider.utils.helpers import to_snake_case +from pydantic import Field, field_validator from yfinance import Ticker @@ -19,13 +21,26 @@ class YFinanceIncomeStatementQueryParams(IncomeStatementQueryParams): Source: https://finance.yahoo.com/ """ + period: Optional[Literal["annual", "quarter"]] = Field(default="annual") + class YFinanceIncomeStatementData(IncomeStatementData): """Yahoo Finance Income Statement Data.""" - # TODO: Standardize the fields - @field_validator("date", mode="before", check_fields=False) + __alias_dict__ = { + "selling_general_and_admin_expense": "selling_general_and_administration", + "research_and_development_expense": "research_and_development", + "total_pre_tax_income": "pretax_income", + "net_income_attributable_to_common_shareholders": "net_income_common_stockholders", + "weighted_average_basic_shares_outstanding": "basic_average_shares", + "weighted_average_diluted_shares_outstanding": "diluted_average_shares", + "basic_earnings_per_share": "basic_eps", + "diluted_earnings_per_share": "diluted_eps", + } + + @field_validator("period_ending", mode="before", check_fields=False) def date_validate(cls, v): # pylint: disable=E0213 + """Validate the date field.""" if isinstance(v, str): return datetime.strptime(v, "%Y-%m-%d %H:%M:%S").date() return v @@ -41,23 +56,28 @@ class YFinanceIncomeStatementFetcher( @staticmethod def transform_query(params: Dict[str, Any]) -> YFinanceIncomeStatementQueryParams: + """Transform the query parameters.""" return YFinanceIncomeStatementQueryParams(**params) @staticmethod def extract_data( + # pylint: disable=unused-argument query: YFinanceIncomeStatementQueryParams, credentials: Optional[Dict[str, str]], **kwargs: Any, ) -> List[YFinanceIncomeStatementData]: + """Extract the data from the Yahoo Finance endpoints.""" period = "yearly" if query.period == "annual" else "quarterly" data = Ticker(query.symbol).get_income_stmt( as_dict=False, pretty=False, freq=period ) - data = data.convert_dtypes().fillna(0).to_dict() - data = [{"date": str(key), **value} for key, value in data.items()] - # To match standardization - for d in data: - d["Symbol"] = query.symbol + if data is None: + raise EmptyDataError() + data.index = [to_snake_case(i) for i in data.index] + data = data.reset_index().sort_index(ascending=False).set_index("index") + data = data.convert_dtypes().fillna(0).replace(0, None).to_dict() + data = [{"period_ending": str(key), **value} for key, value in data.items()] + data = json.loads(json.dumps(data)) return data @@ -68,4 +88,5 @@ class YFinanceIncomeStatementFetcher( data: List[Dict], **kwargs: Any, ) -> List[YFinanceIncomeStatementData]: + """Transform the data.""" return [YFinanceIncomeStatementData.model_validate(d) for d in data] diff --git a/openbb_platform/providers/yfinance/tests/record/http/test_yfinance_fetchers/test_y_finance_balance_sheet_fetcher.yaml b/openbb_platform/providers/yfinance/tests/record/http/test_yfinance_fetchers/test_y_finance_balance_sheet_fetcher.yaml index 2135d82cf89..8bf34133aa4 100644 --- a/openbb_platform/providers/yfinance/tests/record/http/test_yfinance_fetchers/test_y_finance_balance_sheet_fetcher.yaml +++ b/openbb_platform/providers/yfinance/tests/record/http/test_yfinance_fetchers/test_y_finance_balance_sheet_fetcher.yaml @@ -1,4 +1,102 @@ interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Connection: + - keep-alive + method: GET + uri: https://fc.yahoo.com/ + response: + body: + string: "\n\n \n \n \n Yahoo\n + \ \n + \ \n \n \n + \ \n \n \n \n \n \n \n \n \n \n\n" + headers: + Cache-Control: + - no-store + Connection: + - keep-alive + Content-Language: + - en + Content-Length: + - '4350' + Content-Type: + - text/html + Date: + - Sun, 10 Dec 2023 06:04:04 GMT + Expect-CT: + - max-age=31536000, report-uri="http://csp.yahoo.com/beacon/csp?src=yahoocom-expect-ct-report-only" + Server: + - ATS + Set-Cookie: + - A3=d=AQABBMNUdWUCEHHotkmiYDzy9IYxIAom2AMFEgEBAQGmdmV_ZSXUxyMA_eMAAA&S=AQAAAq0ej1llRnFRH7mN3U_LlbQ; + Expires=Mon, 9 Dec 2024 12:04:04 GMT; Max-Age=31557600; Domain=.yahoo.com; + Path=/; SameSite=None; Secure; HttpOnly + Strict-Transport-Security: + - max-age=31536000 + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + status: + code: 502 + message: Connection timed out - request: body: null headers: @@ -11,103 +109,143 @@ interactions: Cookie: - MOCK_COOKIE method: GET - uri: https://query2.finance.yahoo.com/ws/fundamentals-timeseries/v1/finance/timeseries/AAPL?crumb=MOCK_CRUMB&period1=MOCK_PERIOD_1&period2=MOCK_PERIOD_2&symbol=AAPL&type=quarterlyTreasurySharesNumber%2CquarterlyPreferredSharesNumber%2CquarterlyOrdinarySharesNumber%2CquarterlyShareIssued%2CquarterlyNetDebt%2CquarterlyTotalDebt%2CquarterlyTangibleBookValue%2CquarterlyInvestedCapital%2CquarterlyWorkingCapital%2CquarterlyNetTangibleAssets%2CquarterlyCapitalLeaseObligations%2CquarterlyCommonStockEquity%2CquarterlyPreferredStockEquity%2CquarterlyTotalCapitalization%2CquarterlyTotalEquityGrossMinorityInterest%2CquarterlyMinorityInterest%2CquarterlyStockholdersEquity%2CquarterlyOtherEquityInterest%2CquarterlyGainsLossesNotAffectingRetainedEarnings%2CquarterlyOtherEquityAdjustments%2CquarterlyFixedAssetsRevaluationReserve%2CquarterlyForeignCurrencyTranslationAdjustments%2CquarterlyMinimumPensionLiabilities%2CquarterlyUnrealizedGainLoss%2CquarterlyTreasuryStock%2CquarterlyRetainedEarnings%2CquarterlyAdditionalPaidInCapital%2CquarterlyCapitalStock%2CquarterlyOtherCapitalStock%2CquarterlyCommonStock%2CquarterlyPreferredStock%2CquarterlyTotalPartnershipCapital%2CquarterlyGeneralPartnershipCapital%2CquarterlyLimitedPartnershipCapital%2CquarterlyTotalLiabilitiesNetMinorityInterest%2CquarterlyTotalNonCurrentLiabilitiesNetMinorityInterest%2CquarterlyOtherNonCurrentLiabilities%2CquarterlyLiabilitiesHeldforSaleNonCurrent%2CquarterlyRestrictedCommonStock%2CquarterlyPreferredSecuritiesOutsideStockEquity%2CquarterlyDerivativeProductLiabilities%2CquarterlyEmployeeBenefits%2CquarterlyNonCurrentPensionAndOtherPostretirementBenefitPlans%2CquarterlyNonCurrentAccruedExpenses%2CquarterlyDuetoRelatedPartiesNonCurrent%2CquarterlyTradeandOtherPayablesNonCurrent%2CquarterlyNonCurrentDeferredLiabilities%2CquarterlyNonCurrentDeferredRevenue%2CquarterlyNonCurrentDeferredTaxesLiabilities%2CquarterlyLongTermDebtAndCapitalLeaseObligation%2CquarterlyLongTermCapitalLeaseObligation%2CquarterlyLongTermDebt%2CquarterlyLongTermProvisions%2CquarterlyCurrentLiabilities%2CquarterlyOtherCurrentLiabilities%2CquarterlyCurrentDeferredLiabilities%2CquarterlyCurrentDeferredRevenue%2CquarterlyCurrentDeferredTaxesLiabilities%2CquarterlyCurrentDebtAndCapitalLeaseObligation%2CquarterlyCurrentCapitalLeaseObligation%2CquarterlyCurrentDebt%2CquarterlyOtherCurrentBorrowings%2CquarterlyLineOfCredit%2CquarterlyCommercialPaper%2CquarterlyCurrentNotesPayable%2CquarterlyPensionandOtherPostRetirementBenefitPlansCurrent%2CquarterlyCurrentProvisions%2CquarterlyPayablesAndAccruedExpenses%2CquarterlyCurrentAccruedExpenses%2CquarterlyInterestPayable%2CquarterlyPayables%2CquarterlyOtherPayable%2CquarterlyDuetoRelatedPartiesCurrent%2CquarterlyDividendsPayable%2CquarterlyTotalTaxPayable%2CquarterlyIncomeTaxPayable%2CquarterlyAccountsPayable%2CquarterlyTotalAssets%2CquarterlyTotalNonCurrentAssets%2CquarterlyOtherNonCurrentAssets%2CquarterlyDefinedPensionBenefit%2CquarterlyNonCurrentPrepaidAssets%2CquarterlyNonCurrentDeferredAssets%2CquarterlyNonCurrentDeferredTaxesAssets%2CquarterlyDuefromRelatedPartiesNonCurrent%2CquarterlyNonCurrentNoteReceivables%2CquarterlyNonCurrentAccountsReceivable%2CquarterlyFinancialAssets%2CquarterlyInvestmentsAndAdvances%2CquarterlyOtherInvestments%2CquarterlyInvestmentinFinancialAssets%2CquarterlyHeldToMaturitySecurities%2CquarterlyAvailableForSaleSecurities%2CquarterlyFinancialAssetsDesignatedasFairValueThroughProfitorLossTotal%2CquarterlyTradingSecurities%2CquarterlyLongTermEquityInvestment%2CquarterlyInvestmentsinJointVenturesatCost%2CquarterlyInvestmentsInOtherVenturesUnderEquityMethod%2CquarterlyInvestmentsinAssociatesatCost%2CquarterlyInvestmentsinSubsidiariesatCost%2CquarterlyInvestmentProperties%2CquarterlyGoodwillAndOtherIntangibleAssets%2CquarterlyOtherIntangibleAssets%2CquarterlyGoodwill%2CquarterlyNetPPE%2CquarterlyAccumulatedDepreciation%2CquarterlyGrossPPE%2CquarterlyLeases%2CquarterlyConstructionInProgress%2CquarterlyOtherProperties%2CquarterlyMachineryFurnitureEquipment%2CquarterlyBuildingsAndImprovements%2CquarterlyLandAndImprovements%2CquarterlyProperties%2CquarterlyCurrentAssets%2CquarterlyOtherCurrentAssets%2CquarterlyHedgingAssetsCurrent%2CquarterlyAssetsHeldForSaleCurrent%2CquarterlyCurrentDeferredAssets%2CquarterlyCurrentDeferredTaxesAssets%2CquarterlyRestrictedCash%2CquarterlyPrepaidAssets%2CquarterlyInventory%2CquarterlyInventoriesAdjustmentsAllowances%2CquarterlyOtherInventories%2CquarterlyFinishedGoods%2CquarterlyWorkInProcess%2CquarterlyRawMaterials%2CquarterlyReceivables%2CquarterlyReceivablesAdjustmentsAllowances%2CquarterlyOtherReceivables%2CquarterlyDuefromRelatedPartiesCurrent%2CquarterlyTaxesReceivable%2CquarterlyAccruedInterestReceivable%2CquarterlyNotesReceivable%2CquarterlyLoansReceivable%2CquarterlyAccountsReceivable%2CquarterlyAllowanceForDoubtfulAccountsReceivable%2CquarterlyGrossAccountsReceivable%2CquarterlyCashCashEquivalentsAndShortTermInvestments%2CquarterlyOtherShortTermInvestments%2CquarterlyCashAndCashEquivalents%2CquarterlyCashEquivalents%2CquarterlyCashFinancial + uri: https://query1.finance.yahoo.com/v1/test/getcrumb + response: + body: + string: PcpVn10YeHm + headers: + Age: + - '0' + Connection: + - keep-alive + Expect-CT: + - max-age=31536000, report-uri="http://csp.yahoo.com/beacon/csp?src=yahoocom-expect-ct-report-only" + Referrer-Policy: + - no-referrer-when-downgrade + Strict-Transport-Security: + - max-age=31536000 + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + cache-control: + - private + content-type: + - text/plain;charset=utf-8 + date: + - Sun, 10 Dec 2023 06:04:04 GMT + server: + - ATS + x-envoy-decorator-operation: + - finance-yql--mtls-default-production-gq1.finance-k8s.svc.yahoo.local:4080/* + x-envoy-upstream-service-time: + - '1' + x-frame-options: + - SAMEORIGIN + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Connection: + - keep-alive + Cookie: + - MOCK_COOKIE + method: GET + uri: https://query2.finance.yahoo.com/ws/fundamentals-timeseries/v1/finance/timeseries/AAPL?crumb=MOCK_CRUMB&period1=MOCK_PERIOD_1&period2=MOCK_PERIOD_2&symbol=AAPL&type=annualTreasurySharesNumber%2CannualPreferredSharesNumber%2CannualOrdinarySharesNumber%2CannualShareIssued%2CannualNetDebt%2CannualTotalDebt%2CannualTangibleBookValue%2CannualInvestedCapital%2CannualWorkingCapital%2CannualNetTangibleAssets%2CannualCapitalLeaseObligations%2CannualCommonStockEquity%2CannualPreferredStockEquity%2CannualTotalCapitalization%2CannualTotalEquityGrossMinorityInterest%2CannualMinorityInterest%2CannualStockholdersEquity%2CannualOtherEquityInterest%2CannualGainsLossesNotAffectingRetainedEarnings%2CannualOtherEquityAdjustments%2CannualFixedAssetsRevaluationReserve%2CannualForeignCurrencyTranslationAdjustments%2CannualMinimumPensionLiabilities%2CannualUnrealizedGainLoss%2CannualTreasuryStock%2CannualRetainedEarnings%2CannualAdditionalPaidInCapital%2CannualCapitalStock%2CannualOtherCapitalStock%2CannualCommonStock%2CannualPreferredStock%2CannualTotalPartnershipCapital%2CannualGeneralPartnershipCapital%2CannualLimitedPartnershipCapital%2CannualTotalLiabilitiesNetMinorityInterest%2CannualTotalNonCurrentLiabilitiesNetMinorityInterest%2CannualOtherNonCurrentLiabilities%2CannualLiabilitiesHeldforSaleNonCurrent%2CannualRestrictedCommonStock%2CannualPreferredSecuritiesOutsideStockEquity%2CannualDerivativeProductLiabilities%2CannualEmployeeBenefits%2CannualNonCurrentPensionAndOtherPostretirementBenefitPlans%2CannualNonCurrentAccruedExpenses%2CannualDuetoRelatedPartiesNonCurrent%2CannualTradeandOtherPayablesNonCurrent%2CannualNonCurrentDeferredLiabilities%2CannualNonCurrentDeferredRevenue%2CannualNonCurrentDeferredTaxesLiabilities%2CannualLongTermDebtAndCapitalLeaseObligation%2CannualLongTermCapitalLeaseObligation%2CannualLongTermDebt%2CannualLongTermProvisions%2CannualCurrentLiabilities%2CannualOtherCurrentLiabilities%2CannualCurrentDeferredLiabilities%2CannualCurrentDeferredRevenue%2CannualCurrentDeferredTaxesLiabilities%2CannualCurrentDebtAndCapitalLeaseObligation%2CannualCurrentCapitalLeaseObligation%2CannualCurrentDebt%2CannualOtherCurrentBorrowings%2CannualLineOfCredit%2CannualCommercialPaper%2CannualCurrentNotesPayable%2CannualPensionandOtherPostRetirementBenefitPlansCurrent%2CannualCurrentProvisions%2CannualPayablesAndAccruedExpenses%2CannualCurrentAccruedExpenses%2CannualInterestPayable%2CannualPayables%2CannualOtherPayable%2CannualDuetoRelatedPartiesCurrent%2CannualDividendsPayable%2CannualTotalTaxPayable%2CannualIncomeTaxPayable%2CannualAccountsPayable%2CannualTotalAssets%2CannualTotalNonCurrentAssets%2CannualOtherNonCurrentAssets%2CannualDefinedPensionBenefit%2CannualNonCurrentPrepaidAssets%2CannualNonCurrentDeferredAssets%2CannualNonCurrentDeferredTaxesAssets%2CannualDuefromRelatedPartiesNonCurrent%2CannualNonCurrentNoteReceivables%2CannualNonCurrentAccountsReceivable%2CannualFinancialAssets%2CannualInvestmentsAndAdvances%2CannualOtherInvestments%2CannualInvestmentinFinancialAssets%2CannualHeldToMaturitySecurities%2CannualAvailableForSaleSecurities%2CannualFinancialAssetsDesignatedasFairValueThroughProfitorLossTotal%2CannualTradingSecurities%2CannualLongTermEquityInvestment%2CannualInvestmentsinJointVenturesatCost%2CannualInvestmentsInOtherVenturesUnderEquityMethod%2CannualInvestmentsinAssociatesatCost%2CannualInvestmentsinSubsidiariesatCost%2CannualInvestmentProperties%2CannualGoodwillAndOtherIntangibleAssets%2CannualOtherIntangibleAssets%2CannualGoodwill%2CannualNetPPE%2CannualAccumulatedDepreciation%2CannualGrossPPE%2CannualLeases%2CannualConstructionInProgress%2CannualOtherProperties%2CannualMachineryFurnitureEquipment%2CannualBuildingsAndImprovements%2CannualLandAndImprovements%2CannualProperties%2CannualCurrentAssets%2CannualOtherCurrentAssets%2CannualHedgingAssetsCurrent%2CannualAssetsHeldForSaleCurrent%2CannualCurrentDeferredAssets%2CannualCurrentDeferredTaxesAssets%2CannualRestrictedCash%2CannualPrepaidAssets%2CannualInventory%2CannualInventoriesAdjustmentsAllowances%2CannualOtherInventories%2CannualFinishedGoods%2CannualWorkInProcess%2CannualRawMaterials%2CannualReceivables%2CannualReceivablesAdjustmentsAllowances%2CannualOtherReceivables%2CannualDuefromRelatedPartiesCurrent%2CannualTaxesReceivable%2CannualAccruedInterestReceivable%2CannualNotesReceivable%2CannualLoansReceivable%2CannualAccountsReceivable%2CannualAllowanceForDoubtfulAccountsReceivable%2CannualGrossAccountsReceivable%2CannualCashCashEquivalentsAndShortTermInvestments%2CannualOtherShortTermInvestments%2CannualCashAndCashEquivalents%2CannualCashEquivalents%2CannualCashFinancial response: body: string: !!binary | - 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 - QEib9uSXerVYfP/+/17keudpyAAA + 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 headers: Age: - '0' @@ -132,7 +270,7 @@ interactions: content-type: - application/json;charset=utf-8 date: - - Mon, 27 Nov 2023 23:48:22 GMT + - Sun, 10 Dec 2023 06:04:04 GMT server: - ATS vary: @@ -140,7 +278,7 @@ interactions: x-envoy-decorator-operation: - finance-company-fundamentals-api--mtls-production-gq1.finance-k8s.svc.yahoo.local:4080/* x-envoy-upstream-service-time: - - '125' + - '52' status: code: 200 message: OK diff --git a/openbb_platform/providers/yfinance/tests/record/http/test_yfinance_fetchers/test_y_finance_cash_flow_statement_fetcher.yaml b/openbb_platform/providers/yfinance/tests/record/http/test_yfinance_fetchers/test_y_finance_cash_flow_statement_fetcher.yaml index 2c9f8470193..ed3550fcc7f 100644 --- a/openbb_platform/providers/yfinance/tests/record/http/test_yfinance_fetchers/test_y_finance_cash_flow_statement_fetcher.yaml +++ b/openbb_platform/providers/yfinance/tests/record/http/test_yfinance_fetchers/test_y_finance_cash_flow_statement_fetcher.yaml @@ -1,4 +1,102 @@ interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Connection: + - keep-alive + method: GET + uri: https://fc.yahoo.com/ + response: + body: + string: "\n\n \n \n \n Yahoo\n + \ \n + \ \n \n \n + \ \n \n \n \n \n \n \n \n \n \n\n" + headers: + Cache-Control: + - no-store + Connection: + - keep-alive + Content-Language: + - en + Content-Length: + - '4352' + Content-Type: + - text/html + Date: + - Sun, 10 Dec 2023 06:05:23 GMT + Expect-CT: + - max-age=31536000, report-uri="http://csp.yahoo.com/beacon/csp?src=yahoocom-expect-ct-report-only" + Server: + - ATS + Set-Cookie: + - A3=d=AQABBBJVdWUCEIVe01LHL8MRSTvwZ_jk5DsFEgEBAQGmdmV_ZSXUxyMA_eMAAA&S=AQAAAnUrE59Vd8D7AXpm4AfeXE4; + Expires=Mon, 9 Dec 2024 12:05:23 GMT; Max-Age=31557600; Domain=.yahoo.com; + Path=/; SameSite=None; Secure; HttpOnly + Strict-Transport-Security: + - max-age=31536000 + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + status: + code: 502 + message: Connection timed out - request: body: null headers: @@ -11,85 +109,132 @@ interactions: Cookie: - MOCK_COOKIE method: GET - uri: https://query2.finance.yahoo.com/ws/fundamentals-timeseries/v1/finance/timeseries/AAPL?crumb=MOCK_CRUMB&period1=MOCK_PERIOD_1&period2=MOCK_PERIOD_2&symbol=AAPL&type=quarterlyForeignSales%2CquarterlyDomesticSales%2CquarterlyAdjustedGeographySegmentData%2CquarterlyFreeCashFlow%2CquarterlyRepurchaseOfCapitalStock%2CquarterlyRepaymentOfDebt%2CquarterlyIssuanceOfDebt%2CquarterlyIssuanceOfCapitalStock%2CquarterlyCapitalExpenditure%2CquarterlyInterestPaidSupplementalData%2CquarterlyIncomeTaxPaidSupplementalData%2CquarterlyEndCashPosition%2CquarterlyOtherCashAdjustmentOutsideChangeinCash%2CquarterlyBeginningCashPosition%2CquarterlyEffectOfExchangeRateChanges%2CquarterlyChangesInCash%2CquarterlyOtherCashAdjustmentInsideChangeinCash%2CquarterlyCashFlowFromDiscontinuedOperation%2CquarterlyFinancingCashFlow%2CquarterlyCashFromDiscontinuedFinancingActivities%2CquarterlyCashFlowFromContinuingFinancingActivities%2CquarterlyNetOtherFinancingCharges%2CquarterlyInterestPaidCFF%2CquarterlyProceedsFromStockOptionExercised%2CquarterlyCashDividendsPaid%2CquarterlyPreferredStockDividendPaid%2CquarterlyCommonStockDividendPaid%2CquarterlyNetPreferredStockIssuance%2CquarterlyPreferredStockPayments%2CquarterlyPreferredStockIssuance%2CquarterlyNetCommonStockIssuance%2CquarterlyCommonStockPayments%2CquarterlyCommonStockIssuance%2CquarterlyNetIssuancePaymentsOfDebt%2CquarterlyNetShortTermDebtIssuance%2CquarterlyShortTermDebtPayments%2CquarterlyShortTermDebtIssuance%2CquarterlyNetLongTermDebtIssuance%2CquarterlyLongTermDebtPayments%2CquarterlyLongTermDebtIssuance%2CquarterlyInvestingCashFlow%2CquarterlyCashFromDiscontinuedInvestingActivities%2CquarterlyCashFlowFromContinuingInvestingActivities%2CquarterlyNetOtherInvestingChanges%2CquarterlyInterestReceivedCFI%2CquarterlyDividendsReceivedCFI%2CquarterlyNetInvestmentPurchaseAndSale%2CquarterlySaleOfInvestment%2CquarterlyPurchaseOfInvestment%2CquarterlyNetInvestmentPropertiesPurchaseAndSale%2CquarterlySaleOfInvestmentProperties%2CquarterlyPurchaseOfInvestmentProperties%2CquarterlyNetBusinessPurchaseAndSale%2CquarterlySaleOfBusiness%2CquarterlyPurchaseOfBusiness%2CquarterlyNetIntangiblesPurchaseAndSale%2CquarterlySaleOfIntangibles%2CquarterlyPurchaseOfIntangibles%2CquarterlyNetPPEPurchaseAndSale%2CquarterlySaleOfPPE%2CquarterlyPurchaseOfPPE%2CquarterlyCapitalExpenditureReported%2CquarterlyOperatingCashFlow%2CquarterlyCashFromDiscontinuedOperatingActivities%2CquarterlyCashFlowFromContinuingOperatingActivities%2CquarterlyTaxesRefundPaid%2CquarterlyInterestReceivedCFO%2CquarterlyInterestPaidCFO%2CquarterlyDividendReceivedCFO%2CquarterlyDividendPaidCFO%2CquarterlyChangeInWorkingCapital%2CquarterlyChangeInOtherWorkingCapital%2CquarterlyChangeInOtherCurrentLiabilities%2CquarterlyChangeInOtherCurrentAssets%2CquarterlyChangeInPayablesAndAccruedExpense%2CquarterlyChangeInAccruedExpense%2CquarterlyChangeInInterestPayable%2CquarterlyChangeInPayable%2CquarterlyChangeInDividendPayable%2CquarterlyChangeInAccountPayable%2CquarterlyChangeInTaxPayable%2CquarterlyChangeInIncomeTaxPayable%2CquarterlyChangeInPrepaidAssets%2CquarterlyChangeInInventory%2CquarterlyChangeInReceivables%2CquarterlyChangesInAccountReceivables%2CquarterlyOtherNonCashItems%2CquarterlyExcessTaxBenefitFromStockBasedCompensation%2CquarterlyStockBasedCompensation%2CquarterlyUnrealizedGainLossOnInvestmentSecurities%2CquarterlyProvisionandWriteOffofAssets%2CquarterlyAssetImpairmentCharge%2CquarterlyAmortizationOfSecurities%2CquarterlyDeferredTax%2CquarterlyDeferredIncomeTax%2CquarterlyDepreciationAmortizationDepletion%2CquarterlyDepletion%2CquarterlyDepreciationAndAmortization%2CquarterlyAmortizationCashFlow%2CquarterlyAmortizationOfIntangibles%2CquarterlyDepreciation%2CquarterlyOperatingGainsLosses%2CquarterlyPensionAndEmployeeBenefitExpense%2CquarterlyEarningsLossesFromEquityInvestments%2CquarterlyGainLossOnInvestmentSecurities%2CquarterlyNetForeignCurrencyExchangeGainLoss%2CquarterlyGainLossOnSaleOfPPE%2CquarterlyGainLossOnSaleOfBusiness%2CquarterlyNetIncomeFromContinuingOperations%2CquarterlyCashFlowsfromusedinOperatingActivitiesDirect%2CquarterlyTaxesRefundPaidDirect%2CquarterlyInterestReceivedDirect%2CquarterlyInterestPaidDirect%2CquarterlyDividendsReceivedDirect%2CquarterlyDividendsPaidDirect%2CquarterlyClassesofCashPayments%2CquarterlyOtherCashPaymentsfromOperatingActivities%2CquarterlyPaymentsonBehalfofEmployees%2CquarterlyPaymentstoSuppliersforGoodsandServices%2CquarterlyClassesofCashReceiptsfromOperatingActivities%2CquarterlyOtherCashReceiptsfromOperatingActivities%2CquarterlyReceiptsfromGovernmentGrants%2CquarterlyReceiptsfromCustomers + uri: https://query1.finance.yahoo.com/v1/test/getcrumb + response: + body: + string: mx0kCCtsr8A + headers: + Age: + - '0' + Connection: + - keep-alive + Expect-CT: + - max-age=31536000, report-uri="http://csp.yahoo.com/beacon/csp?src=yahoocom-expect-ct-report-only" + Referrer-Policy: + - no-referrer-when-downgrade + Strict-Transport-Security: + - max-age=31536000 + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-XSS-Protection: + - 1; mode=block + cache-control: + - private + content-type: + - text/plain;charset=utf-8 + date: + - Sun, 10 Dec 2023 06:05:23 GMT + server: + - ATS + x-envoy-decorator-operation: + - finance-yql--mtls-default-production-gq1.finance-k8s.svc.yahoo.local:4080/* + x-envoy-upstream-service-time: + - '1' + x-frame-options: + - SAMEORIGIN + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate, br + Connection: + - keep-alive + Cookie: + - MOCK_COOKIE + method: GET + uri: https://query2.finance.yahoo.com/ws/fundamentals-timeseries/v1/finance/timeseries/AAPL?crumb=MOCK_CRUMB&period1=MOCK_PERIOD_1&period2=MOCK_PERIOD_2&symbol=AAPL&type=annualForeignSales%2CannualDomesticSales%2CannualAdjustedGeographySegmentData%2CannualFreeCashFlow%2CannualRepurchaseOfCapitalStock%2CannualRepaymentOfDebt%2CannualIssuanceOfDebt%2CannualIssuanceOfCapitalStock%2CannualCapitalExpenditure%2CannualInterestPaidSupplementalData%2CannualIncomeTaxPaidSupplementalData%2CannualEndCashPosition%2CannualOtherCashAdjustmentOutsideChangeinCash%2CannualBeginningCashPosition%2CannualEffectOfExchangeRateChanges%2CannualChangesInCash%2CannualOtherCashAdjustmentInsideChangeinCash%2CannualCashFlowFromDiscontinuedOperation%2CannualFinancingCashFlow%2CannualCashFromDiscontinuedFinancingActivities%2CannualCashFlowFromContinuingFinancingActivities%2CannualNetOtherFinancingCharges%2CannualInterestPaidCFF%2CannualProceedsFromStockOptionExercised%2CannualCashDividendsPaid%2CannualPreferredStockDividendPaid%2CannualCommonStockDividendPaid%2CannualNetPreferredStockIssuance%2CannualPreferredStockPayments%2CannualPreferredStockIssuance%2CannualNetCommonStockIssuance%2CannualCommonStockPayments%2CannualCommonStockIssuance%2CannualNetIssuancePaymentsOfDebt%2CannualNetShortTermDebtIssuance%2CannualShortTermDebtPayments%2CannualShortTermDebtIssuance%2CannualNetLongTermDebtIssuance%2CannualLongTermDebtPayments%2CannualLongTermDebtIssuance%2CannualInvestingCashFlow%2CannualCashFromDiscontinuedInvestingActivities%2CannualCashFlowFromContinuingInvestingActivities%2CannualNetOtherInvestingChanges%2CannualInterestReceivedCFI%2CannualDividendsReceivedCFI%2CannualNetInvestmentPurchaseAndSale%2CannualSaleOfInvestment%2CannualPurchaseOfInvestment%2CannualNetInvestmentPropertiesPurchaseAndSale%2CannualSaleOfInvestmentProperties%2CannualPurchaseOfInvestmentProperties%2CannualNetBusinessPurchaseAndSale%2CannualSaleOfBusiness%2CannualPurchaseOfBusiness%2CannualNetIntangiblesPurchaseAndSale%2CannualSaleOfIntangibles%2CannualPurchaseOfIntangibles%2CannualNetPPEPurchaseAndSale%2CannualSaleOfPPE%2CannualPurchaseOfPPE%2CannualCapitalExpenditureReported%2CannualOperatingCashFlow%2CannualCashFromDiscontinuedOperatingActivities%2CannualCashFlowFromContinuingOperatingActivities%2CannualTaxesRefundPaid%2CannualInterestReceivedCFO%2CannualInterestPaidCFO%2CannualDividendReceivedCFO%2CannualDividendPaidCFO%2CannualChangeInWorkingCapital%2CannualChangeInOtherWorkingCapital%2CannualChangeInOtherCurrentLiabilities%2CannualChangeInOtherCurrentAssets%2CannualChangeInPayablesAndAccruedExpense%2CannualChangeInAccruedExpense%2CannualChangeInInterestPayable%2CannualChangeInPayable%2CannualChangeInDividendPayable%2CannualChangeInAccountPayable%2CannualChangeInTaxPayable%2CannualChangeInIncomeTaxPayable%2CannualChangeInPrepaidAssets%2CannualChangeInInventory%2CannualChangeInReceivables%2CannualChangesInAccountReceivables%2CannualOtherNonCashItems%2CannualExcessTaxBenefitFromStockBasedCompensation%2CannualStockBasedCompensation%2CannualUnrealizedGainLossOnInvestmentSecurities%2CannualProvisionandWriteOffofAssets%2CannualAssetImpairmentCharge%2CannualAmortizationOfSecurities%2CannualDeferredTax%2CannualDeferredIncomeTax%2CannualDepreciationAmortizationDepletion%2CannualDepletion%2CannualDepreciationAndAmortization%2CannualAmortizationCashFlow%2CannualAmortizationOfIntangibles%2CannualDepreciation%2CannualOperatingGainsLosses%2CannualPensionAndEmployeeBenefitExpense%2CannualEarningsLossesFromEquityInvestments%2CannualGainLossOnInvestmentSecurities%2CannualNetForeignCurrencyExchangeGainLoss%2CannualGainLossOnSaleOfPPE%2CannualGainLossOnSaleOfBusiness%2CannualNetIncomeFromContinuingOperations%2CannualCashFlowsfromusedinOperatingActivitiesDirect%2CannualTaxesRefundPaidDirect%2CannualInterestReceivedDirect%2CannualInterestPaidDirect%2CannualDividendsReceivedDirect%2CannualDividendsPaidDirect%2CannualClassesofCashPayments%2CannualOtherCashPaymentsfromOperatingActivities%2CannualPaymentsonBehalfofEmployees%2CannualPaymentstoSuppliersforGoodsandServices%2CannualClassesofCashReceiptsfromOperatingActivities%2CannualOtherCashReceiptsfromOperatingActivities%2CannualReceiptsfromGovernmentGrants%2CannualReceiptsfromCustomers response: body: string: !!binary | - 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 + 0rqZvK7Wi8WPH/8DhPP2VCedAAA= headers: Age: - '0' @@ -114,7 +259,7 @@ interactions: content-type: - application/json;charset=utf-8 date: - - Mon, 27 Nov 2023 23:48:22 GMT + - Sun, 10 Dec 2023 06:05:24 GMT server: - ATS vary: @@ -122,7 +267,7 @@ interactions: x-envoy-decorator-operation: - finance-company-fundamentals-api--mtls-production-gq1.finance-k8s.svc.yahoo.local:4080/* x-envoy-upstream-service-time: - - '68' + - '43' status: code: 200 message: OK