marketstack-python-client 1.0.0__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.
- marketstack_python_client-1.0.0/LICENSE +21 -0
- marketstack_python_client-1.0.0/MANIFEST.in +4 -0
- marketstack_python_client-1.0.0/PKG-INFO +182 -0
- marketstack_python_client-1.0.0/README.md +171 -0
- marketstack_python_client-1.0.0/marketstack/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/client/__init__.py +0 -0
- marketstack_python_client-1.0.0/marketstack/client/http.py +36 -0
- marketstack_python_client-1.0.0/marketstack/client/marketstack.py +148 -0
- marketstack_python_client-1.0.0/marketstack/models/__init__.py +0 -0
- marketstack_python_client-1.0.0/marketstack/models/bond.py +47 -0
- marketstack_python_client-1.0.0/marketstack/models/cik_code.py +26 -0
- marketstack_python_client-1.0.0/marketstack/models/commodity.py +83 -0
- marketstack_python_client-1.0.0/marketstack/models/company.py +278 -0
- marketstack_python_client-1.0.0/marketstack/models/concept.py +65 -0
- marketstack_python_client-1.0.0/marketstack/models/currency.py +23 -0
- marketstack_python_client-1.0.0/marketstack/models/dividend.py +27 -0
- marketstack_python_client-1.0.0/marketstack/models/eod.py +48 -0
- marketstack_python_client-1.0.0/marketstack/models/etf.py +129 -0
- marketstack_python_client-1.0.0/marketstack/models/exchange.py +117 -0
- marketstack_python_client-1.0.0/marketstack/models/index.py +47 -0
- marketstack_python_client-1.0.0/marketstack/models/intraday.py +43 -0
- marketstack_python_client-1.0.0/marketstack/models/pagination.py +42 -0
- marketstack_python_client-1.0.0/marketstack/models/split.py +24 -0
- marketstack_python_client-1.0.0/marketstack/models/stockprice.py +31 -0
- marketstack_python_client-1.0.0/marketstack/models/ticker.py +159 -0
- marketstack_python_client-1.0.0/marketstack/models/ticker_info.py +197 -0
- marketstack_python_client-1.0.0/marketstack/models/timezone.py +21 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/__init__.py +0 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/bond/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/bond/bond.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/bondlist/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/bondlist/bondlist.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/cikcode/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/cikcode/cikcode.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/commodities/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/commodities/commodities.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/commoditieshistory/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/commoditieshistory/commoditieshistory.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/company_facts/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/company_facts/company_facts.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/companyname/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/companyname/companyname.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/companyratings/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/companyratings/companyratings.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/concept/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/concept/concept.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/currencies/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/currencies/currencies.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/dividends/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/dividends/dividends.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/eod/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/eod/eod.py +20 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/etfholdings/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/etfholdings/etfholdings.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/etflist/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/etflist/etflist.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/exchanges/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/exchanges/exchanges.py +109 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/frames/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/frames/frames.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/indexinfo/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/indexinfo/indexinfo.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/indexlist/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/indexlist/indexlist.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/intraday/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/intraday/intraday.py +20 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/splits/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/splits/splits.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/stockprice/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/stockprice/stockprice.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/submissions/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/submissions/submissions.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/tickerinfo/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/tickerinfo/tickerinfo.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/tickers/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/tickers/tickers.py +150 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/tickerslist/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/tickerslist/tickerslist.py +12 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/timezones/__init__.py +1 -0
- marketstack_python_client-1.0.0/marketstack/namespaces/timezones/timezones.py +12 -0
- marketstack_python_client-1.0.0/marketstack_python_client.egg-info/PKG-INFO +182 -0
- marketstack_python_client-1.0.0/marketstack_python_client.egg-info/SOURCES.txt +87 -0
- marketstack_python_client-1.0.0/marketstack_python_client.egg-info/dependency_links.txt +1 -0
- marketstack_python_client-1.0.0/marketstack_python_client.egg-info/requires.txt +2 -0
- marketstack_python_client-1.0.0/marketstack_python_client.egg-info/top_level.txt +1 -0
- marketstack_python_client-1.0.0/openapi.yaml +5669 -0
- marketstack_python_client-1.0.0/pyproject.toml +35 -0
- marketstack_python_client-1.0.0/setup.cfg +4 -0
- marketstack_python_client-1.0.0/tests/test_integration.py +213 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 01Joseph-Hwang10
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: marketstack-python-client
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A Python client for the Marketstack API.
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: httpx>=0.28.1
|
|
9
|
+
Requires-Dist: pydantic>=2.13.4
|
|
10
|
+
Dynamic: license-file
|
|
11
|
+
|
|
12
|
+
# Marketstack Python Client
|
|
13
|
+
|
|
14
|
+
A modern, fully-typed Python client for the [Marketstack API (v2)](https://marketstack.com/). Built on top of `httpx` and `pydantic`, this client offers high performance, strict type validation, and an elegant fluent API interface.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- **Modern Python Support:** Optimized for Python `>= 3.10`.
|
|
21
|
+
- **Fully Typed Requests & Responses:** Leverages Pydantic v2 and PEP 692 `Unpack` for complete autocomplete, editor hints, and runtime validation.
|
|
22
|
+
- **Fluent & Hierarchical API:** Easily access nested endpoints (e.g., `client.tickers("AAPL").eod.list()`).
|
|
23
|
+
- **Comprehensive Coverage:** Supports 25+ namespaces covering end-of-day (EOD) data, intraday, tickers, stock exchanges, stock splits, dividends, ETFs, indices, currencies, bonds, commodities, company fundamentals, and more.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
Install the package via `pip`:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install marketstack-python-client
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or using `uv`:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
uv add marketstack-python-client
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
To use the client, you will need a Marketstack API key. Get one by registering at [marketstack.com](https://marketstack.com/).
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
import os
|
|
49
|
+
from marketstack import Marketstack
|
|
50
|
+
|
|
51
|
+
# Initialize the client with your access key
|
|
52
|
+
client = Marketstack(api_key=os.environ["MARKETSTACK_API_KEY"])
|
|
53
|
+
|
|
54
|
+
# 1. Fetch generic End-of-Day (EOD) stock data
|
|
55
|
+
eod_data = client.eod.list(symbols="AAPL,MSFT")
|
|
56
|
+
for bar in eod_data.data:
|
|
57
|
+
print(f"{bar.symbol} closed at {bar.close} on {bar.date}")
|
|
58
|
+
|
|
59
|
+
# 2. Access Ticker-specific data using the fluent API
|
|
60
|
+
aapl_ticker = client.tickers("AAPL").get()
|
|
61
|
+
print(f"Name: {aapl_ticker.name}, Stock Exchange: {aapl_ticker.stock_exchange.name}")
|
|
62
|
+
|
|
63
|
+
# Fetch EOD prices specifically for AAPL
|
|
64
|
+
aapl_eod = client.tickers("AAPL").eod.list(limit=10)
|
|
65
|
+
for bar in aapl_eod.data:
|
|
66
|
+
print(f"AAPL Close: {bar.close}")
|
|
67
|
+
|
|
68
|
+
# 3. Access Stock Exchange specific tickers and EOD data
|
|
69
|
+
nasdaq_eod = client.exchanges("XNAS").eod.list(symbols="AAPL", limit=5)
|
|
70
|
+
print(f"Fetched {len(nasdaq_eod.data)} records from NASDAQ")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Client Namespaces & API Coverage
|
|
76
|
+
|
|
77
|
+
The `Marketstack` client provides dedicated namespaces mapping to the various endpoints of the Marketstack API.
|
|
78
|
+
|
|
79
|
+
### 1. Tickers (Fluent API)
|
|
80
|
+
Interact with a specific ticker symbol.
|
|
81
|
+
```python
|
|
82
|
+
ticker = client.tickers("AAPL")
|
|
83
|
+
|
|
84
|
+
ticker.get() # Basic ticker information
|
|
85
|
+
ticker.eod.list() # End-of-Day historical data
|
|
86
|
+
ticker.eod.latest() # Latest End-of-Day bar
|
|
87
|
+
ticker.eod.for_a_date("2023-10-27") # End-of-Day bar for a specific date
|
|
88
|
+
ticker.intraday.list() # Intraday / Real-time data
|
|
89
|
+
ticker.intraday.latest() # Latest intraday data
|
|
90
|
+
ticker.intraday.for_a_date("2023-10-27")
|
|
91
|
+
ticker.splits.list() # Split history
|
|
92
|
+
ticker.dividends.list() # Dividend history
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 2. Stock Exchanges (Fluent API)
|
|
96
|
+
Interact with stock exchanges.
|
|
97
|
+
```python
|
|
98
|
+
exchange = client.exchanges("XNAS")
|
|
99
|
+
|
|
100
|
+
exchange.get() # Basic exchange info
|
|
101
|
+
exchange.tickers.list() # All tickers listed on this exchange
|
|
102
|
+
exchange.eod.list(symbols="AAPL") # EOD data for a ticker on this exchange
|
|
103
|
+
exchange.intraday.list(symbols="AAPL") # Intraday data for a ticker on this exchange
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 3. End-of-Day (EOD) & Intraday Market Data
|
|
107
|
+
Retrieve general EOD and Intraday datasets.
|
|
108
|
+
```python
|
|
109
|
+
# General EOD endpoints
|
|
110
|
+
client.eod.list(symbols="AAPL", date_from="2023-01-01")
|
|
111
|
+
client.eod.latest(symbols="AAPL")
|
|
112
|
+
client.eod.for_a_date(date="2023-10-27", symbols="AAPL")
|
|
113
|
+
|
|
114
|
+
# General Intraday endpoints
|
|
115
|
+
client.intraday.list(symbols="AAPL")
|
|
116
|
+
client.intraday.latest(symbols="AAPL")
|
|
117
|
+
client.intraday.for_a_date(date="2023-10-27", symbols="AAPL")
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 4. Other Specialized Namespaces
|
|
121
|
+
The client supports many other endpoints depending on your Marketstack subscription tier:
|
|
122
|
+
|
|
123
|
+
- **Dividends & Splits:**
|
|
124
|
+
- `client.dividends.list(symbols="AAPL")`
|
|
125
|
+
- `client.splits.list(symbols="AAPL")`
|
|
126
|
+
- **Currencies & Timezones:**
|
|
127
|
+
- `client.currencies.list()`
|
|
128
|
+
- `client.timezones.list()`
|
|
129
|
+
- **Bonds & Index Info:**
|
|
130
|
+
- `client.bondlist.list(country="US")`
|
|
131
|
+
- `client.bond.get(country="US")`
|
|
132
|
+
- `client.indexlist.list()`
|
|
133
|
+
- `client.indexinfo.get(index="SPX")`
|
|
134
|
+
- **ETFs:**
|
|
135
|
+
- `client.etflist.list(ticker="SPY")`
|
|
136
|
+
- `client.etfholdings.get(ticker="PRSVX")`
|
|
137
|
+
- **Company Fundamentals (Requires Enterprise/Tier Plan):**
|
|
138
|
+
- `client.company_facts.get(cik_code="0000320193")`
|
|
139
|
+
- `client.companyname.get(cik_code="0000320193")`
|
|
140
|
+
- `client.companyratings.get(ticker="AAPL")`
|
|
141
|
+
- `client.concept.get_accounts_payable(cik_code="0000320193")`
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Development
|
|
146
|
+
|
|
147
|
+
We use `uv` for dependency management and workspace workflows.
|
|
148
|
+
|
|
149
|
+
### Prerequisites
|
|
150
|
+
|
|
151
|
+
- Python 3.10 or higher
|
|
152
|
+
- `uv` package manager
|
|
153
|
+
|
|
154
|
+
### Setup
|
|
155
|
+
|
|
156
|
+
Clone the repository and install the dependencies:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
uv sync
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Running Tests
|
|
163
|
+
|
|
164
|
+
This project uses `pytest` for unit and integration testing.
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
# Run all unit tests
|
|
168
|
+
uv run pytest -v
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
To run the integration tests against the live Marketstack API, make sure to set the `MARKETSTACK_API_KEY` environment variable in your `.env` or current session. Note that some tests require higher-tier plans and are marked to be skipped if your API key lacks access.
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
export MARKETSTACK_API_KEY="your_api_key_here"
|
|
175
|
+
uv run pytest tests/test_integration.py
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## License
|
|
181
|
+
|
|
182
|
+
This project is licensed under the MIT License. See individual files or package settings for more details.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Marketstack Python Client
|
|
2
|
+
|
|
3
|
+
A modern, fully-typed Python client for the [Marketstack API (v2)](https://marketstack.com/). Built on top of `httpx` and `pydantic`, this client offers high performance, strict type validation, and an elegant fluent API interface.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Modern Python Support:** Optimized for Python `>= 3.10`.
|
|
10
|
+
- **Fully Typed Requests & Responses:** Leverages Pydantic v2 and PEP 692 `Unpack` for complete autocomplete, editor hints, and runtime validation.
|
|
11
|
+
- **Fluent & Hierarchical API:** Easily access nested endpoints (e.g., `client.tickers("AAPL").eod.list()`).
|
|
12
|
+
- **Comprehensive Coverage:** Supports 25+ namespaces covering end-of-day (EOD) data, intraday, tickers, stock exchanges, stock splits, dividends, ETFs, indices, currencies, bonds, commodities, company fundamentals, and more.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
Install the package via `pip`:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install marketstack-python-client
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or using `uv`:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv add marketstack-python-client
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
To use the client, you will need a Marketstack API key. Get one by registering at [marketstack.com](https://marketstack.com/).
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
import os
|
|
38
|
+
from marketstack import Marketstack
|
|
39
|
+
|
|
40
|
+
# Initialize the client with your access key
|
|
41
|
+
client = Marketstack(api_key=os.environ["MARKETSTACK_API_KEY"])
|
|
42
|
+
|
|
43
|
+
# 1. Fetch generic End-of-Day (EOD) stock data
|
|
44
|
+
eod_data = client.eod.list(symbols="AAPL,MSFT")
|
|
45
|
+
for bar in eod_data.data:
|
|
46
|
+
print(f"{bar.symbol} closed at {bar.close} on {bar.date}")
|
|
47
|
+
|
|
48
|
+
# 2. Access Ticker-specific data using the fluent API
|
|
49
|
+
aapl_ticker = client.tickers("AAPL").get()
|
|
50
|
+
print(f"Name: {aapl_ticker.name}, Stock Exchange: {aapl_ticker.stock_exchange.name}")
|
|
51
|
+
|
|
52
|
+
# Fetch EOD prices specifically for AAPL
|
|
53
|
+
aapl_eod = client.tickers("AAPL").eod.list(limit=10)
|
|
54
|
+
for bar in aapl_eod.data:
|
|
55
|
+
print(f"AAPL Close: {bar.close}")
|
|
56
|
+
|
|
57
|
+
# 3. Access Stock Exchange specific tickers and EOD data
|
|
58
|
+
nasdaq_eod = client.exchanges("XNAS").eod.list(symbols="AAPL", limit=5)
|
|
59
|
+
print(f"Fetched {len(nasdaq_eod.data)} records from NASDAQ")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Client Namespaces & API Coverage
|
|
65
|
+
|
|
66
|
+
The `Marketstack` client provides dedicated namespaces mapping to the various endpoints of the Marketstack API.
|
|
67
|
+
|
|
68
|
+
### 1. Tickers (Fluent API)
|
|
69
|
+
Interact with a specific ticker symbol.
|
|
70
|
+
```python
|
|
71
|
+
ticker = client.tickers("AAPL")
|
|
72
|
+
|
|
73
|
+
ticker.get() # Basic ticker information
|
|
74
|
+
ticker.eod.list() # End-of-Day historical data
|
|
75
|
+
ticker.eod.latest() # Latest End-of-Day bar
|
|
76
|
+
ticker.eod.for_a_date("2023-10-27") # End-of-Day bar for a specific date
|
|
77
|
+
ticker.intraday.list() # Intraday / Real-time data
|
|
78
|
+
ticker.intraday.latest() # Latest intraday data
|
|
79
|
+
ticker.intraday.for_a_date("2023-10-27")
|
|
80
|
+
ticker.splits.list() # Split history
|
|
81
|
+
ticker.dividends.list() # Dividend history
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 2. Stock Exchanges (Fluent API)
|
|
85
|
+
Interact with stock exchanges.
|
|
86
|
+
```python
|
|
87
|
+
exchange = client.exchanges("XNAS")
|
|
88
|
+
|
|
89
|
+
exchange.get() # Basic exchange info
|
|
90
|
+
exchange.tickers.list() # All tickers listed on this exchange
|
|
91
|
+
exchange.eod.list(symbols="AAPL") # EOD data for a ticker on this exchange
|
|
92
|
+
exchange.intraday.list(symbols="AAPL") # Intraday data for a ticker on this exchange
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 3. End-of-Day (EOD) & Intraday Market Data
|
|
96
|
+
Retrieve general EOD and Intraday datasets.
|
|
97
|
+
```python
|
|
98
|
+
# General EOD endpoints
|
|
99
|
+
client.eod.list(symbols="AAPL", date_from="2023-01-01")
|
|
100
|
+
client.eod.latest(symbols="AAPL")
|
|
101
|
+
client.eod.for_a_date(date="2023-10-27", symbols="AAPL")
|
|
102
|
+
|
|
103
|
+
# General Intraday endpoints
|
|
104
|
+
client.intraday.list(symbols="AAPL")
|
|
105
|
+
client.intraday.latest(symbols="AAPL")
|
|
106
|
+
client.intraday.for_a_date(date="2023-10-27", symbols="AAPL")
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 4. Other Specialized Namespaces
|
|
110
|
+
The client supports many other endpoints depending on your Marketstack subscription tier:
|
|
111
|
+
|
|
112
|
+
- **Dividends & Splits:**
|
|
113
|
+
- `client.dividends.list(symbols="AAPL")`
|
|
114
|
+
- `client.splits.list(symbols="AAPL")`
|
|
115
|
+
- **Currencies & Timezones:**
|
|
116
|
+
- `client.currencies.list()`
|
|
117
|
+
- `client.timezones.list()`
|
|
118
|
+
- **Bonds & Index Info:**
|
|
119
|
+
- `client.bondlist.list(country="US")`
|
|
120
|
+
- `client.bond.get(country="US")`
|
|
121
|
+
- `client.indexlist.list()`
|
|
122
|
+
- `client.indexinfo.get(index="SPX")`
|
|
123
|
+
- **ETFs:**
|
|
124
|
+
- `client.etflist.list(ticker="SPY")`
|
|
125
|
+
- `client.etfholdings.get(ticker="PRSVX")`
|
|
126
|
+
- **Company Fundamentals (Requires Enterprise/Tier Plan):**
|
|
127
|
+
- `client.company_facts.get(cik_code="0000320193")`
|
|
128
|
+
- `client.companyname.get(cik_code="0000320193")`
|
|
129
|
+
- `client.companyratings.get(ticker="AAPL")`
|
|
130
|
+
- `client.concept.get_accounts_payable(cik_code="0000320193")`
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Development
|
|
135
|
+
|
|
136
|
+
We use `uv` for dependency management and workspace workflows.
|
|
137
|
+
|
|
138
|
+
### Prerequisites
|
|
139
|
+
|
|
140
|
+
- Python 3.10 or higher
|
|
141
|
+
- `uv` package manager
|
|
142
|
+
|
|
143
|
+
### Setup
|
|
144
|
+
|
|
145
|
+
Clone the repository and install the dependencies:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
uv sync
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Running Tests
|
|
152
|
+
|
|
153
|
+
This project uses `pytest` for unit and integration testing.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Run all unit tests
|
|
157
|
+
uv run pytest -v
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
To run the integration tests against the live Marketstack API, make sure to set the `MARKETSTACK_API_KEY` environment variable in your `.env` or current session. Note that some tests require higher-tier plans and are marked to be skipped if your API key lacks access.
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
export MARKETSTACK_API_KEY="your_api_key_here"
|
|
164
|
+
uv run pytest tests/test_integration.py
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
This project is licensed under the MIT License. See individual files or package settings for more details.
|
|
@@ -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"]
|