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 all 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
Original file line number Diff line number Diff line change
Expand Up @@ -1985,6 +1985,14 @@ def test_equity_fundamental_reported_financials(params, headers):
"provider": "sec",
}
),
(
{
"symbol": "NVDA",
"date": None,
"limit": 10,
"provider": "fmp",
}
),
],
)
@pytest.mark.integration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1884,6 +1884,14 @@ def test_equity_fundamental_reported_financials(params, obb):
"provider": "sec",
}
),
(
{
"symbol": "NVDA",
"date": None,
"limit": 10,
"provider": "fmp",
}
),
],
)
@pytest.mark.integration
Expand Down
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_13FHR import FMPForm13FHRFetcher
from openbb_fmp.models.forward_ebitda_estimates import FMPForwardEbitdaEstimatesFetcher
from openbb_fmp.models.forward_eps_estimates import FMPForwardEpsEstimatesFetcher
from openbb_fmp.models.government_trades import FMPGovernmentTradesFetcher
Expand Down Expand Up @@ -138,6 +139,7 @@
"WorldNews": FMPWorldNewsFetcher,
"EtfHistorical": FMPEquityHistoricalFetcher,
"YieldCurve": FMPYieldCurveFetcher,
"Form13FHR": FMPForm13FHRFetcher,
"GovernmentTrades": FMPGovernmentTradesFetcher,
},
repr_name="Financial Modeling Prep (FMP)",
Expand Down
142 changes: 142 additions & 0 deletions openbb_platform/providers/fmp/openbb_fmp/models/form_13FHR.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
"""Form 13f Model."""

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

from openbb_core.app.model.abstract.error import OpenBBError
from openbb_fmp.models.equity_profile import FMPEquityProfileFetcher
from pydantic import Field

from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.form_13FHR import (
Form13FHRData,
Form13FHRQueryParams,
)
from openbb_core.provider.utils.descriptions import DATA_DESCRIPTIONS
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, response_callback
from openbb_fmp.utils.parse_13f import date_to_quarter_end


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",
"symbol": "tickercusip",
"final_link": "finalLink",
}
symbol: Optional[str] = Field(
default=None, description=DATA_DESCRIPTIONS.get("symbol", "")
)
filling_date: Optional[dateType] = Field(
default=None, description="Date when the filing was submitted to the SEC."
)
accepted_date: Optional[dateType] = Field(
default=None, description="Date when the filing was accepted by the SEC."
)
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 Form 13f endpoint."""
api_key = credentials.get("fmp_api_key") if credentials else ""
if query.symbol.isnumeric():
cik = query.symbol
else:
try:
profile = await FMPEquityProfileFetcher.fetch_data({"symbol": query.symbol}, {"fmp_api_key": api_key})
cik = getattr(profile[0], "cik", "")
if not cik:
raise OpenBBError(f"Invalid symbol -> {query.symbol}")
except OpenBBError as e:
raise OpenBBError(f"Invalid symbol -> {query.symbol} -> {e}")
date_url = create_url(
3,
f"form-thirteen-date/{cik}",
api_key,
query,
exclude=["symbol", "limit"],
)
dates = await amake_request(date_url, response_callback=response_callback, **kwargs)
if query.date:
date = date_to_quarter_end(str(query.date))
if date not in dates:
raise EmptyDataError(f"Data for Date {date} not found for cik {cik},please change the date")
dates = [date]
if not dates:
raise EmptyDataError("No data returned for the given symbol.")
results: List[Dict] = []

async def get_one(date):
"""Get data for the given date."""
date = datetime.strptime(date, "%Y-%m-%d").date()
query.date = date
url = create_url(
3,
f"form-thirteen/{cik}",
api_key,
query,
exclude=["symbol", "limit"],
)
result = await amake_request(url, response_callback=response_callback, **kwargs)
if not result or len(result) == 0:
warn(f"Symbol Error: No data found for symbol {query.symbol}")
if result:
results.extend(result)

await asyncio.gather(*[get_one(date) for date in dates])
joshuaBri marked this conversation as resolved.
Show resolved Hide resolved

if not results:
raise EmptyDataError("No data returned for the given symbol.")
if query.limit:
return results[:query.limit]
return results

@staticmethod
def transform_data(
query: FMPForm13FHRQueryParams, data: List[Dict], **kwargs: Any
) -> List[FMPForm13FHRData]:
"""Return the transformed data."""
if query.symbol.isnumeric():
return [FMPForm13FHRData(**{k: v for k, v in d.items() if k != "cik"}) for d in data]
return [FMPForm13FHRData(**d) for d in data]
14 changes: 14 additions & 0 deletions openbb_platform/providers/fmp/openbb_fmp/utils/parse_13f.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Utility functions for parsing FMP Form 13F-HR."""


def date_to_quarter_end(date: str) -> str:
"""Convert a date to the end of the calendar quarter."""
# pylint: disable=import-outside-toplevel
from pandas import to_datetime
from pandas.tseries.offsets import QuarterEnd

return (
(to_datetime(date).to_period("Q").to_timestamp("D") + QuarterEnd())
.date()
.strftime("%Y-%m-%d")
)
15 changes: 15 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_13FHR 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 @@ -765,6 +766,20 @@ def test_fmp_historical_market_cap_fetcher(credentials=test_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": "brk-a",
"date": date(2024, 9, 30),
"limit": 1,
}
fetcher = FMPForm13FHRFetcher()
result = fetcher.test(params, credentials)
assert result is None


@pytest.mark.record_http
def test_fmp_government_trades_fetcher(credentials=test_credentials):
"""Test FMP government trades fetcher.
Expand Down
Loading