Skip to main content

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

  • All kline intervals — 1m, 5m, 15m, 1h, 4h, 1d and more
  • Full type safety — Pydantic models with IDE autocomplete
  • Typed data objectsOHLCV and Trade with numpy arrays
  • Async & sync — Both StockAPIs and StockAPIsSync clients
  • CLI — Command-line interface for quick exports
  • Progress tracking — Callbacks for long-running operations
  • Auto-caching — Local disk cache for repeated queries

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: PARTIAL is a success — available data was downloaded. DEFERRED occurs 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 (with interval for klines)
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",
    interval="1m",  # Check specific interval
)
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="1m",
    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

Supported Intervals

All standard kline intervals are supported:

Interval Description
1m 1 minute
3m 3 minutes
5m 5 minutes
15m 15 minutes
30m 30 minutes
1h 1 hour
2h 2 hours
4h 4 hours
6h 6 hours
8h 8 hours
12h 12 hours
1d 1 day
3d 3 days
1w 1 week
1M 1 month

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
    KlineInterval,      # Type alias for intervals
)

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

stockapis-0.1.8.tar.gz (49.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stockapis-0.1.8-py3-none-any.whl (75.1 kB view details)

Uploaded Python 3

File details

Details for the file stockapis-0.1.8.tar.gz.

File metadata

  • Download URL: stockapis-0.1.8.tar.gz
  • Upload date:
  • Size: 49.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.18

File hashes

Hashes for stockapis-0.1.8.tar.gz
Algorithm Hash digest
SHA256 12d5efb3e1f0ec1be83bf6b2cd19e2d40c079d0a596a3ea20afc3ce231e8f248
MD5 c1664641c206159f196e73eb41cf5cc0
BLAKE2b-256 6c2bd66a1a7e56f7c4b70a45a157513d31251be46d59826bd5163ce21c9f510b

See more details on using hashes here.

File details

Details for the file stockapis-0.1.8-py3-none-any.whl.

File metadata

  • Download URL: stockapis-0.1.8-py3-none-any.whl
  • Upload date:
  • Size: 75.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.18

File hashes

Hashes for stockapis-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 fd260096a2ebeb12a52a5443e852504d676b7f90f9428ff4912ec70356014bc3
MD5 6272af2d364dffec9efca30ef8ddd7ae
BLAKE2b-256 5fe07178aae71245778e932c87641eaa221d11f87258793388251018c03e0345

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page