Skip to content

userFRM/ThetaDataDx

ThetaDataDx

Rust SDK for ThetaData market data — single Rust core, four language surfaces (Rust, Python, TypeScript, C++).

build license Crates.io PyPI npm Docs Discord

thetadatadx is a native Rust SDK for ThetaData market data. It connects directly to ThetaData's three public surfaces — MDDS (historical request/response over gRPC), FPSS (real-time streaming over TCP), and FLATFILES (whole-universe daily blobs over the legacy MDDS port) — decodes ticks in-process, and exposes a typed API across Rust, Python, TypeScript, and C++ from a single Rust core. No JVM, no subprocess, no IPC serialization. Go consumers can build a thin cgo wrapper against the unchanged C ABI in ffi/ — header at sdks/cpp/include/thetadx.h, all FFI types and free fns exported as tdx_* symbols.

Important

A valid ThetaData subscription is required. The SDK authenticates against ThetaData's Nexus API using your account credentials.

Requirements

  • Rust 1.88 or newer. Declared as rust-version = "1.88" on every workspace [package]; the Linux Lint job in CI is pinned to this floor so dependency bumps that raise the rustc requirement surface before release.
  • A valid ThetaData subscription for the live endpoints.

Highlights

  • Typed everywhere. 61 ThetaData endpoints exposed as typed methods across all four SDKs; no raw JSON or protobuf on the public surface.
  • Arrow-backed DataFrames. Python to_arrow() / to_pandas() / to_polars() pipe through shared Arrow buffers.
  • SPKI-pinned FPSS TLS. Public-key pinning on the FPSS streaming handshake.
  • FIT decoder + SPSC ring buffer on the FPSS path. Decode cost is measured in the benchmarks under crates/thetadatadx/benches/.
  • Shared FFI layer. C++ and Node.js go through the same extern "C" layer; the Python wheel uses PyO3 ABI3 directly. The C ABI is also the supported integration path for any third-party Go/C/other-language consumer that wants to roll their own wrapper.
  • Covers all three public surfaces. MDDS gRPC endpoints, FPSS wire format with reconnect semantics, and the FLATFILES daily-blob protocol — every transport speaks directly to ThetaData's production servers from a single client. See the parity checklist and the vendor flat-file reference.
  • FLATFILES daily blobs. Pull whole-universe (sec_type, req_type, date) blobs over the legacy MDDS port; decode to vendor-byte CSV, JSONL, or a typed Vec<FlatFileRow> in memory. Cross-language coverage is tracked under the binding issues; the Rust core is shipped today.

Quick start

Tip

Credentials can be supplied as a creds.txt file (email on line 1, password on line 2), inline via Credentials::new("email", "password"), or through the THETADATA_EMAIL / THETADATA_PASSWORD environment variables.

Rust

[dependencies]
thetadatadx = "8"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
use thetadatadx::{ThetaDataDx, Credentials, DirectConfig};

#[tokio::main]
async fn main() -> Result<(), thetadatadx::Error> {
    let creds = Credentials::from_file("creds.txt")?;
    let tdx = ThetaDataDx::connect(&creds, DirectConfig::production()).await?;
    let eod = tdx.stock_history_eod("AAPL", "20240101", "20240301").await?;
    for tick in &eod {
        println!("{}: O={} H={} L={} C={} V={}",
            tick.date, tick.open, tick.high, tick.low, tick.close, tick.volume);
    }
    Ok(())
}

Opt into chainable DataFrame ergonomics by enabling the polars and/or arrow features. Both stay out of the default dep graph:

[dependencies]
thetadatadx = { version = "8", features = ["polars"] }
use thetadatadx::frames::TicksPolarsExt;

let eod = tdx.stock_history_eod("AAPL", "20240101", "20240301").await?;
let df = eod.as_slice().to_polars()?;

The arrow feature exposes a TicksArrowExt::to_arrow that materialises an arrow_array::RecordBatch with the same schema the Python .to_polars() / .to_arrow() terminal produces. features = ["frames"] pulls both in.

Python

pip install thetadatadx
from thetadatadx import Credentials, Config, ThetaDataDx

tdx = ThetaDataDx(Credentials.from_file("creds.txt"), Config.production())
for tick in tdx.stock_history_eod("AAPL", "20240101", "20240301"):
    print(f"{tick.date}: O={tick.open:.2f} H={tick.high:.2f} "
          f"L={tick.low:.2f} C={tick.close:.2f} V={tick.volume}")

TypeScript / Node.js

npm install thetadatadx
import { ThetaDataDx } from 'thetadatadx';

const tdx = await ThetaDataDx.connectFromFile('creds.txt');
for (const t of tdx.stockHistoryEOD('AAPL', '20240101', '20240301')) {
    console.log(`${t.date}: O=${t.open} H=${t.high} L=${t.low} C=${t.close} V=${t.volume}`);
}

C++

#include <thetadx.hpp>
#include <cstdio>

int main() {
    auto tdx = thetadatadx::ThetaDataDx::connect_from_file("creds.txt");
    for (const auto& t : tdx.stock_history_eod("AAPL", "20240101", "20240301")) {
        std::printf("%d: O=%.2f H=%.2f L=%.2f C=%.2f V=%lld\n",
            t.date, t.open, t.high, t.low, t.close, (long long)t.volume);
    }
}

Streaming

One connection, one auth. Historical queries are available immediately; streaming connects lazily on first subscription. The client auto-reconnects and re-subscribes all active contracts on involuntary disconnect.

use thetadatadx::fpss::{FpssData, FpssEvent};
use thetadatadx::fpss::protocol::Contract;

tdx.start_streaming(|event: &FpssEvent| {
    match event {
        FpssEvent::Data(FpssData::Quote { contract_id, bid, ask, .. }) => {
            println!("Quote: {contract_id} bid={bid} ask={ask}");
        }
        FpssEvent::Data(FpssData::Trade { contract_id, price, size, .. }) => {
            println!("Trade: {contract_id} @ {price} x {size}");
        }
        FpssEvent::Data(FpssData::Ohlcvc { contract_id, open, high, low, close, volume, .. }) => {
            println!("OHLCVC: {contract_id} O={open} H={high} L={low} C={close} V={volume}");
        }
        _ => {}
    }
})?;

tdx.subscribe_quotes(&Contract::stock("AAPL"))?;
tdx.subscribe_trades(&Contract::stock("AAPL"))?;

All prices (bid, ask, price, open, high, low, close) are f64, decoded during parsing.

API coverage

61 registry/REST endpoints plus 4 SDK-only historical stream variants, FPSS real-time streaming, and a full Black-Scholes Greeks calculator.

Category Endpoints Examples
Stock 14 EOD, OHLC, trades, quotes, snapshots, at-time
Option 34 Same as stock + 5 Greeks tiers, open interest, contracts
Index 9 EOD, OHLC, price, snapshots
Calendar 3 Market open/close, holiday schedule
Interest Rate 1 EOD rate history

All endpoints return fully typed data in every language. See the API Reference for the complete method list.

Additional surfaces (not REST/gRPC endpoints): FPSS real-time streaming (7 subscribe/unsubscribe methods per contract and per full-stream type) and a local Greeks calculator (22 Black-Scholes Greeks plus an IV solver, callable individually or batched).

Architecture

flowchart TB
    subgraph core["Rust core"]
        direction TB
        thetadatadx["<b>thetadatadx</b><br/>auth · MDDS gRPC · FPSS TCP · decode"]
        tdbe["<b>tdbe</b><br/>types · FIT / FIE codec · Greeks · Price"]
        thetadatadx --> tdbe
    end

    ffi["<b>ffi</b><br/>stable C ABI · panic boundary"]
    core --> ffi

    core -->|PyO3 / maturin| python["Python SDK<br/>(pyo3 · Arrow)"]
    ffi -->|napi-rs| ts["TypeScript SDK<br/>(N-API · BigInt)"]
    ffi -->|extern C| cpp["C++ SDK<br/>(RAII header-only)"]
    core -->|tonic| rust["Rust consumer<br/>(direct crate)"]

    classDef coreStyle fill:#1e3a8a,stroke:#0c1e5c,color:#fff
    classDef ffiStyle fill:#7c2d12,stroke:#450a0a,color:#fff
    classDef sdkStyle fill:#14532d,stroke:#052e16,color:#fff
    class thetadatadx,tdbe coreStyle
    class ffi ffiStyle
    class python,ts,cpp,rust sdkStyle
Loading
Layer Crate / package Purpose
Encoding / types crates/tdbe Tick structs, FIT/FIE codecs, Greeks, Price
Core SDK crates/thetadatadx MDDS gRPC client, FPSS streaming, auth
C FFI ffi/ Stable extern "C" layer consumed by C++, Node.js, and any third-party C/Go consumer
Python sdks/python PyO3 / maturin wheel with Arrow DataFrame adapter
TypeScript sdks/typescript napi-rs prebuilt binary
C++ sdks/cpp RAII header-only wrapper
CLI tools/cli tdx CLI — every generated historical endpoint from the command line
MCP tools/mcp MCP server - gives clients access to every generated historical endpoint plus offline tools over JSON-RPC
Server tools/server REST + WebSocket server exposing the /v3/* route surface
Docs docs/ API reference, architecture, Java parity checklist
Website docs-site/ VitePress documentation site (deployed to GitHub Pages)
Notebooks notebooks/ 7 Jupyter notebooks (101-107)

Protocol parity

thetadatadx implements the ThetaData MDDS and FPSS wire protocols and covers the terminal endpoint surface. Feature-by-feature parity and intentional deviations are tracked in docs/java-parity-checklist.md.

Documentation

Document Description
API Reference All typed methods, streaming builders, generated tick types, and configuration options
Architecture System design, wire protocols, TOML codegen pipeline
Parity Checklist Feature-by-feature protocol and endpoint parity notes
Endpoint Schema TOML codegen format for adding new types/columns
Proto Maintenance Guide for updating proto files
Changelog Release notes with breaking changes, features, and fixes

Contributing

Contributions are welcome. See CONTRIBUTING.md for development setup, pre-commit checks, and pull-request process. Community discussion happens on the ThetaData Discord.

License

Licensed under the Apache License, Version 2.0. See LICENSE.