StockAPIS SDK - Python client for cryptocurrency historical data (trades, klines)
Project description
StockAPIs
Fully typed Python SDK for cryptocurrency historical data (trades, klines) from Binance, Bybit, and OKX.
Features
- Full type safety — Pydantic models with IDE autocomplete
- Typed data objects —
OHLCVandTradewith numpy arrays - Async & sync — Both
StockAPIsandStockAPIsSyncclients - CLI — Command-line interface for quick exports
- Progress tracking — Callbacks for long-running operations
Installation
pip install stockapis
Quick Start
Typed OHLCV Data (Recommended)
from stockapis import StockAPIs, Exchange
async with StockAPIs(api_key="your-api-key") as api:
ohlcv = await api.exports.export_to_ohlcv(
symbol="BTCUSDT",
exchange=Exchange.BINANCE,
from_date="2025-01-01",
to_date="2025-01-07",
interval="1h",
)
# Typed access with autocomplete
print(f"Symbol: {ohlcv.symbol}") # str
print(f"Candles: {len(ohlcv)}") # int
print(f"Latest close: {ohlcv.close[-1]}") # numpy float64
print(f"Latest time: {ohlcv.datetime[-1]}") # datetime
print(f"Volatility: {ohlcv.volatility:.2%}") # float (computed)
Sync Client
from stockapis import StockAPIsSync, Exchange
with StockAPIsSync(api_key="your-api-key") as api:
ohlcv = api.exports.export_to_ohlcv(
symbol="BTCUSDT",
exchange=Exchange.BINANCE,
from_date="2025-01-01",
to_date="2025-01-07",
interval="1h",
)
print(f"Loaded {len(ohlcv)} candles")
Type Safety
All API responses are Pydantic models with full type hints:
from stockapis import StockAPIs, Exchange, DataType
async with StockAPIs(api_key="your-key") as api:
# Create a download request
request = await api.downloads.create(
symbol="BTCUSDT",
exchange=Exchange.BINANCE,
data_type=DataType.KLINES,
from_date="2025-01-01",
to_date="2025-01-07",
interval="1m",
)
# DownloadRequest is a Pydantic model - full IDE support
print(request.id) # int
print(request.symbol.symbol) # str (nested SymbolNested model)
print(request.symbol.exchange) # SymbolNestedExchange enum
print(request.from_date) # date
print(request.to_date) # date
print(request.created_at) # datetime
print(request.status) # DownloadRequestStatus enum
print(request.progress_percent) # float
# Access segments (list of typed DownloadSegment)
for segment in request.segments:
print(segment.target_date) # date
print(segment.status) # DownloadSegmentStatus enum
print(segment.records_ingested) # int
print(segment.completed_at) # datetime | None
Response Models
| Model | Description |
|---|---|
DownloadRequest |
Download job with segments |
DownloadSegment |
Individual day segment |
ExportJob |
Export job status |
DataAvailabilityResponse |
Coverage info |
AvailabilityGridResponse |
Monthly grid |
SymbolsWithDataResponse |
Available symbols |
All models have proper types: date, datetime, enums, nested models.
Typed Data Objects
OHLCV (Candlestick Data)
from stockapis import OHLCV
ohlcv = await api.exports.export_to_ohlcv(...)
# Typed numpy arrays
ohlcv.timestamp # NDArray[np.int64] — Unix ms
ohlcv.datetime # list[datetime] — Python datetime
ohlcv.open # NDArray[np.float64]
ohlcv.high # NDArray[np.float64]
ohlcv.low # NDArray[np.float64]
ohlcv.close # NDArray[np.float64]
ohlcv.volume # NDArray[np.float64]
# Metadata
ohlcv.symbol # str
ohlcv.exchange # str
ohlcv.interval # str
# Computed properties
ohlcv.returns # NDArray[np.float64] — log returns
ohlcv.volatility # float — annualized volatility
len(ohlcv) # int — number of candles
Trade Data
from stockapis import Trade
trades = await api.exports.export_to_trades(...)
# Typed numpy arrays
trades.timestamp # NDArray[np.int64]
trades.datetime # list[datetime]
trades.price # NDArray[np.float64]
trades.quantity # NDArray[np.float64]
trades.is_buyer_maker # NDArray[np.bool_]
# Metadata
trades.symbol # str
trades.exchange # str
len(trades) # int — number of trades
Status Handling
SDK properly handles all statuses including partial data availability:
from stockapis import (
DownloadRequestStatus,
SUCCESS_DOWNLOAD_STATUSES,
TERMINAL_REQUEST_STATUSES,
)
# Wait for download
request = await api.downloads.download_and_wait(...)
# Check status with enums
status = DownloadRequestStatus(request.status)
if status in SUCCESS_DOWNLOAD_STATUSES:
# COMPLETED, SKIPPED, or PARTIAL — data is available
print(f"Success: {request.total_records_ingested} records")
elif status == DownloadRequestStatus.DEFERRED:
# Data not yet available from exchange (1-2 day delay)
print("Data will be available tomorrow")
elif status == DownloadRequestStatus.FAILED:
# Check error in segments
for seg in request.segments:
if seg.error_message:
print(f"{seg.target_date}: {seg.error_message}")
Status Reference
Request statuses (DownloadRequestStatus):
| Status | Description |
|---|---|
PENDING |
Not started |
PROCESSING |
In progress |
COMPLETED |
All done |
SKIPPED |
Data already exists |
PARTIAL |
Some completed, some deferred |
DEFERRED |
All segments deferred |
FAILED |
At least one failed |
Note:
PARTIALis a success — available data was downloaded.DEFERREDoccurs when requesting data too close to today (exchanges publish with 1-2 day delay).
Export Methods
To DataFrame (Polars)
df = await api.exports.export_to_dataframe(
symbol="BTCUSDT",
exchange=Exchange.BINANCE,
data_type=DataType.KLINES,
from_date="2025-01-01",
to_date="2025-01-07",
interval="1m",
)
print(f"Loaded {len(df)} rows")
To File
path = await api.exports.export_to_file(
symbol="BTCUSDT",
exchange=Exchange.BINANCE,
data_type=DataType.KLINES,
from_date="2025-01-01",
to_date="2025-01-07",
interval="1m",
output_path="btcusdt.csv",
on_progress=lambda p: print(f"Progress: {p}%"),
)
Download to QuestDB
result = await api.downloads.download_to_questdb(
symbol="BTCUSDT",
exchange=Exchange.BINANCE,
data_type=DataType.TRADES,
from_date="2025-01-01",
to_date="2025-01-31",
)
print(f"Records: {result['total_records']}")
CLI
# Set API key
export STOCKAPIS_API_KEY=your-api-key
# Export klines to file
stockapis export BTCUSDT -e binance --from 2025-01-01 --to 2025-01-07 -i 1m -o data.csv
# Download trades to QuestDB
stockapis download BTCUSDT -e binance --from 2025-01-01 --to 2025-01-31 --type trades
# Check availability
stockapis availability BTCUSDT -e binance --from 2024-01-01 --to 2024-12-31
# List jobs
stockapis list downloads
stockapis list exports
# Check status
stockapis status 123
Low-Level API
For fine-grained control:
# Create request
request = await api.downloads.create(
symbol="BTCUSDT",
exchange=Exchange.BINANCE,
data_type=DataType.TRADES,
from_date="2025-01-01",
to_date="2025-01-07",
)
# Poll progress
async for req in api.downloads.poll_progress(request.id):
print(f"Progress: {req.progress_percent}%")
# Or wait for completion
completed = await api.downloads.wait_for_completion(
request.id,
poll_interval=5.0,
timeout=3600,
)
Check Data Availability
# Range availability
avail = await api.downloads.check_availability(
symbol="BTCUSDT",
exchange=Exchange.BINANCE,
data_type=DataType.KLINES,
from_date="2024-01-01",
to_date="2024-12-31",
)
print(f"Coverage: {avail.coverage_percent}%")
print(f"Missing days: {avail.missing_days}") # list[date]
# Monthly grid
grid = await api.downloads.get_availability_grid(
symbol="BTCUSDT",
exchange=Exchange.BINANCE,
data_type=DataType.KLINES,
interval="1h",
year=2024,
)
for month in grid.months:
print(f"{month.month}/{month.year}: {month.status}")
Configuration
# Production (default)
api = StockAPIs(api_key="sk_live_xxx")
# Development
api = StockAPIs(api_key="demo_stockapis_2024", mode="dev")
# Custom URL
api = StockAPIs(api_key="your-key", base_url="http://custom:9000")
API Keys
| Type | Prefix | Usage |
|---|---|---|
| Demo | demo_ |
Testing |
| Production | sk_ |
Production |
Enums
from stockapis import (
Exchange, # BINANCE, BYBIT, OKX
MarketType, # SPOT, LINEAR, INVERSE
DataType, # KLINES, TRADES
Granularity, # DAILY, MONTHLY
FileFormat, # CSV, PARQUET, JSON
Compression, # NONE, GZIP, ZIP
DownloadStatus, # Segment statuses
DownloadRequestStatus, # Request statuses
ExportJobStatus, # Export statuses
AvailabilityStatus, # COMPLETE, PARTIAL, EMPTY
)
# Kline intervals
KlineInterval = "1m" | "5m" | "15m" | "30m" | "1h" | "4h" | "1d" | ...
Error Handling
import httpx
try:
df = await api.exports.export_to_dataframe(...)
except httpx.HTTPStatusError as e:
print(f"API error {e.response.status_code}")
except ValueError as e:
print(f"Validation error: {e}")
except TimeoutError as e:
print(f"Timeout: {e}")
except ImportError as e:
print(f"Missing polars: {e}")
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file stockapis-0.1.6.tar.gz.
File metadata
- Download URL: stockapis-0.1.6.tar.gz
- Upload date:
- Size: 49.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fef120c754c8a2c96b5096ac979eb214fa1ad5629b0b272e1285944f63e7b8d0
|
|
| MD5 |
bed35bd4c59452386a7e63d811611e78
|
|
| BLAKE2b-256 |
f335ae94b8efa12d3d7166e396c5e40516973ebf31ebcbd896fda0c70ac1594a
|
File details
Details for the file stockapis-0.1.6-py3-none-any.whl.
File metadata
- Download URL: stockapis-0.1.6-py3-none-any.whl
- Upload date:
- Size: 74.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8896c5375d56ca8d822eb1dae26fea4ca2cd03460beb040fe39a6e89a7226612
|
|
| MD5 |
7b7ac7f29b3524873989b404b613e9fc
|
|
| BLAKE2b-256 |
da6e0c03aea33bac369881fbbda81fd4fbb8ad91f66487a40e290c983349d660
|