marketstack-python-client 1.0.0__py3-none-any.whl
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.
- marketstack/__init__.py +1 -0
- marketstack/client/__init__.py +0 -0
- marketstack/client/http.py +36 -0
- marketstack/client/marketstack.py +148 -0
- marketstack/models/__init__.py +0 -0
- marketstack/models/bond.py +47 -0
- marketstack/models/cik_code.py +26 -0
- marketstack/models/commodity.py +83 -0
- marketstack/models/company.py +278 -0
- marketstack/models/concept.py +65 -0
- marketstack/models/currency.py +23 -0
- marketstack/models/dividend.py +27 -0
- marketstack/models/eod.py +48 -0
- marketstack/models/etf.py +129 -0
- marketstack/models/exchange.py +117 -0
- marketstack/models/index.py +47 -0
- marketstack/models/intraday.py +43 -0
- marketstack/models/pagination.py +42 -0
- marketstack/models/split.py +24 -0
- marketstack/models/stockprice.py +31 -0
- marketstack/models/ticker.py +159 -0
- marketstack/models/ticker_info.py +197 -0
- marketstack/models/timezone.py +21 -0
- marketstack/namespaces/__init__.py +0 -0
- marketstack/namespaces/bond/__init__.py +1 -0
- marketstack/namespaces/bond/bond.py +12 -0
- marketstack/namespaces/bondlist/__init__.py +1 -0
- marketstack/namespaces/bondlist/bondlist.py +12 -0
- marketstack/namespaces/cikcode/__init__.py +1 -0
- marketstack/namespaces/cikcode/cikcode.py +12 -0
- marketstack/namespaces/commodities/__init__.py +1 -0
- marketstack/namespaces/commodities/commodities.py +12 -0
- marketstack/namespaces/commoditieshistory/__init__.py +1 -0
- marketstack/namespaces/commoditieshistory/commoditieshistory.py +12 -0
- marketstack/namespaces/company_facts/__init__.py +1 -0
- marketstack/namespaces/company_facts/company_facts.py +12 -0
- marketstack/namespaces/companyname/__init__.py +1 -0
- marketstack/namespaces/companyname/companyname.py +12 -0
- marketstack/namespaces/companyratings/__init__.py +1 -0
- marketstack/namespaces/companyratings/companyratings.py +12 -0
- marketstack/namespaces/concept/__init__.py +1 -0
- marketstack/namespaces/concept/concept.py +12 -0
- marketstack/namespaces/currencies/__init__.py +1 -0
- marketstack/namespaces/currencies/currencies.py +12 -0
- marketstack/namespaces/dividends/__init__.py +1 -0
- marketstack/namespaces/dividends/dividends.py +12 -0
- marketstack/namespaces/eod/__init__.py +1 -0
- marketstack/namespaces/eod/eod.py +20 -0
- marketstack/namespaces/etfholdings/__init__.py +1 -0
- marketstack/namespaces/etfholdings/etfholdings.py +12 -0
- marketstack/namespaces/etflist/__init__.py +1 -0
- marketstack/namespaces/etflist/etflist.py +12 -0
- marketstack/namespaces/exchanges/__init__.py +1 -0
- marketstack/namespaces/exchanges/exchanges.py +109 -0
- marketstack/namespaces/frames/__init__.py +1 -0
- marketstack/namespaces/frames/frames.py +12 -0
- marketstack/namespaces/indexinfo/__init__.py +1 -0
- marketstack/namespaces/indexinfo/indexinfo.py +12 -0
- marketstack/namespaces/indexlist/__init__.py +1 -0
- marketstack/namespaces/indexlist/indexlist.py +12 -0
- marketstack/namespaces/intraday/__init__.py +1 -0
- marketstack/namespaces/intraday/intraday.py +20 -0
- marketstack/namespaces/splits/__init__.py +1 -0
- marketstack/namespaces/splits/splits.py +12 -0
- marketstack/namespaces/stockprice/__init__.py +1 -0
- marketstack/namespaces/stockprice/stockprice.py +12 -0
- marketstack/namespaces/submissions/__init__.py +1 -0
- marketstack/namespaces/submissions/submissions.py +12 -0
- marketstack/namespaces/tickerinfo/__init__.py +1 -0
- marketstack/namespaces/tickerinfo/tickerinfo.py +12 -0
- marketstack/namespaces/tickers/__init__.py +1 -0
- marketstack/namespaces/tickers/tickers.py +150 -0
- marketstack/namespaces/tickerslist/__init__.py +1 -0
- marketstack/namespaces/tickerslist/tickerslist.py +12 -0
- marketstack/namespaces/timezones/__init__.py +1 -0
- marketstack/namespaces/timezones/timezones.py +12 -0
- marketstack_python_client-1.0.0.dist-info/METADATA +182 -0
- marketstack_python_client-1.0.0.dist-info/RECORD +81 -0
- marketstack_python_client-1.0.0.dist-info/WHEEL +5 -0
- marketstack_python_client-1.0.0.dist-info/licenses/LICENSE +21 -0
- marketstack_python_client-1.0.0.dist-info/top_level.txt +1 -0
marketstack/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .client.marketstack import Marketstack
|
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class HTTPClient:
|
|
5
|
+
def __init__(self, base_url: str, params: dict = None):
|
|
6
|
+
self.base_url = base_url
|
|
7
|
+
self.params = params or {}
|
|
8
|
+
|
|
9
|
+
def get(self, endpoint: str, params: dict = None):
|
|
10
|
+
merged_params = {**self.params}
|
|
11
|
+
if params:
|
|
12
|
+
cleaned_params = {k: v for k, v in params.items() if v is not None}
|
|
13
|
+
merged_params.update(cleaned_params)
|
|
14
|
+
with httpx.Client(base_url=self.base_url, timeout=30.0) as client:
|
|
15
|
+
response = client.get(endpoint, params=merged_params)
|
|
16
|
+
response.raise_for_status()
|
|
17
|
+
data = response.json()
|
|
18
|
+
if isinstance(data, dict):
|
|
19
|
+
if "error" in data:
|
|
20
|
+
err = data["error"]
|
|
21
|
+
err_msg = err.get("message", "Unknown error") if isinstance(err, dict) else str(err)
|
|
22
|
+
err_code = err.get("code", "unknown") if isinstance(err, dict) else "unknown"
|
|
23
|
+
raise httpx.HTTPStatusError(
|
|
24
|
+
message=f"API Error ({err_code}): {err_msg}",
|
|
25
|
+
request=response.request,
|
|
26
|
+
response=response,
|
|
27
|
+
)
|
|
28
|
+
if data.get("message") == "error":
|
|
29
|
+
err_msg = data.get("details", "Unknown error")
|
|
30
|
+
err_code = data.get("code", "unknown")
|
|
31
|
+
raise httpx.HTTPStatusError(
|
|
32
|
+
message=f"API Error ({err_code}): {err_msg}",
|
|
33
|
+
request=response.request,
|
|
34
|
+
response=response,
|
|
35
|
+
)
|
|
36
|
+
return data
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
from marketstack.client.http import HTTPClient
|
|
2
|
+
from marketstack.namespaces.bond import Bond
|
|
3
|
+
from marketstack.namespaces.bondlist import BondList
|
|
4
|
+
from marketstack.namespaces.cikcode import CIKCode
|
|
5
|
+
from marketstack.namespaces.commodities import Commodities
|
|
6
|
+
from marketstack.namespaces.commoditieshistory import CommoditiesHistory
|
|
7
|
+
from marketstack.namespaces.company_facts import CompanyFacts
|
|
8
|
+
from marketstack.namespaces.companyname import CompanyName
|
|
9
|
+
from marketstack.namespaces.companyratings import CompanyRatings
|
|
10
|
+
from marketstack.namespaces.concept import Concept
|
|
11
|
+
from marketstack.namespaces.currencies import Currencies
|
|
12
|
+
from marketstack.namespaces.dividends import Dividends
|
|
13
|
+
from marketstack.namespaces.eod import EOD
|
|
14
|
+
from marketstack.namespaces.etfholdings import ETFHoldings
|
|
15
|
+
from marketstack.namespaces.etflist import ETFList
|
|
16
|
+
from marketstack.namespaces.exchanges import Exchanges
|
|
17
|
+
from marketstack.namespaces.frames import Frames
|
|
18
|
+
from marketstack.namespaces.indexinfo import IndexInfo
|
|
19
|
+
from marketstack.namespaces.indexlist import IndexList
|
|
20
|
+
from marketstack.namespaces.intraday import Intraday
|
|
21
|
+
from marketstack.namespaces.splits import Splits
|
|
22
|
+
from marketstack.namespaces.stockprice import StockPrice
|
|
23
|
+
from marketstack.namespaces.submissions import Submissions
|
|
24
|
+
from marketstack.namespaces.tickerinfo import TickerInfo
|
|
25
|
+
from marketstack.namespaces.tickers import Tickers
|
|
26
|
+
from marketstack.namespaces.tickerslist import TickersList
|
|
27
|
+
from marketstack.namespaces.timezones import Timezones
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Marketstack:
|
|
31
|
+
"""
|
|
32
|
+
The marketstack API was built to deliver worldwide stock market data
|
|
33
|
+
(real-time, intraday and historical), together with information on stock
|
|
34
|
+
exchanges, tickers, indices, ETFs, bonds, commodities and company
|
|
35
|
+
fundamentals, in a simple, lightweight JSON format. Requests to the REST API
|
|
36
|
+
are made using a straightforward HTTP GET URL structure. This documentation
|
|
37
|
+
covers the v2 API surface.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(self, api_key: str):
|
|
41
|
+
self.http_client = HTTPClient(
|
|
42
|
+
base_url="https://api.marketstack.com",
|
|
43
|
+
params={"access_key": api_key},
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def bond(self) -> Bond:
|
|
48
|
+
return Bond(http_client=self.http_client)
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def bondlist(self) -> BondList:
|
|
52
|
+
return BondList(http_client=self.http_client)
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def cikcode(self) -> CIKCode:
|
|
56
|
+
return CIKCode(http_client=self.http_client)
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def commodities(self) -> Commodities:
|
|
60
|
+
return Commodities(http_client=self.http_client)
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def commoditieshistory(self) -> CommoditiesHistory:
|
|
64
|
+
return CommoditiesHistory(http_client=self.http_client)
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def company_facts(self) -> CompanyFacts:
|
|
68
|
+
return CompanyFacts(http_client=self.http_client)
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def companyname(self) -> CompanyName:
|
|
72
|
+
return CompanyName(http_client=self.http_client)
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def companyratings(self) -> CompanyRatings:
|
|
76
|
+
return CompanyRatings(http_client=self.http_client)
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def concept(self) -> Concept:
|
|
80
|
+
return Concept(http_client=self.http_client)
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def currencies(self) -> Currencies:
|
|
84
|
+
return Currencies(http_client=self.http_client)
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def dividends(self) -> Dividends:
|
|
88
|
+
return Dividends(http_client=self.http_client)
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def eod(self) -> EOD:
|
|
92
|
+
return EOD(http_client=self.http_client)
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def etfholdings(self) -> ETFHoldings:
|
|
96
|
+
return ETFHoldings(http_client=self.http_client)
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def etflist(self) -> ETFList:
|
|
100
|
+
return ETFList(http_client=self.http_client)
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def exchanges(self) -> Exchanges:
|
|
104
|
+
return Exchanges(http_client=self.http_client)
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def frames(self) -> Frames:
|
|
108
|
+
return Frames(http_client=self.http_client)
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def indexinfo(self) -> IndexInfo:
|
|
112
|
+
return IndexInfo(http_client=self.http_client)
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def indexlist(self) -> IndexList:
|
|
116
|
+
return IndexList(http_client=self.http_client)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def intraday(self) -> Intraday:
|
|
120
|
+
return Intraday(http_client=self.http_client)
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def splits(self) -> Splits:
|
|
124
|
+
return Splits(http_client=self.http_client)
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def stockprice(self) -> StockPrice:
|
|
128
|
+
return StockPrice(http_client=self.http_client)
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def submissions(self) -> Submissions:
|
|
132
|
+
return Submissions(http_client=self.http_client)
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def tickerinfo(self) -> TickerInfo:
|
|
136
|
+
return TickerInfo(http_client=self.http_client)
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def tickers(self) -> Tickers:
|
|
140
|
+
return Tickers(http_client=self.http_client)
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def tickerslist(self) -> TickersList:
|
|
144
|
+
return TickersList(http_client=self.http_client)
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def timezones(self) -> Timezones:
|
|
148
|
+
return Timezones(http_client=self.http_client)
|
|
File without changes
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from typing import Union
|
|
3
|
+
from types import NoneType
|
|
4
|
+
from .pagination import Pagniation, PaginationRequest
|
|
5
|
+
from typing import TypedDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BondRequest(TypedDict, total=False):
|
|
9
|
+
country: Union[NoneType, str] = None
|
|
10
|
+
"""Filter bonds by country."""
|
|
11
|
+
|
|
12
|
+
class BondListRequest(PaginationRequest, total=False):
|
|
13
|
+
country: Union[NoneType, str] = None
|
|
14
|
+
"""Filter bond list by country."""
|
|
15
|
+
|
|
16
|
+
class BondInfoItem(BaseModel):
|
|
17
|
+
region: str
|
|
18
|
+
"""Region where the bond is supported."""
|
|
19
|
+
country: str
|
|
20
|
+
"""Country where the bond is supported."""
|
|
21
|
+
type: str
|
|
22
|
+
"""Bond tenor/type (for example 10Y)."""
|
|
23
|
+
yield_: str = Field(..., alias="yield")
|
|
24
|
+
"""Current bond yield."""
|
|
25
|
+
price_change_day: str
|
|
26
|
+
"""Price change day-over-day."""
|
|
27
|
+
percentage_week: str
|
|
28
|
+
"""Weekly change percentage."""
|
|
29
|
+
percentage_month: str
|
|
30
|
+
"""Monthly change percentage."""
|
|
31
|
+
percentage_year: str
|
|
32
|
+
"""Yearly change percentage."""
|
|
33
|
+
date: str
|
|
34
|
+
"""Quote date."""
|
|
35
|
+
model_config = {"populate_by_name": True}
|
|
36
|
+
|
|
37
|
+
class BondInfoResponse(BaseModel):
|
|
38
|
+
pagination: Pagniation
|
|
39
|
+
data: list["BondInfoItem"]
|
|
40
|
+
|
|
41
|
+
class BondListItem(BaseModel):
|
|
42
|
+
country: str
|
|
43
|
+
"""Country supported for bonds."""
|
|
44
|
+
|
|
45
|
+
class BondListResponse(BaseModel):
|
|
46
|
+
pagination: Pagniation
|
|
47
|
+
data: list["BondListItem"]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
from typing import Union
|
|
3
|
+
from types import NoneType
|
|
4
|
+
from .pagination import Pagniation, PaginationRequest
|
|
5
|
+
from typing import TypedDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CIKCodeRequest(PaginationRequest, total=False):
|
|
9
|
+
company_name: Union[NoneType, str] = None
|
|
10
|
+
"""Search by company name."""
|
|
11
|
+
|
|
12
|
+
class CIKItem(BaseModel):
|
|
13
|
+
cik_code: str
|
|
14
|
+
"""Company CIK code."""
|
|
15
|
+
company_name: str
|
|
16
|
+
"""Company name."""
|
|
17
|
+
ein: str
|
|
18
|
+
"""Employer Identification Number."""
|
|
19
|
+
sic: str
|
|
20
|
+
"""Standard Industrial Classification."""
|
|
21
|
+
sic_description: str
|
|
22
|
+
"""SIC description."""
|
|
23
|
+
|
|
24
|
+
class CIKSearchResponse(BaseModel):
|
|
25
|
+
pagination: Pagniation
|
|
26
|
+
data: list["CIKItem"]
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
from typing import Union
|
|
3
|
+
from types import NoneType
|
|
4
|
+
from .pagination import Pagniation, PaginationRequest
|
|
5
|
+
from typing import TypedDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CommoditiesRequest(TypedDict, total=False):
|
|
9
|
+
commodity_name: Union[NoneType, str] = None
|
|
10
|
+
"""Filter by commodity name."""
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CommoditiesHistoryRequest(TypedDict, total=False):
|
|
14
|
+
commodity_name: Union[NoneType, str] = None
|
|
15
|
+
"""Filter by commodity name."""
|
|
16
|
+
date_from: Union[NoneType, str] = None
|
|
17
|
+
"""Start date."""
|
|
18
|
+
date_to: Union[NoneType, str] = None
|
|
19
|
+
"""End date."""
|
|
20
|
+
frequency: Union[NoneType, str] = None
|
|
21
|
+
"""Frequency (e.g. 1day)."""
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class CommodityItem(BaseModel):
|
|
25
|
+
commodity_name: str
|
|
26
|
+
"""Name of the commodity."""
|
|
27
|
+
commodity_unit: str
|
|
28
|
+
"""Unit of the commodity."""
|
|
29
|
+
commodity_price: str
|
|
30
|
+
"""Current price of the commodity."""
|
|
31
|
+
price_change_day: str
|
|
32
|
+
"""Absolute day change."""
|
|
33
|
+
percentage_day: str
|
|
34
|
+
"""Day change in percent."""
|
|
35
|
+
percentage_week: str
|
|
36
|
+
"""Week change in percent."""
|
|
37
|
+
percentage_month: str
|
|
38
|
+
"""Month change in percent."""
|
|
39
|
+
percentage_year: str
|
|
40
|
+
"""Year change in percent."""
|
|
41
|
+
quarter1_25: str
|
|
42
|
+
"""Value for the first quarter of 2025."""
|
|
43
|
+
quarter2_25: str
|
|
44
|
+
"""Value for the second quarter of 2025."""
|
|
45
|
+
quarter3_25: str
|
|
46
|
+
"""Value for the third quarter of 2025."""
|
|
47
|
+
quarter4_25: str
|
|
48
|
+
"""Value for the fourth quarter of 2025."""
|
|
49
|
+
datetime: str
|
|
50
|
+
"""Timestamp of the commodity price in ISO8601 format."""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class CommodityResponse(BaseModel):
|
|
54
|
+
data: list[CommodityItem]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class CommodityHistoricalBasics(BaseModel):
|
|
58
|
+
frequency: str
|
|
59
|
+
"""Frequency of the historical data (e.g., 1day, 1month)."""
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class CommodityPriceItem(BaseModel):
|
|
63
|
+
commodity_price: str
|
|
64
|
+
"""Price of the commodity for the date."""
|
|
65
|
+
date: str
|
|
66
|
+
"""Date for the price (YYYY-MM-DD or YYYY-MM for monthly)."""
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class CommodityHistoricalData(BaseModel):
|
|
70
|
+
commodity_name: str
|
|
71
|
+
"""Name of the commodity."""
|
|
72
|
+
commodity_unit: str
|
|
73
|
+
"""Unit of the commodity."""
|
|
74
|
+
commodity_prices: list[CommodityPriceItem]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class CommodityHistoricalResult(BaseModel):
|
|
78
|
+
basics: CommodityHistoricalBasics
|
|
79
|
+
data: list[CommodityHistoricalData]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class CommodityHistoricalResponse(BaseModel):
|
|
83
|
+
result: CommodityHistoricalResult
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from typing import Union
|
|
3
|
+
from types import NoneType
|
|
4
|
+
from .pagination import Pagniation, PaginationRequest
|
|
5
|
+
from typing import TypedDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CompanyFactsRequest(PaginationRequest, total=False):
|
|
9
|
+
cik_code: Union[NoneType, str] = None
|
|
10
|
+
"""Filter by CIK code."""
|
|
11
|
+
|
|
12
|
+
class CompanyNameRequest(PaginationRequest, total=False):
|
|
13
|
+
cik_code: Union[NoneType, str] = None
|
|
14
|
+
"""Filter by CIK code."""
|
|
15
|
+
|
|
16
|
+
class CompanyRatingsRequest(TypedDict, total=False):
|
|
17
|
+
ticker: Union[NoneType, str] = None
|
|
18
|
+
"""Filter by stock ticker symbol."""
|
|
19
|
+
date_from: Union[NoneType, str] = None
|
|
20
|
+
"""Start date."""
|
|
21
|
+
date_to: Union[NoneType, str] = None
|
|
22
|
+
"""End date."""
|
|
23
|
+
rated: Union[NoneType, str] = None
|
|
24
|
+
"""Filter by rating."""
|
|
25
|
+
|
|
26
|
+
class SubmissionsRequest(TypedDict, total=False):
|
|
27
|
+
cik_code: Union[NoneType, str] = None
|
|
28
|
+
"""Filter by CIK code."""
|
|
29
|
+
accession_number: Union[NoneType, str] = None
|
|
30
|
+
"""Filter by accession number."""
|
|
31
|
+
cik_code_name: Union[NoneType, str] = None
|
|
32
|
+
"""Filter by CIK name."""
|
|
33
|
+
filing_from: Union[NoneType, str] = None
|
|
34
|
+
"""Start date."""
|
|
35
|
+
filing_to: Union[NoneType, str] = None
|
|
36
|
+
"""End date."""
|
|
37
|
+
report_from: Union[NoneType, str] = None
|
|
38
|
+
"""Report start date."""
|
|
39
|
+
report_to: Union[NoneType, str] = None
|
|
40
|
+
"""Report end date."""
|
|
41
|
+
|
|
42
|
+
class CompanyFactUnitItem(BaseModel):
|
|
43
|
+
fp: Union[NoneType, str] = None
|
|
44
|
+
"""Fiscal period (e.g. Q3, FY)."""
|
|
45
|
+
fy: Union[NoneType, int] = None
|
|
46
|
+
"""Fiscal year."""
|
|
47
|
+
start: Union[NoneType, str] = None
|
|
48
|
+
"""Period start date. Present on duration concepts (e.g. revenue, expenses); absent on point-in-time concepts."""
|
|
49
|
+
end: Union[NoneType, str] = None
|
|
50
|
+
"""Period end date."""
|
|
51
|
+
val: float
|
|
52
|
+
"""Reported value."""
|
|
53
|
+
accn: str
|
|
54
|
+
"""Accession number of the source filing."""
|
|
55
|
+
form: str
|
|
56
|
+
"""Filing form type (e.g. 10-K, 10-Q)."""
|
|
57
|
+
filed: str
|
|
58
|
+
"""Filing date."""
|
|
59
|
+
frame: Union[NoneType, str] = None
|
|
60
|
+
"""CY frame identifier (present when comparable)."""
|
|
61
|
+
|
|
62
|
+
class CompanyFactConcept(BaseModel):
|
|
63
|
+
"""A single XBRL concept."""
|
|
64
|
+
label: str
|
|
65
|
+
"""Human-readable concept label."""
|
|
66
|
+
description: str
|
|
67
|
+
"""Concept definition."""
|
|
68
|
+
units: dict[str, list[CompanyFactUnitItem]]
|
|
69
|
+
"""Fact values keyed by unit of measure (e.g. USD, shares)."""
|
|
70
|
+
|
|
71
|
+
class CompanyFactsData(BaseModel):
|
|
72
|
+
cik: int
|
|
73
|
+
"""SEC Central Index Key."""
|
|
74
|
+
company_name: str
|
|
75
|
+
"""Company name."""
|
|
76
|
+
facts: dict[str, dict[str, CompanyFactConcept]]
|
|
77
|
+
"""XBRL concepts keyed by taxonomy (e.g. dei, us-gaap), then by concept tag. Keys are dynamic; the value shape below is consistent."""
|
|
78
|
+
|
|
79
|
+
class CompanyFactsByCIKResponse(BaseModel):
|
|
80
|
+
data: CompanyFactsData
|
|
81
|
+
|
|
82
|
+
class CompanyAddress(BaseModel):
|
|
83
|
+
street1: str
|
|
84
|
+
street2: str
|
|
85
|
+
city: str
|
|
86
|
+
state_or_country: str
|
|
87
|
+
zip_code: str
|
|
88
|
+
|
|
89
|
+
class CompanyAddresses(BaseModel):
|
|
90
|
+
"""Mailing and business addresses."""
|
|
91
|
+
mailing: Union[NoneType, CompanyAddress] = None
|
|
92
|
+
business: Union[NoneType, CompanyAddress] = None
|
|
93
|
+
|
|
94
|
+
class CompanyNameData(BaseModel):
|
|
95
|
+
cik_code: str
|
|
96
|
+
"""Company CIK code."""
|
|
97
|
+
company_name: str
|
|
98
|
+
"""Company name."""
|
|
99
|
+
ein: str
|
|
100
|
+
"""Employer Identification Number."""
|
|
101
|
+
sic: str
|
|
102
|
+
"""Standard Industrial Classification code."""
|
|
103
|
+
sic_description: str
|
|
104
|
+
"""SIC description."""
|
|
105
|
+
phone: str
|
|
106
|
+
"""Company registered phone."""
|
|
107
|
+
incorporation_state: str
|
|
108
|
+
"""Abbreviation of the incorporation state."""
|
|
109
|
+
addresses: CompanyAddresses
|
|
110
|
+
"""Mailing and business addresses."""
|
|
111
|
+
|
|
112
|
+
class CompanyNameByCIKResponse(BaseModel):
|
|
113
|
+
data: CompanyNameData
|
|
114
|
+
|
|
115
|
+
class CompanyRatingsStatus(BaseModel):
|
|
116
|
+
code: int
|
|
117
|
+
"""HTTP status code."""
|
|
118
|
+
message: str
|
|
119
|
+
"""Status message."""
|
|
120
|
+
details: Union[NoneType, str] = None
|
|
121
|
+
"""Additional details."""
|
|
122
|
+
|
|
123
|
+
class CompanyRatingsBasics(BaseModel):
|
|
124
|
+
company_name: str
|
|
125
|
+
"""Name of the company."""
|
|
126
|
+
ticker: str
|
|
127
|
+
"""Ticker symbol."""
|
|
128
|
+
|
|
129
|
+
class AnalystConsensus(BaseModel):
|
|
130
|
+
consensus_conclusion: str
|
|
131
|
+
"""Overall consensus (e.g. Buy, Hold, Sell)."""
|
|
132
|
+
stock_price: str
|
|
133
|
+
"""Current stock price."""
|
|
134
|
+
analyst_average: str
|
|
135
|
+
"""Average analyst price target."""
|
|
136
|
+
analyst_highest: str
|
|
137
|
+
"""Highest analyst price target."""
|
|
138
|
+
analyst_lowest: str
|
|
139
|
+
"""Lowest analyst price target."""
|
|
140
|
+
analysts_number: str
|
|
141
|
+
"""Number of contributing analysts."""
|
|
142
|
+
buy: str
|
|
143
|
+
"""Count of buy ratings."""
|
|
144
|
+
hold: str
|
|
145
|
+
"""Count of hold ratings."""
|
|
146
|
+
sell: str
|
|
147
|
+
"""Count of sell ratings."""
|
|
148
|
+
consensus_date: str
|
|
149
|
+
"""Date of the consensus."""
|
|
150
|
+
|
|
151
|
+
class AnalystRatingDetail(BaseModel):
|
|
152
|
+
date_rating: str
|
|
153
|
+
"""Date the rating was issued."""
|
|
154
|
+
target_date: str
|
|
155
|
+
"""Target date for the price target."""
|
|
156
|
+
price_target: str
|
|
157
|
+
"""Analyst price target."""
|
|
158
|
+
rated: str
|
|
159
|
+
"""Rating (buy, sell, hold)."""
|
|
160
|
+
conclusion: str
|
|
161
|
+
"""Rating conclusion."""
|
|
162
|
+
|
|
163
|
+
class AnalystItem(BaseModel):
|
|
164
|
+
analyst_name: str
|
|
165
|
+
"""Analyst name."""
|
|
166
|
+
analyst_firm: str
|
|
167
|
+
"""Analyst firm."""
|
|
168
|
+
analyst_role: str
|
|
169
|
+
"""Analyst role/title."""
|
|
170
|
+
rating: AnalystRatingDetail
|
|
171
|
+
|
|
172
|
+
class CompanyRatingsOutput(BaseModel):
|
|
173
|
+
"""Analyst consensus and individual analyst ratings."""
|
|
174
|
+
analyst_consensus: AnalystConsensus
|
|
175
|
+
analysts: list[AnalystItem]
|
|
176
|
+
"""Individual analyst ratings."""
|
|
177
|
+
|
|
178
|
+
class CompanyRatingsResult(BaseModel):
|
|
179
|
+
basics: CompanyRatingsBasics
|
|
180
|
+
output: CompanyRatingsOutput
|
|
181
|
+
"""Analyst consensus and individual analyst ratings."""
|
|
182
|
+
|
|
183
|
+
class CompanyRatingsResponse(BaseModel):
|
|
184
|
+
status: "CompanyRatingsStatus"
|
|
185
|
+
result: "CompanyRatingsResult"
|
|
186
|
+
|
|
187
|
+
class FormerName(BaseModel):
|
|
188
|
+
name: str
|
|
189
|
+
from_: str = Field(..., alias="from")
|
|
190
|
+
to: str
|
|
191
|
+
model_config = {"populate_by_name": True}
|
|
192
|
+
|
|
193
|
+
class RecentFilings(BaseModel):
|
|
194
|
+
"""Most recent filings as index-aligned parallel arrays."""
|
|
195
|
+
accession_number: list[str]
|
|
196
|
+
filing_date: list[str]
|
|
197
|
+
report_date: list[str]
|
|
198
|
+
acceptance_date_time: list[str]
|
|
199
|
+
act: list[str]
|
|
200
|
+
form: list[str]
|
|
201
|
+
file_number: list[str]
|
|
202
|
+
film_number: list[str]
|
|
203
|
+
core_type: list[str]
|
|
204
|
+
size: list[int]
|
|
205
|
+
primary_document: list[str]
|
|
206
|
+
primary_doc_description: list[str]
|
|
207
|
+
|
|
208
|
+
class OlderFilingFile(BaseModel):
|
|
209
|
+
name: str
|
|
210
|
+
filing_count: int
|
|
211
|
+
filing_from: str
|
|
212
|
+
filing_to: str
|
|
213
|
+
|
|
214
|
+
class SubmissionsFilings(BaseModel):
|
|
215
|
+
"""Recent filings and paginated file references."""
|
|
216
|
+
recent: RecentFilings
|
|
217
|
+
"""Most recent filings as index-aligned parallel arrays."""
|
|
218
|
+
files: list[OlderFilingFile]
|
|
219
|
+
"""References to older, paginated filing files."""
|
|
220
|
+
|
|
221
|
+
class SubmissionsData(BaseModel):
|
|
222
|
+
cik_code: str
|
|
223
|
+
"""SEC Central Index Key (zero-padded)."""
|
|
224
|
+
company_name: str
|
|
225
|
+
"""Company name."""
|
|
226
|
+
entity_type: str
|
|
227
|
+
"""Entity type (e.g. operating)."""
|
|
228
|
+
ein: str
|
|
229
|
+
"""Employer Identification Number."""
|
|
230
|
+
sic: str
|
|
231
|
+
"""Standard Industrial Classification code."""
|
|
232
|
+
sic_description: str
|
|
233
|
+
"""SIC description."""
|
|
234
|
+
owner_org: str
|
|
235
|
+
"""SEC owner organization classification."""
|
|
236
|
+
insider_transaction_for_owner_exists: int
|
|
237
|
+
"""Whether insider transactions exist for the owner (0 or 1)."""
|
|
238
|
+
insider_transaction_for_issuer_exists: int
|
|
239
|
+
"""Whether insider transactions exist for the issuer (0 or 1)."""
|
|
240
|
+
tickers: list[str]
|
|
241
|
+
exchanges: list[str]
|
|
242
|
+
description: str
|
|
243
|
+
"""Company description."""
|
|
244
|
+
website: str
|
|
245
|
+
"""Company website."""
|
|
246
|
+
investor_website: str
|
|
247
|
+
"""Investor relations website."""
|
|
248
|
+
category_filer: str
|
|
249
|
+
"""Filer category (e.g. Large accelerated filer)."""
|
|
250
|
+
fiscal_year_end: str
|
|
251
|
+
"""Fiscal year end (MMDD)."""
|
|
252
|
+
incorporation_state_or_country: str
|
|
253
|
+
"""State or country of incorporation."""
|
|
254
|
+
incorporation_state_or_country_desc: str
|
|
255
|
+
"""State or country of incorporation, described."""
|
|
256
|
+
phone: str
|
|
257
|
+
"""Company phone number."""
|
|
258
|
+
addresses: CompanyAddresses
|
|
259
|
+
"""Mailing and business addresses."""
|
|
260
|
+
former_names: list[FormerName]
|
|
261
|
+
"""Previous company names with active date ranges."""
|
|
262
|
+
filings: SubmissionsFilings
|
|
263
|
+
"""Recent filings and paginated file references."""
|
|
264
|
+
|
|
265
|
+
class SubmissionsByCIKResponse(BaseModel):
|
|
266
|
+
data: SubmissionsData
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
# Rebuild models to resolve forward references
|
|
270
|
+
CompanyFactsByCIKResponse.model_rebuild()
|
|
271
|
+
CompanyNameByCIKResponse.model_rebuild()
|
|
272
|
+
CompanyRatingsResponse.model_rebuild()
|
|
273
|
+
CompanyRatingsResult.model_rebuild()
|
|
274
|
+
CompanyRatingsOutput.model_rebuild()
|
|
275
|
+
AnalystItem.model_rebuild()
|
|
276
|
+
SubmissionsByCIKResponse.model_rebuild()
|
|
277
|
+
SubmissionsData.model_rebuild()
|
|
278
|
+
SubmissionsFilings.model_rebuild()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
from typing import Union
|
|
3
|
+
from types import NoneType
|
|
4
|
+
from .company import CompanyFactConcept
|
|
5
|
+
from .pagination import Pagniation, PaginationRequest
|
|
6
|
+
from typing import TypedDict
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ConceptRequest(PaginationRequest, total=False):
|
|
10
|
+
cik_code: Union[NoneType, str] = None
|
|
11
|
+
"""Filter by CIK code."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FramesRequest(PaginationRequest, total=False):
|
|
15
|
+
frame: Union[NoneType, str] = None
|
|
16
|
+
"""Specify CY frame identifier."""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AccountsPayableData(BaseModel):
|
|
20
|
+
cik: int
|
|
21
|
+
"""SEC Central Index Key."""
|
|
22
|
+
company_name: str
|
|
23
|
+
"""Company name."""
|
|
24
|
+
us_gaap: dict[str, CompanyFactConcept] = Field(..., alias="us-gaap")
|
|
25
|
+
"""US GAAP concepts keyed by tag (e.g. AccountsPayableCurrent)."""
|
|
26
|
+
|
|
27
|
+
model_config = {"populate_by_name": True}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AccountsPayableResponse(BaseModel):
|
|
31
|
+
data: AccountsPayableData
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class FrameDataItem(BaseModel):
|
|
35
|
+
accn: str
|
|
36
|
+
"""Accession number."""
|
|
37
|
+
cik: int
|
|
38
|
+
"""SEC Central Index Key."""
|
|
39
|
+
entityName: str
|
|
40
|
+
"""Entity name."""
|
|
41
|
+
end: str
|
|
42
|
+
"""End date (YYYY-MM-DD)."""
|
|
43
|
+
val: float
|
|
44
|
+
"""Value."""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class FrameData(BaseModel):
|
|
48
|
+
taxonomy: str
|
|
49
|
+
"""Taxonomy (e.g., us-gaap)."""
|
|
50
|
+
tag: str
|
|
51
|
+
"""Tag name (e.g., AccountsPayableCurrent)."""
|
|
52
|
+
ccp: str
|
|
53
|
+
"""Calendar period code (e.g., CY2023Q1I)."""
|
|
54
|
+
uom: str
|
|
55
|
+
"""Unit of measure (e.g., USD)."""
|
|
56
|
+
label: str
|
|
57
|
+
"""Concept label."""
|
|
58
|
+
description: str
|
|
59
|
+
"""Concept description."""
|
|
60
|
+
frame_data: list[FrameDataItem]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class FrameResponse(BaseModel):
|
|
64
|
+
pagination: Pagniation
|
|
65
|
+
data: FrameData
|