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] Add the 13f data directly from the FMP #6956

Open
wants to merge 25 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7a545ec
[Feature] Add Form13f Data
joshuaBri Nov 20, 2024
1769dd3
Merge remote-tracking branch 'origin/develop' into feature/13f
joshuaBri Nov 22, 2024
4ca868e
[Enhancement] Standardize the endpoint form_13f from FMP
joshuaBri Nov 25, 2024
5975494
Merge branch 'develop' into feature/13f
deeleeramone Nov 26, 2024
82e7c32
[Feature] Use FMP endpoints for FMP data
joshuaBri Nov 27, 2024
3175e28
Merge branch 'develop' into feature/13f
joshuaBri Dec 2, 2024
0f21e07
Merge branch 'develop' into feature/13f
deeleeramone Dec 5, 2024
3d8d366
Merge branch 'develop' into feature/13f
joshuaBri Dec 6, 2024
1484a18
Merge remote-tracking branch 'origin/develop' into feature/13f
joshuaBri Dec 9, 2024
c40ec7e
[Enhancement] Fix branch 13f,use FMPEquityProfileFetcher to get cik
joshuaBri Dec 9, 2024
6a6a620
Merge remote-tracking branch 'origin/feature/13f' into feature/13f
joshuaBri Dec 9, 2024
56171f1
Merge branch 'develop' into feature/13f
deeleeramone Dec 13, 2024
3169067
[Enhancement] Fix branch 13f
joshuaBri Dec 16, 2024
3a4d203
[Enhancement] Fix branch 13f
joshuaBri Dec 16, 2024
ade080d
Update openbb_platform/providers/fmp/openbb_fmp/models/form_13FHR.py
joshuaBri Dec 17, 2024
bac8206
Update openbb_platform/providers/fmp/openbb_fmp/models/form_13FHR.py
joshuaBri Dec 17, 2024
899777d
[Enhancement] Fix branch 13f
joshuaBri Dec 17, 2024
534a6c4
Merge branch 'develop' into feature/13f
joshuaBri Dec 26, 2024
14f213b
Merge branch 'develop' into feature/13f
deeleeramone Dec 31, 2024
ba5c270
[BugFix]Parameter date Functions
joshuaBri Jan 9, 2025
e5b6b3a
Merge remote-tracking branch 'origin/feature/13f' into feature/13f
joshuaBri Jan 9, 2025
18b3632
Merge branch 'develop' into feature/13f
joshuaBri Jan 9, 2025
2b47779
[BugFix] remove annotation
joshuaBri Jan 9, 2025
9b4899f
Merge branch 'develop' into feature/13f
deeleeramone Jan 13, 2025
0ed8c83
Merge branch 'develop' into feature/13f
deeleeramone Jan 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions openbb_platform/providers/fmp/openbb_fmp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from openbb_fmp.models.etf_sectors import FMPEtfSectorsFetcher
from openbb_fmp.models.executive_compensation import FMPExecutiveCompensationFetcher
from openbb_fmp.models.financial_ratios import FMPFinancialRatiosFetcher
from openbb_fmp.models.form_13f import FMPForm13FHRFetcher
from openbb_fmp.models.forward_ebitda_estimates import FMPForwardEbitdaEstimatesFetcher
from openbb_fmp.models.forward_eps_estimates import FMPForwardEpsEstimatesFetcher
from openbb_fmp.models.historical_dividends import FMPHistoricalDividendsFetcher
Expand Down Expand Up @@ -137,6 +138,7 @@
"WorldNews": FMPWorldNewsFetcher,
"EtfHistorical": FMPEquityHistoricalFetcher,
"YieldCurve": FMPYieldCurveFetcher,
"Form13FHR": FMPForm13FHRFetcher,
},
repr_name="Financial Modeling Prep (FMP)",
deprecated_credentials={"API_KEY_FINANCIALMODELINGPREP": "fmp_api_key"},
Expand Down
109 changes: 109 additions & 0 deletions openbb_platform/providers/fmp/openbb_fmp/models/form_13f.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""Form 13f Model."""

import asyncio
from datetime import date as dateType
from typing import Any, Dict, List, Optional
from warnings import warn

from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.form_13FHR import (
Form13FHRData,
Form13FHRQueryParams,
)
from openbb_core.provider.utils.errors import EmptyDataError
from openbb_core.provider.utils.helpers import amake_request
from openbb_fmp.utils.helpers import create_url
from pydantic import Field


class FMPForm13FHRQueryParams(Form13FHRQueryParams):
"""Form 13f Query Parameters.

Source: https://financialmodelingprep.com/api/v3/form-thirteen/0001388838?date=2021-09-30
"""


class FMPForm13FHRData(Form13FHRData):
"""Form13 FHR Data Model."""

__alias_dict__ = {
"period_ending": "date",
"issuer": "nameOfIssuer",
"principal_amount": "shares",
"asset_class": "titleOfClass",
"filling_date": "fillingDate",
"accepted_date": "acceptedDate",
"ticker_cusip": "tickercusip",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"ticker_cusip" -> "symbol"

"final_link": "finalLink",
}
filling_date: dateType = Field(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where fields have default=None, they need to be annotated as, Optional[type]

default=None, description="Date when the filing was submitted to the SEC."
)
accepted_date: dateType = Field(
default=None, description="Date when the filing was accepted by the SEC."
)
ticker_cusip: Optional[str] = Field(
default=None, description="Ticker symbol associated with the CUSIP."
)
link: Optional[str] = Field(
default=None, description="URL link to the SEC filing on the SEC website."
)
final_link: Optional[str] = Field(
default=None,
description="URL link to the XML information table of the SEC filing.",
)


class FMPForm13FHRFetcher(
Fetcher[
FMPForm13FHRQueryParams,
List[FMPForm13FHRData],
]
):
"""Fetches and transforms data from the Form 13f endpoints."""

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

@staticmethod
async def aextract_data(
query: FMPForm13FHRQueryParams,
credentials: Optional[Dict[str, str]] = None,
**kwargs: Any,
) -> List[Dict]:
"""Return the raw data from the House Disclosure endpoint."""
symbols = query.symbol.split(",")
results: List[Dict] = []

async def get_one(symbol):
"""Get data for the given symbol."""
api_key = credentials.get("fmp_api_key") if credentials else ""
url = create_url(
3,
f"form-thirteen/{symbol}",
api_key,
query,
exclude=["symbol", "limit"],
)
result = await amake_request(url, **kwargs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, we can handle API authorization errors if we pass a specific response_callback helper function to amake_request

from openbb_fmp.utils.helpers import response_callback
result = await amake_request(url, response_callback=response_callback, **kwargs)

Obviously, you wouldn't be likely to know this, but it will ensure that authorization error messages get properly communicated to the user.

if not result or len(result) == 0:
warn(f"Symbol Error: No data found for symbol {symbol}")
if result:
results.extend(result)

await asyncio.gather(*[get_one(symbol) for symbol in symbols])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As noted already, we are more interested in getting multiple filings from the same symbol, rather than the same date for multiple symbols. If we only allow 1 symbol, but multiple dates, we'll need to handle each date for the given symbol.


results = [i for i in results if isinstance(i, dict)]
if not results:
raise EmptyDataError("No data returned for the given symbol.")

return results

@staticmethod
def transform_data(
query: FMPForm13FHRQueryParams, data: List[Dict], **kwargs: Any
) -> List[FMPForm13FHRData]:
"""Return the transformed data."""
return [FMPForm13FHRData(**d) for d in data]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FMP is returning an additional field, "cik", which we do not want because it is the filer's CIK and having this value makes things both confusing and redundant. Please pop that value before returning the response.

14 changes: 14 additions & 0 deletions openbb_platform/providers/fmp/tests/test_fmp_fetchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import pytest
from openbb_core.app.service.user_service import UserService
from openbb_fmp.models.form_13f import FMPForm13FHRFetcher
from openbb_fmp.models.analyst_estimates import FMPAnalystEstimatesFetcher
from openbb_fmp.models.available_indices import FMPAvailableIndicesFetcher
from openbb_fmp.models.balance_sheet import FMPBalanceSheetFetcher
Expand Down Expand Up @@ -762,3 +763,16 @@ def test_fmp_historical_market_cap_fetcher(credentials=test_credentials):
fetcher = FmpHistoricalMarketCapFetcher()
result = fetcher.test(params, credentials)
assert result is None


@pytest.mark.record_http
def test_fmp_form_13f_fetcher(credentials=test_credentials):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In, openbb_platform/extensions/equity/integration, there are two test files for the integration tests, API and Python. A full set of parameters (can be None if the param is optional) with provider='fmp' needs to be added to the params of the endpoint test. Insert them below the "sec" provider params.

"""Test FMP form 13f fetcher."""
params = {
"symbol": "0001388838",
"date": date(2021, 9, 30),
"limit": 1,
}
fetcher = FMPForm13FHRFetcher()
result = fetcher.test(params, credentials)
assert result is None
Loading