Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/financials-notes: Financial Statements Notes Data #5862

Closed
wants to merge 13 commits into from
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""Financial Statements Notes Standard Model."""

from datetime import date as dateType
from typing import Optional

from pydantic import Field

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,
)


class FinancialStatementsNotesQueryParams(QueryParams):
"""Financial Statements Notes Query."""

tag: str = Field(
description="The data tag for the note."
+ " Use `statements_notes_tags()` to get a list of tags."
+ " For Intrinio, use the associated 'intrinio_id'."
)


class FinancialStatementsNotesData(Data):
"""Financial Statements Notes Data."""

content: str = Field(description="The contents of the note.")
period_ending: Optional[dateType] = Field(
default=None, description="The date of the period ending the report."
)
filing_date: Optional[dateType] = Field(
description="The date of the filing", default=None
)
cik: Optional[str] = Field(default=None, description=DATA_DESCRIPTIONS.get("cik"))
xbrl_tag: Optional[str] = Field(
default=None, description="The XBRL tag for the note."
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Financial Attributes Standard Model."""
"""Financial Statements Notes Tags Standard Model."""

from datetime import date as dateType
from typing import Literal, Optional
Expand All @@ -13,33 +13,29 @@
)


class FinancialAttributesQueryParams(QueryParams):
"""Financial Attributes Query."""
class FinancialStatementsNotesTagsQueryParams(QueryParams):
"""Financial Statements Notes Tags Query."""

symbol: str = Field(description=QUERY_DESCRIPTIONS.get("symbol"))
tag: str = Field(description=QUERY_DESCRIPTIONS.get("tag"))
period: Optional[Literal["annual", "quarter"]] = Field(
default="annual", description=QUERY_DESCRIPTIONS.get("period")
)
limit: Optional[int] = Field(
default=1000, description=QUERY_DESCRIPTIONS.get("limit")
)
type: Optional[str] = Field(
default=None, description="Filter by type, when applicable."
)
start_date: Optional[dateType] = Field(
default=None, description=QUERY_DESCRIPTIONS.get("start_date")
)
end_date: Optional[dateType] = Field(
default=None, description=QUERY_DESCRIPTIONS.get("end_date")
)
sort: Optional[Literal["asc", "desc"]] = Field(
default="desc", description="Sort order."
)


class FinancialAttributesData(Data):
"""Financial Attributes Data."""
class FinancialStatementsNotesTagsData(Data):
"""Financial Statements Notes Tags Data."""

date: dateType = Field(description=DATA_DESCRIPTIONS.get("date"))
value: Optional[float] = Field(default=None, description="The value of the data.")
period_ending: Optional[dateType] = Field(
default=None, description="The date of the period ending the report."
)
filing_date: dateType = Field(description="The date of the filing")
cik: Optional[str] = Field(default=None, description=DATA_DESCRIPTIONS.get("cik"))
xbrl_tag: Optional[str] = Field(
default=None, description="The XBRL tag for the note."
)
65 changes: 65 additions & 0 deletions openbb_platform/extensions/equity/integration/test_equity_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1657,6 +1657,71 @@ def test_equity_fundamental_trailing_dividend_yield(params, headers):
assert result.status_code == 200


@pytest.mark.parametrize(
"params",
[
(
{
"provider": "intrinio",
"symbol": "AAPL",
"start_date": "2022-01-01",
"end_date": "2023-01-01",
"period": "quarter",
}
)
],
)
@pytest.mark.integration
def test_equity_fundamental_statements_notes_tags(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/statements_notes_tags?{query_str}"
result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200


@pytest.mark.parametrize(
"params",
[
(
{
"provider": "intrinio",
"tag": "placeholder",
"content_format": "text",
}
)
],
)
@pytest.mark.integration
def test_equity_fundamental_statements_notes(params, headers):
params = {p: v for p, v in params.items() if v}

tags_params = {
"provider": "intrinio",
"symbol": "AAPL",
"start_date": "2022-01-01",
"end_date": "2023-01-01",
"period": "quarter",
}

tags_query_str = get_querystring(tags_params, [])
tags_url = f"http://0.0.0.0:8000/api/v1/equity/fundamental/statements_notes_tags?{tags_query_str}"
tag = requests.get(tags_url, headers=headers, timeout=10).json()["results"][0][
"intrinio_id"
]
params["tag"] = tag
query_str = get_querystring(params, [])
url = (
tags_url
) = f"http://0.0.0.0:8000/api/v1/equity/fundamental/statements_notes?{query_str}"

result = requests.get(url, headers=headers, timeout=10)
assert isinstance(result, requests.Response)
assert result.status_code == 200


@parametrize(
"params",
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1558,6 +1558,66 @@ def test_equity_fundamental_trailing_dividend_yield(params, obb):
assert len(result.results) > 0


@pytest.mark.parametrize(
"params",
[
(
{
"provider": "intrinio",
"symbol": "AAPL",
"start_date": "2022-01-01",
"end_date": "2023-01-01",
"period": "quarter",
}
)
],
)
@pytest.mark.integration
def test_equity_fundamental_statements_notes_tags(params, obb):
params = {p: v for p, v in params.items() if v}

result = obb.equity.fundamental.statements_notes_tags(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.results) > 0


@pytest.mark.parametrize(
"params",
[
(
{
"provider": "intrinio",
"tag": "placeholder",
"content_format": "text",
}
)
],
)
@pytest.mark.integration
def test_equity_fundamental_statements_notes(params, obb):
params = {p: v for p, v in params.items() if v}

tags_params = {
"provider": "intrinio",
"symbol": "AAPL",
"start_date": "2022-01-01",
"end_date": "2023-01-01",
"period": "quarter",
}
tag = (
obb.equity.fundamental.statements_notes_tags(**tags_params)
.results[0]
.intrinio_id
)
params["tag"] = tag

result = obb.equity.fundamental.statements_notes(**params)
assert result
assert isinstance(result, OBBject)
assert len(result.model_dump()["results"]) > 0


@parametrize(
"params",
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,25 @@ async def trailing_dividend_yield(
) -> OBBject:
"""Trailing 1yr dividend yield."""
return await OBBject.from_query(Query(**locals()))


@router.command(model="FinancialStatementsNotesTags")
async def statements_notes_tags(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject[BaseModel]:
"""Get the XBRL tag names associated with a company's financial statements notes."""
return await OBBject.from_query(Query(**locals()))


@router.command(model="FinancialStatementsNotes")
async def statements_notes(
cc: CommandContext,
provider_choices: ProviderChoices,
standard_params: StandardParams,
extra_params: ExtraParams,
) -> OBBject[BaseModel]:
"""Get the accompanying notes for a specific tag from a company's financial statements."""
return await OBBject.from_query(Query(**locals()))
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
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_statements_notes import (
IntrinioFinancialStatementsNotesFetcher,
)
from openbb_intrinio.models.financial_statements_notes_tags import (
IntrinioFinancialStatementsNotesTagsFetcher,
)
from openbb_intrinio.models.financial_ratios import IntrinioFinancialRatiosFetcher
from openbb_intrinio.models.fred_series import IntrinioFredSeriesFetcher
from openbb_intrinio.models.historical_attributes import (
Expand Down Expand Up @@ -54,6 +60,8 @@
"EquityInfo": IntrinioEquityInfoFetcher,
"EquityQuote": IntrinioEquityQuoteFetcher,
"EquitySearch": IntrinioEquitySearchFetcher,
"FinancialStatementsNotes": IntrinioFinancialStatementsNotesFetcher,
"FinancialStatementsNotesTags": IntrinioFinancialStatementsNotesTagsFetcher,
"FinancialRatios": IntrinioFinancialRatiosFetcher,
"FredSeries": IntrinioFredSeriesFetcher,
"HistoricalAttributes": IntrinioHistoricalAttributesFetcher,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""Intrinio Financial Statements Notes Model."""

from typing import Any, Dict, Literal, Optional

from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.financial_statements_notes import (
FinancialStatementsNotesData,
FinancialStatementsNotesQueryParams,
)
from openbb_intrinio.utils.helpers import get_data_one
from pydantic import Field


class IntrinioFinancialStatementsNotesQueryParams(FinancialStatementsNotesQueryParams):
"""
Intrinio Financial Statements Notes Query.

Source: https://docs.intrinio.com/documentation/web_api/get_note_v2
"""

content_format: Literal["text", "html"] = Field(
default="text", description="Format of the content, either text or html."
)


class IntrinioFinancialStatementsNotesData(FinancialStatementsNotesData):
"""Intrinio Financial Statements Notes Data."""

report_type: Optional[str] = Field(
default=None, description="The type of report the note is from."
)
intrinio_id: Optional[str] = Field(
default=None, description="The Intrinio ID for the note."
)


class IntrinioFinancialStatementsNotesFetcher(
Fetcher[
IntrinioFinancialStatementsNotesQueryParams,
IntrinioFinancialStatementsNotesData,
]
):
"""Transform the query, extract and transform the data from the Intrinio endpoints."""

@staticmethod
def transform_query(
params: Dict[str, Any]
) -> IntrinioFinancialStatementsNotesQueryParams:
"""Transform the query params."""
return IntrinioFinancialStatementsNotesQueryParams(**params)

@staticmethod
async def aextract_data(
query: IntrinioFinancialStatementsNotesQueryParams,
credentials: Optional[Dict[str, str]],
**kwargs: Any,
) -> Dict:
"""Return the raw data from the Intrinio endpoint."""
api_key = credentials.get("intrinio_api_key") if credentials else ""
data: Dict = {}

url = f"https://api-v2.intrinio.com/filings/notes/{query.tag}?content_format={query.content_format}&api_key={api_key}"

data = await get_data_one(url)

return data

@staticmethod
def transform_data(
query: IntrinioFinancialStatementsNotesQueryParams,
data: Dict,
**kwargs: Any,
) -> IntrinioFinancialStatementsNotesData:
"""Return the transformed data."""
results = {
"cik": data["filing"].get("cik", None),
"filing_date": data["filing"].get("filing_date", None),
"period_ending": data["filing"].get("period_end_date", None),
"report_type": data["filing"].get("report_type", None),
"xbrl_tag": data.get("xbrl_tag", None),
"intrinio_id": data.get("id", None),
"content": data.get("content", None),
}
return IntrinioFinancialStatementsNotesData.model_validate(results)
Loading
Loading