openbb-sec 1.2.2__tar.gz → 1.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/PKG-INFO +2 -2
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/company_filings.py +3 -2
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/etf_holdings.py +2 -2
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/schema_files.py +2 -1
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/symbol_map.py +2 -1
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/utils/frames.py +8 -7
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/utils/helpers.py +4 -3
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/utils/parse_13f.py +10 -9
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/pyproject.toml +2 -2
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/README.md +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/__init__.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/__init__.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/cik_map.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/compare_company_facts.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/equity_ftd.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/equity_search.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/form_13FHR.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/institutions_search.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/py.typed +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/rss_litigation.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/models/sic_search.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/py.typed +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/utils/__init__.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/utils/definitions.py +0 -0
- {openbb_sec-1.2.2 → openbb_sec-1.2.3}/openbb_sec/utils/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: openbb-sec
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.3
|
|
4
4
|
Summary: SEC extension for OpenBB
|
|
5
5
|
License: AGPL-3.0-only
|
|
6
6
|
Author: OpenBB Team
|
|
@@ -16,7 +16,7 @@ Requires-Dist: aiohttp-client-cache (>=0.11.0,<0.12.0)
|
|
|
16
16
|
Requires-Dist: aiosqlite (>=0.20.0,<0.21.0)
|
|
17
17
|
Requires-Dist: bs4 (>=0.0.2,<0.0.3)
|
|
18
18
|
Requires-Dist: lxml (>=5.2.1,<6.0.0)
|
|
19
|
-
Requires-Dist: openbb-core (>=1.2.
|
|
19
|
+
Requires-Dist: openbb-core (>=1.2.5,<2.0.0)
|
|
20
20
|
Requires-Dist: xmltodict (>=0.13.0,<0.14.0)
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
|
|
@@ -10,6 +10,7 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
10
10
|
|
|
11
11
|
from aiohttp_client_cache import SQLiteBackend
|
|
12
12
|
from aiohttp_client_cache.session import CachedSession
|
|
13
|
+
from openbb_core.app.model.abstract.error import OpenBBError
|
|
13
14
|
from openbb_core.app.utils import get_user_cache_directory
|
|
14
15
|
from openbb_core.provider.abstract.fetcher import Fetcher
|
|
15
16
|
from openbb_core.provider.standard_models.company_filings import (
|
|
@@ -158,9 +159,9 @@ class SecCompanyFilingsFetcher(
|
|
|
158
159
|
query.symbol.lower(), use_cache=query.use_cache
|
|
159
160
|
)
|
|
160
161
|
if not query.cik:
|
|
161
|
-
raise
|
|
162
|
+
raise OpenBBError(f"CIK not found for symbol {query.symbol}")
|
|
162
163
|
if query.cik is None:
|
|
163
|
-
raise
|
|
164
|
+
raise OpenBBError("CIK or symbol must be provided.")
|
|
164
165
|
|
|
165
166
|
# The leading 0s need to be inserted but are typically removed from the data to store as an integer.
|
|
166
167
|
if len(query.cik) != 10: # type: ignore
|
|
@@ -11,6 +11,7 @@ import pandas as pd
|
|
|
11
11
|
import xmltodict
|
|
12
12
|
from aiohttp_client_cache import SQLiteBackend
|
|
13
13
|
from aiohttp_client_cache.session import CachedSession
|
|
14
|
+
from openbb_core.app.model.abstract.error import OpenBBError
|
|
14
15
|
from openbb_core.app.utils import get_user_cache_directory
|
|
15
16
|
from openbb_core.provider.abstract.annotated_result import AnnotatedResult
|
|
16
17
|
from openbb_core.provider.abstract.fetcher import Fetcher
|
|
@@ -348,7 +349,7 @@ class SecEtfHoldingsFetcher(
|
|
|
348
349
|
raise e
|
|
349
350
|
filing_candidates = pd.DataFrame.from_records(filings)
|
|
350
351
|
if filing_candidates.empty:
|
|
351
|
-
raise
|
|
352
|
+
raise OpenBBError(f"No N-Port records found for {query.symbol}.")
|
|
352
353
|
dates = filing_candidates.period_ending.to_list()
|
|
353
354
|
new_date: str = ""
|
|
354
355
|
if query.date is not None:
|
|
@@ -397,7 +398,6 @@ class SecEtfHoldingsFetcher(
|
|
|
397
398
|
**kwargs: Any,
|
|
398
399
|
) -> AnnotatedResult[List[SecEtfHoldingsData]]:
|
|
399
400
|
"""Transform the data."""
|
|
400
|
-
|
|
401
401
|
if not data:
|
|
402
402
|
raise EmptyDataError(f"No data was returned for the symbol, {query.symbol}")
|
|
403
403
|
results = []
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import Any, Dict, List, Optional
|
|
4
4
|
|
|
5
|
+
from openbb_core.app.model.abstract.error import OpenBBError
|
|
5
6
|
from openbb_core.provider.abstract.data import Data
|
|
6
7
|
from openbb_core.provider.abstract.fetcher import Fetcher
|
|
7
8
|
from openbb_core.provider.standard_models.cot_search import CotSearchQueryParams
|
|
@@ -43,7 +44,7 @@ class SecSchemaFilesFetcher(Fetcher[SecSchemaFilesQueryParams, SecSchemaFilesDat
|
|
|
43
44
|
) -> Dict:
|
|
44
45
|
"""Return the raw data from the SEC endpoint."""
|
|
45
46
|
if query.url and ".xsd" in query.url or query.url and ".xml" in query.url:
|
|
46
|
-
raise
|
|
47
|
+
raise OpenBBError("Invalid URL. This endpoint does not parse the files.")
|
|
47
48
|
results = get_schema_filelist(query.query, query.url)
|
|
48
49
|
|
|
49
50
|
return {"files": results}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
from typing import Any, Dict, Optional
|
|
6
6
|
|
|
7
|
+
from openbb_core.app.model.abstract.error import OpenBBError
|
|
7
8
|
from openbb_core.provider.abstract.data import Data
|
|
8
9
|
from openbb_core.provider.abstract.fetcher import Fetcher
|
|
9
10
|
from openbb_core.provider.standard_models.symbol_map import SymbolMapQueryParams
|
|
@@ -46,7 +47,7 @@ class SecSymbolMapFetcher(
|
|
|
46
47
|
) -> Dict:
|
|
47
48
|
"""Return the raw data from the SEC endpoint."""
|
|
48
49
|
if not query.query.isdigit():
|
|
49
|
-
raise
|
|
50
|
+
raise OpenBBError("Query is required and must be a valid CIK.")
|
|
50
51
|
symbol = await cik_map(int(query.query), query.use_cache)
|
|
51
52
|
response = {"symbol": symbol}
|
|
52
53
|
return response
|
|
@@ -9,6 +9,7 @@ from warnings import warn
|
|
|
9
9
|
|
|
10
10
|
from aiohttp_client_cache import SQLiteBackend
|
|
11
11
|
from aiohttp_client_cache.session import CachedSession
|
|
12
|
+
from openbb_core.app.model.abstract.error import OpenBBError
|
|
12
13
|
from openbb_core.app.utils import get_user_cache_directory
|
|
13
14
|
from openbb_core.provider.utils.errors import EmptyDataError
|
|
14
15
|
from openbb_core.provider.utils.helpers import amake_request
|
|
@@ -180,7 +181,7 @@ FACTS = [
|
|
|
180
181
|
"LongTermDebt",
|
|
181
182
|
"LongTermDebtCurrent",
|
|
182
183
|
"LongTermDebtMaturitiesRepaymentsOfPrincipalAfterYearFive",
|
|
183
|
-
"LongTermDebtMaturitiesRepaymentsOfPrincipalInNextTwelveMonths",
|
|
184
|
+
"LongTermDebtMaturitiesRepaymentsOfPrincipalInNextTwelveMonths", # pragma: allowlist secret
|
|
184
185
|
"LongTermDebtMaturitiesRepaymentsOfPrincipalInYearFive",
|
|
185
186
|
"LongTermDebtMaturitiesRepaymentsOfPrincipalInYearFour",
|
|
186
187
|
"LongTermDebtMaturitiesRepaymentsOfPrincipalInYearThree",
|
|
@@ -736,7 +737,7 @@ async def get_frame( # pylint: disable =too-many-arguments,too-many-locals, too
|
|
|
736
737
|
try:
|
|
737
738
|
response = await fetch_data(url, use_cache, persist)
|
|
738
739
|
except Exception:
|
|
739
|
-
raise
|
|
740
|
+
raise OpenBBError(message) from e
|
|
740
741
|
elif "Q" in url and not url.endswith("I.json"):
|
|
741
742
|
warn(
|
|
742
743
|
"No frame was found for the requested quarter, trying instantaneous data."
|
|
@@ -745,9 +746,9 @@ async def get_frame( # pylint: disable =too-many-arguments,too-many-locals, too
|
|
|
745
746
|
try:
|
|
746
747
|
response = await fetch_data(url, use_cache, persist)
|
|
747
748
|
except Exception:
|
|
748
|
-
raise
|
|
749
|
+
raise OpenBBError(message) from e
|
|
749
750
|
else:
|
|
750
|
-
raise
|
|
751
|
+
raise OpenBBError(message) from e
|
|
751
752
|
|
|
752
753
|
data = sorted(response.get("data", {}), key=lambda x: x["val"], reverse=True) # type: ignore
|
|
753
754
|
metadata = {
|
|
@@ -779,9 +780,9 @@ async def get_concept(
|
|
|
779
780
|
taxonomy: Optional[TAXONOMIES] = "us-gaap",
|
|
780
781
|
use_cache: bool = True,
|
|
781
782
|
) -> Dict:
|
|
782
|
-
"""Return all the XBRL disclosures from a single company (CIK)
|
|
783
|
-
|
|
784
|
-
for each units
|
|
783
|
+
"""Return all the XBRL disclosures from a single company (CIK) Concept (a taxonomy and tag) into a single JSON file.
|
|
784
|
+
|
|
785
|
+
Each entry contains a separate array of facts for each units of measure that the company has chosen to disclose
|
|
785
786
|
(e.g. net profits reported in U.S. dollars and in Canadian dollars).
|
|
786
787
|
|
|
787
788
|
Parameters
|
|
@@ -9,6 +9,7 @@ from zipfile import ZipFile
|
|
|
9
9
|
import pandas as pd
|
|
10
10
|
from aiohttp_client_cache import SQLiteBackend
|
|
11
11
|
from aiohttp_client_cache.session import CachedSession
|
|
12
|
+
from openbb_core.app.model.abstract.error import OpenBBError
|
|
12
13
|
from openbb_core.app.utils import get_user_cache_directory
|
|
13
14
|
from openbb_core.provider.utils.helpers import amake_request, make_request
|
|
14
15
|
from openbb_sec.utils.definitions import HEADERS, SEC_HEADERS
|
|
@@ -280,7 +281,7 @@ async def get_series_id(
|
|
|
280
281
|
|
|
281
282
|
results = pd.DataFrame()
|
|
282
283
|
if not symbol and not cik:
|
|
283
|
-
raise
|
|
284
|
+
raise OpenBBError("Either symbol or cik must be provided.")
|
|
284
285
|
|
|
285
286
|
target = symbol if symbol else cik
|
|
286
287
|
choice = "cik" if not symbol else "symbol"
|
|
@@ -310,9 +311,9 @@ async def get_nport_candidates(symbol: str, use_cache: bool = True) -> List[Dict
|
|
|
310
311
|
else _series_id["seriesId"].iloc[0]
|
|
311
312
|
)
|
|
312
313
|
except IndexError as e:
|
|
313
|
-
raise
|
|
314
|
+
raise OpenBBError("Fund not found for, the symbol: " + symbol) from e
|
|
314
315
|
if series_id == "" or series_id is None:
|
|
315
|
-
raise
|
|
316
|
+
raise OpenBBError("Fund not found for, the symbol: " + symbol)
|
|
316
317
|
|
|
317
318
|
url = f"https://efts.sec.gov/LATEST/search-index?q={series_id}&dateRange=all&forms=NPORT-P"
|
|
318
319
|
response: Union[dict, List[dict]] = {}
|
|
@@ -4,6 +4,7 @@ from typing import Any, Dict, Optional
|
|
|
4
4
|
|
|
5
5
|
import xmltodict
|
|
6
6
|
from bs4 import BeautifulSoup
|
|
7
|
+
from openbb_core.app.model.abstract.error import OpenBBError
|
|
7
8
|
from openbb_core.provider.utils.helpers import amake_request
|
|
8
9
|
from openbb_sec.models.company_filings import SecCompanyFilingsFetcher
|
|
9
10
|
from openbb_sec.utils.definitions import HEADERS
|
|
@@ -28,14 +29,14 @@ async def get_13f_candidates(symbol: Optional[str] = None, cik: Optional[str] =
|
|
|
28
29
|
if symbol is not None:
|
|
29
30
|
params["symbol"] = symbol
|
|
30
31
|
if cik is None and symbol is None:
|
|
31
|
-
raise
|
|
32
|
+
raise OpenBBError("Either symbol or cik must be provided.")
|
|
32
33
|
|
|
33
34
|
params["use_cache"] = False
|
|
34
35
|
params["form_type"] = "13F-HR"
|
|
35
36
|
filings = await fetcher.fetch_data(params, {})
|
|
36
37
|
filings = [d.model_dump() for d in filings]
|
|
37
38
|
if len(filings) == 0:
|
|
38
|
-
raise
|
|
39
|
+
raise OpenBBError(f"No 13F-HR filings found for {symbol if symbol else cik}.")
|
|
39
40
|
|
|
40
41
|
# Filings before June 30, 2013 are non-structured and are not supported by downstream parsers.
|
|
41
42
|
up_to = to_datetime("2013-06-30").date() # pylint: disable=unused-variable # noqa
|
|
@@ -52,7 +53,7 @@ async def complete_submission_callback(response, _):
|
|
|
52
53
|
"""Use callback function for processing the response object."""
|
|
53
54
|
if response.status == 200:
|
|
54
55
|
return await response.text()
|
|
55
|
-
raise
|
|
56
|
+
raise OpenBBError(f"Request failed with status code {response.status}")
|
|
56
57
|
|
|
57
58
|
|
|
58
59
|
async def get_complete_submission(url: str):
|
|
@@ -75,7 +76,7 @@ def parse_header(filing_str: str) -> Dict:
|
|
|
75
76
|
header_dict = xmltodict.parse(str(header_xml)).get("type")
|
|
76
77
|
if header_dict:
|
|
77
78
|
return header_dict # type: ignore
|
|
78
|
-
raise
|
|
79
|
+
raise OpenBBError(
|
|
79
80
|
"Failed to parse the form header."
|
|
80
81
|
+ " Check the `filing_str` to for the tag, 'headerData'."
|
|
81
82
|
)
|
|
@@ -91,7 +92,7 @@ def get_submission_type(filing_str: str):
|
|
|
91
92
|
except KeyError:
|
|
92
93
|
form_type = header["#text"]
|
|
93
94
|
return form_type
|
|
94
|
-
raise
|
|
95
|
+
raise OpenBBError(
|
|
95
96
|
"Failed to get the submission type from the form header."
|
|
96
97
|
+ " Check the response from `parse_header`."
|
|
97
98
|
)
|
|
@@ -102,7 +103,7 @@ def get_period_ending(filing_str: str):
|
|
|
102
103
|
header = parse_header(filing_str)
|
|
103
104
|
if header.get("filerInfo"):
|
|
104
105
|
return header["filerInfo"].get("periodOfReport")
|
|
105
|
-
raise
|
|
106
|
+
raise OpenBBError(
|
|
106
107
|
"Failed to get the period of report from the form header."
|
|
107
108
|
+ " Check the response from `parse_header`."
|
|
108
109
|
)
|
|
@@ -118,12 +119,12 @@ async def parse_13f_hr(filing: str):
|
|
|
118
119
|
|
|
119
120
|
# Validate the submission so we know that we can parse it.
|
|
120
121
|
if get_submission_type(filing) not in ("13F-HR", "13F-HR/A"):
|
|
121
|
-
raise
|
|
122
|
+
raise OpenBBError("Submission type is not 13F-HR.")
|
|
122
123
|
|
|
123
124
|
soup = BeautifulSoup(filing, "lxml-xml")
|
|
124
125
|
|
|
125
126
|
info_table = soup.find_all("informationTable")
|
|
126
|
-
if info_table
|
|
127
|
+
if not info_table:
|
|
127
128
|
info_table = soup.find_all("table")[-1]
|
|
128
129
|
|
|
129
130
|
parsed_xml = xmltodict.parse(
|
|
@@ -131,7 +132,7 @@ async def parse_13f_hr(filing: str):
|
|
|
131
132
|
)["informationTable"]["infoTable"]
|
|
132
133
|
|
|
133
134
|
if parsed_xml is None:
|
|
134
|
-
raise
|
|
135
|
+
raise OpenBBError(
|
|
135
136
|
"Failed to parse the 13F-HR information table."
|
|
136
137
|
+ " Check the `filing_str` to make sure it is valid and contains the tag 'informationTable'."
|
|
137
138
|
+ " Documents filed before Q2 2013 are not supported."
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "openbb-sec"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.3"
|
|
4
4
|
description = "SEC extension for OpenBB"
|
|
5
5
|
authors = ["OpenBB Team <hello@openbb.co>"]
|
|
6
6
|
license = "AGPL-3.0-only"
|
|
@@ -9,7 +9,7 @@ packages = [{ include = "openbb_sec" }]
|
|
|
9
9
|
|
|
10
10
|
[tool.poetry.dependencies]
|
|
11
11
|
python = ">=3.8,<3.12"
|
|
12
|
-
openbb-core = "^1.2.
|
|
12
|
+
openbb-core = "^1.2.5"
|
|
13
13
|
aiohttp-client-cache = "^0.11.0"
|
|
14
14
|
aiosqlite = "^0.20.0"
|
|
15
15
|
xmltodict = "^0.13.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|