financial ratios

This commit is contained in:
tehcoderer
2023-08-08 18:08:17 -04:00
parent 4b364f438e
commit f07e34e108
9 changed files with 276 additions and 43 deletions

View File

@@ -328,18 +328,23 @@ def pta(
return CommandOutput(results=Query(**locals()).execute())
@router.command(model="FinancialRatios")
def ratios(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> CommandOutput[BaseModel]:
"""Extensive set of ratios over time."""
return CommandOutput(results=Query(**locals()).execute())
@router.command
def rating() -> CommandOutput[Empty]: # type: ignore
"""Analyst prices and ratings over time of the company."""
return CommandOutput(results=Empty())
@router.command
def ratios() -> CommandOutput[Empty]: # type: ignore
"""Extensive set of ratios over time."""
return CommandOutput(results=Empty())
@router.command
def revfc() -> CommandOutput[Empty]: # type: ignore
"""Earning Estimate by Analysts - Revenue."""

View File

@@ -16,6 +16,7 @@ from openbb_fmp.models.esg_risk_rating import FMPESGRiskRatingFetcher
from openbb_fmp.models.esg_score import FMPESGScoreFetcher
from openbb_fmp.models.esg_sector import FMPESGSectorFetcher
from openbb_fmp.models.executive_compensation import FMPExecutiveCompensationFetcher
from openbb_fmp.models.financial_ratios import FMPFinancialRatiosFetcher
from openbb_fmp.models.forex_eod import FMPForexEODFetcher
from openbb_fmp.models.forex_pairs import FMPForexPairsFetcher
from openbb_fmp.models.global_news import FMPGlobalNewsFetcher
@@ -101,5 +102,6 @@ fmp_provider = Provider(
"MajorIndicesConstituents": FMPMajorIndicesConstituentsFetcher,
"DividendCalendar": FMPDividendCalendarFetcher,
"StockQuote": FMPStockQuoteFetcher,
"FinancialRatios": FMPFinancialRatiosFetcher,
},
)

View File

@@ -0,0 +1,118 @@
"""FMP Income Statement Fetcher."""
from typing import Any, Dict, List, Literal, Optional
from openbb_provider.abstract.fetcher import Fetcher
from openbb_provider.standard_models.base import FinancialStatementQueryParams
from openbb_provider.standard_models.financial_ratios import FinancialRatiosData
from openbb_fmp.utils.helpers import get_data_many
PeriodType = Literal["annual", "quarter"]
class FMPFinancialRatiosQueryParams(FinancialStatementQueryParams):
"""FMP Financial Ratios QueryParams.
Source: https://financialmodelingprep.com/developer/docs/#Company-Financial-Ratios
Symbol must be provided.
"""
class FMPFinancialRatiosData(FinancialRatiosData):
"""FMP Financial Ratios Data."""
class Config:
fields = {
"current_ratio": "currentRatio",
"quick_ratio": "quickRatio",
"cash_ratio": "cashRatio",
"days_of_sales_outstanding": "daysOfSalesOutstanding",
"days_of_inventory_outstanding": "daysOfInventoryOutstanding",
"operating_cycle": "operatingCycle",
"days_of_payables_outstanding": "daysOfPayablesOutstanding",
"cash_conversion_cycle": "cashConversionCycle",
"gross_profit_margin": "grossProfitMargin",
"operating_profit_margin": "operatingProfitMargin",
"pretax_profit_margin": "pretaxProfitMargin",
"net_profit_margin": "netProfitMargin",
"effective_tax_rate": "effectiveTaxRate",
"return_on_assets": "returnOnAssets",
"return_on_equity": "returnOnEquity",
"return_on_capital_employed": "returnOnCapitalEmployed",
"net_income_per_ebt": "netIncomePerEBT",
"ebt_per_ebit": "ebtPerEbit",
"ebit_per_revenue": "ebitPerRevenue",
"debt_ratio": "debtRatio",
"debt_equity_ratio": "debtEquityRatio",
"long_term_debt_to_capitalization": "longTermDebtToCapitalization",
"total_debt_to_capitalization": "totalDebtToCapitalization",
"interest_coverage": "interestCoverage",
"cash_flow_to_debt_ratio": "cashFlowToDebtRatio",
"company_equity_multiplier": "companyEquityMultiplier",
"receivables_turnover": "receivablesTurnover",
"payables_turnover": "payablesTurnover",
"inventory_turnover": "inventoryTurnover",
"fixed_asset_turnover": "fixedAssetTurnover",
"asset_turnover": "assetTurnover",
"operating_cash_flow_per_share": "operatingCashFlowPerShare",
"free_cash_flow_per_share": "freeCashFlowPerShare",
"cash_per_share": "cashPerShare",
"payout_ratio": "payoutRatio",
"operating_cash_flow_sales_ratio": "operatingCashFlowSalesRatio",
"free_cash_flow_operating_cash_flow_ratio": "freeCashFlowOperatingCashFlowRatio",
"cash_flow_coverage_ratios": "cashFlowCoverageRatios",
"short_term_coverage_ratios": "shortTermCoverageRatios",
"capital_expenditure_coverage_ratio": "capitalExpenditureCoverageRatio",
"dividend_paid_and_capex_coverage_ratio": "dividendPaidAndCapexCoverageRatio",
"dividend_payout_ratio": "dividendPayoutRatio",
"price_book_value_ratio": "priceBookValueRatio",
"price_to_book_ratio": "priceToBookRatio",
"price_to_sales_ratio": "priceToSalesRatio",
"price_earnings_ratio": "priceEarningsRatio",
"price_to_free_cash_flows_ratio": "priceToFreeCashFlowsRatio",
"price_to_operating_cash_flows_ratio": "priceToOperatingCashFlowsRatio",
"price_cash_flow_ratio": "priceCashFlowRatio",
"price_earnings_to_growth_ratio": "priceEarningsToGrowthRatio",
"price_sales_ratio": "priceSalesRatio",
"dividend_yield": "dividendYield",
"enterprise_value_multiple": "enterpriseValueMultiple",
"price_fair_value": "priceFairValue",
}
class FMPFinancialRatiosFetcher(
Fetcher[
FMPFinancialRatiosQueryParams,
List[FMPFinancialRatiosData],
]
):
@staticmethod
def transform_query(params: Dict[str, Any]) -> FMPFinancialRatiosQueryParams:
return FMPFinancialRatiosQueryParams(**params)
@staticmethod
def extract_data(
query: FMPFinancialRatiosQueryParams,
credentials: Optional[Dict[str, str]],
**kwargs: Any,
) -> List[FMPFinancialRatiosData]:
api_key = credentials.get("fmp_api_key") if credentials else ""
query.period = "annual" if query.period == "annually" else "quarter"
base_url = "https://financialmodelingprep.com/api/v3"
url = (
f"{base_url}/ratios/{query.symbol}?"
f"period={query.period}&limit={query.limit}&apikey={api_key}"
)
return get_data_many(url, FMPFinancialRatiosData, **kwargs)
@staticmethod
def transform_data(
data: List[FMPFinancialRatiosData],
) -> List[FinancialRatiosData]:
return [FinancialRatiosData.parse_obj(d.dict()) for d in data]

View File

@@ -1,6 +1,5 @@
"""FMP Historical Dividends fetcher."""
from datetime import datetime
from typing import Any, Dict, List, Optional
from openbb_provider.abstract.fetcher import Fetcher
@@ -8,7 +7,6 @@ from openbb_provider.standard_models.historical_dividends import (
HistoricalDividendsData,
HistoricalDividendsQueryParams,
)
from pydantic import validator
from openbb_fmp.utils.helpers import create_url, get_data_many
@@ -31,18 +29,6 @@ class FMPHistoricalDividendsData(HistoricalDividendsData):
"declaration_date": "declarationDate",
}
@validator("declarationDate", pre=True, check_fields=False)
def declaration_date_validate(cls, v: str): # pylint: disable=E0213
return datetime.strptime(v, "%Y-%m-%d") if v else None
@validator("recordDate", pre=True, check_fields=False)
def record_date_validate(cls, v: str): # pylint: disable=E0213
return datetime.strptime(v, "%Y-%m-%d") if v else None
@validator("paymentDate", pre=True, check_fields=False)
def payment_date_validate(cls, v: str): # pylint: disable=E0213
return datetime.strptime(v, "%Y-%m-%d") if v else None
class FMPHistoricalDividendsFetcher(
Fetcher[
@@ -70,5 +56,5 @@ class FMPHistoricalDividendsFetcher(
@staticmethod
def transform_data(
data: List[FMPHistoricalDividendsData],
) -> List[FMPHistoricalDividendsData]:
return data
) -> List[HistoricalDividendsData]:
return [HistoricalDividendsData.parse_obj(d.dict()) for d in data]

View File

@@ -1,7 +1,6 @@
"""FMP Historical Employees fetcher."""
from datetime import datetime
from typing import Any, Dict, List, Optional
from openbb_provider.abstract.fetcher import Fetcher
@@ -9,7 +8,6 @@ from openbb_provider.standard_models.historical_employees import (
HistoricalEmployeesData,
HistoricalEmployeesQueryParams,
)
from pydantic import validator
from openbb_fmp.utils.helpers import create_url, get_data_many
@@ -34,18 +32,6 @@ class FMPHistoricalEmployeesData(HistoricalEmployeesData):
"employee_count": "employeeCount",
}
@validator("acceptanceTime", pre=True, check_fields=False)
def acceptance_time_validate(cls, v): # pylint: disable=E0213
return datetime.strptime(v, "%Y-%m-%d %H:%M:%S")
@validator("periodOfReport", pre=True, check_fields=False)
def period_of_report_validate(cls, v): # pylint: disable=E0213
return datetime.strptime(v, "%Y-%m-%d")
@validator("filingDate", pre=True, check_fields=False)
def filing_date_validate(cls, v): # pylint: disable=E0213
return datetime.strptime(v, "%Y-%m-%d")
class FMPHistoricalEmployeesFetcher(
Fetcher[

View File

@@ -50,5 +50,5 @@ class FMPStockPeersFetcher(
return get_data_one(url, FMPStockPeersData, **kwargs)
@staticmethod
def transform_data(data: FMPStockPeersData) -> FMPStockPeersData:
return data
def transform_data(data: FMPStockPeersData) -> StockPeersData:
return StockPeersData.parse_obj(data.dict())

View File

@@ -0,0 +1,112 @@
"""Financial ratios data model."""
from typing import Optional
from pydantic import Field
from openbb_provider.abstract.data import Data
class FinancialRatiosData(Data):
symbol: str = Field(description="The symbol of the company.")
date: str = Field(description="The date of the financial ratios.")
period: str = Field(description="The period of the financial ratios.")
current_ratio: Optional[float] = Field(description="The current ratio.")
quick_ratio: Optional[float] = Field(description="The quick ratio.")
cash_ratio: Optional[float] = Field(description="The cash ratio.")
days_of_sales_outstanding: Optional[float] = Field(
description="Days of sales outstanding."
)
days_of_inventory_outstanding: Optional[float] = Field(
description="Days of inventory outstanding."
)
operating_cycle: Optional[float] = Field(description="Operating cycle.")
days_of_payables_outstanding: Optional[float] = Field(
description="Days of payables outstanding."
)
cash_conversion_cycle: Optional[float] = Field(description="Cash conversion cycle.")
gross_profit_margin: Optional[float] = Field(description="Gross profit margin.")
operating_profit_margin: Optional[float] = Field(
description="Operating profit margin."
)
pretax_profit_margin: Optional[float] = Field(description="Pretax profit margin.")
net_profit_margin: Optional[float] = Field(description="Net profit margin.")
effective_tax_rate: Optional[float] = Field(description="Effective tax rate.")
return_on_assets: Optional[float] = Field(description="Return on assets.")
return_on_equity: Optional[float] = Field(description="Return on equity.")
return_on_capital_employed: Optional[float] = Field(
description="Return on capital employed."
)
net_income_per_ebt: Optional[float] = Field(description="Net income per EBT.")
ebt_per_ebit: Optional[float] = Field(description="EBT per EBIT.")
ebit_per_revenue: Optional[float] = Field(description="EBIT per revenue.")
debt_ratio: Optional[float] = Field(description="Debt ratio.")
debt_equity_ratio: Optional[float] = Field(description="Debt equity ratio.")
long_term_debt_to_capitalization: Optional[float] = Field(
description="Long term debt to capitalization."
)
total_debt_to_capitalization: Optional[float] = Field(
description="Total debt to capitalization."
)
interest_coverage: Optional[float] = Field(description="Interest coverage.")
cash_flow_to_debt_ratio: Optional[float] = Field(
description="Cash flow to debt ratio."
)
company_equity_multiplier: Optional[float] = Field(
description="Company equity multiplier."
)
receivables_turnover: Optional[float] = Field(description="Receivables turnover.")
payables_turnover: Optional[float] = Field(description="Payables turnover.")
inventory_turnover: Optional[float] = Field(description="Inventory turnover.")
fixed_asset_turnover: Optional[float] = Field(description="Fixed asset turnover.")
asset_turnover: Optional[float] = Field(description="Asset turnover.")
operating_cash_flow_per_share: Optional[float] = Field(
description="Operating cash flow per share."
)
free_cash_flow_per_share: Optional[float] = Field(
description="Free cash flow per share."
)
cash_per_share: Optional[float] = Field(description="Cash per share.")
payout_ratio: Optional[float] = Field(description="Payout ratio.")
operating_cash_flow_sales_ratio: Optional[float] = Field(
description="Operating cash flow sales ratio."
)
free_cash_flow_operating_cash_flow_ratio: Optional[float] = Field(
description="Free cash flow operating cash flow ratio."
)
cash_flow_coverage_ratios: Optional[float] = Field(
description="Cash flow coverage ratios."
)
short_term_coverage_ratios: Optional[float] = Field(
description="Short term coverage ratios."
)
capital_expenditure_coverage_ratio: Optional[float] = Field(
description="Capital expenditure coverage ratio."
)
dividend_paid_and_capex_coverage_ratio: Optional[float] = Field(
description="Dividend paid and capex coverage ratio."
)
dividend_payout_ratio: Optional[float] = Field(description="Dividend payout ratio.")
price_book_value_ratio: Optional[float] = Field(
description="Price book value ratio."
)
price_to_book_ratio: Optional[float] = Field(description="Price to book ratio.")
price_to_sales_ratio: Optional[float] = Field(description="Price to sales ratio.")
price_earnings_ratio: Optional[float] = Field(description="Price earnings ratio.")
price_to_free_cash_flows_ratio: Optional[float] = Field(
description="Price to free cash flows ratio."
)
price_to_operating_cash_flows_ratio: Optional[float] = Field(
description="Price to operating cash flows ratio."
)
price_cash_flow_ratio: Optional[float] = Field(description="Price cash flow ratio.")
price_earnings_to_growth_ratio: Optional[float] = Field(
description="Price earnings to growth ratio."
)
price_sales_ratio: Optional[float] = Field(description="Price sales ratio.")
dividend_yield: Optional[float] = Field(description="Dividend yield.")
enterprise_value_multiple: Optional[float] = Field(
description="Enterprise value multiple."
)
price_fair_value: Optional[float] = Field(description="Price fair value.")

View File

@@ -4,7 +4,7 @@
from datetime import date as dateType
from typing import Optional
from pydantic import Field
from pydantic import Field, validator
from openbb_provider.abstract.data import Data
from openbb_provider.abstract.query_params import QueryParams
@@ -25,11 +25,23 @@ class HistoricalDividendsData(Data):
)
dividend: float = Field(description="The dividend of the historical dividends.")
record_date: Optional[dateType] = Field(
description="The record date of the historical dividends."
description="The record date of the historical dividends.", default=None
)
payment_date: Optional[dateType] = Field(
description="The payment date of the historical dividends."
description="The payment date of the historical dividends.", default=None
)
declaration_date: Optional[dateType] = Field(
description="The declaration date of the historical dividends."
description="The declaration date of the historical dividends.", default=None
)
@validator("declaration_date", pre=True, check_fields=False)
def declaration_date_validate(cls, v: str): # pylint: disable=E0213
return dateType.fromisoformat(v) if v else None
@validator("record_date", pre=True, check_fields=False)
def record_date_validate(cls, v: str): # pylint: disable=E0213
return dateType.fromisoformat(v) if v else None
@validator("payment_date", pre=True, check_fields=False)
def payment_date_validate(cls, v: str): # pylint: disable=E0213
return dateType.fromisoformat(v) if v else None

View File

@@ -3,7 +3,7 @@
from datetime import date, datetime
from pydantic import Field
from pydantic import Field, validator
from openbb_provider.abstract.data import Data
from openbb_provider.abstract.query_params import QueryParams
@@ -35,3 +35,15 @@ class HistoricalEmployeesData(Data, BaseSymbol):
source: str = Field(
description="The source URL which retrieves this data for the company."
)
@validator("acceptance_time", pre=True, check_fields=False)
def acceptance_time_validate(cls, v): # pylint: disable=E0213
return datetime.strptime(v, "%Y-%m-%d %H:%M:%S")
@validator("period_of_report", pre=True, check_fields=False)
def period_of_report_validate(cls, v): # pylint: disable=E0213
return datetime.strptime(v, "%Y-%m-%d")
@validator("filing_date", pre=True, check_fields=False)
def filing_date_validate(cls, v): # pylint: disable=E0213
return datetime.strptime(v, "%Y-%m-%d")