-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
base: develop
Are you sure you want to change the base?
Changes from 2 commits
7a545ec
1769dd3
4ca868e
5975494
82e7c32
3175e28
0f21e07
3d8d366
1484a18
c40ec7e
6a6a620
56171f1
3169067
3a4d203
ade080d
bac8206
899777d
534a6c4
14f213b
ba5c270
e5b6b3a
18b3632
2b47779
9b4899f
0ed8c83
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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", | ||
"final_link": "finalLink", | ||
} | ||
filling_date: dateType = Field( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where fields have |
||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here, we can handle API authorization errors if we pass a specific
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]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
|
@@ -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): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In, |
||
"""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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"ticker_cusip" -> "symbol"