{"id":47734203,"url":"https://github.com/userfrm/thetadatadx","last_synced_at":"2026-05-09T22:22:24.642Z","repository":{"id":346989496,"uuid":"1192403390","full_name":"userFRM/ThetaDataDx","owner":"userFRM","description":"No-JVM ThetaData Terminal — native Rust SDK for direct MDDS (gRPC) and FPSS (TCP) market data access","archived":false,"fork":false,"pushed_at":"2026-04-29T20:56:10.000Z","size":9004,"stargazers_count":11,"open_issues_count":6,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-29T22:34:55.221Z","etag":null,"topics":["async","finance","grpc","historical-data","low-latency","market-data","options","python","real-time","rust","streaming","tcp","thetadata","tick-data","zero-copy","zstd"],"latest_commit_sha":null,"homepage":"https://userfrm.github.io/ThetaDataDx/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/userFRM.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-26T07:18:36.000Z","updated_at":"2026-04-26T21:47:15.000Z","dependencies_parsed_at":"2026-04-06T17:01:09.547Z","dependency_job_id":null,"html_url":"https://github.com/userFRM/ThetaDataDx","commit_stats":null,"previous_names":["userfrm/thetadx"],"tags_count":54,"template":false,"template_full_name":null,"purl":"pkg:github/userFRM/ThetaDataDx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/userFRM%2FThetaDataDx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/userFRM%2FThetaDataDx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/userFRM%2FThetaDataDx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/userFRM%2FThetaDataDx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/userFRM","download_url":"https://codeload.github.com/userFRM/ThetaDataDx/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/userFRM%2FThetaDataDx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32499691,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","finance","grpc","historical-data","low-latency","market-data","options","python","real-time","rust","streaming","tcp","thetadata","tick-data","zero-copy","zstd"],"created_at":"2026-04-02T22:13:58.297Z","updated_at":"2026-05-01T14:02:02.764Z","avatar_url":"https://github.com/userFRM.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ThetaDataDx\n\nRust SDK for ThetaData market data — single Rust core, five language surfaces (Rust, Python, TypeScript, Go, C++).\n\n[![build](https://github.com/userFRM/ThetaDataDx/actions/workflows/ci.yml/badge.svg)](https://github.com/userFRM/ThetaDataDx/actions/workflows/ci.yml)\n[![license](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](./LICENSE)\n[![Crates.io](https://img.shields.io/crates/v/thetadatadx.svg)](https://crates.io/crates/thetadatadx)\n[![PyPI](https://img.shields.io/pypi/v/thetadatadx)](https://pypi.org/project/thetadatadx)\n[![npm](https://img.shields.io/npm/v/thetadatadx)](https://www.npmjs.com/package/thetadatadx)\n[![Docs](https://img.shields.io/docsrs/thetadatadx)](https://docs.rs/thetadatadx)\n[![Discord](https://img.shields.io/badge/Discord-community-5865F2.svg?logo=discord\u0026logoColor=white)](https://discord.thetadata.us/)\n\n`thetadatadx` is a native Rust SDK for [ThetaData](https://thetadata.us) 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, Go, and C++ from a single Rust core. No JVM, no subprocess, no IPC serialization.\n\n\u003e [!IMPORTANT]\n\u003e A valid [ThetaData](https://thetadata.us) subscription is required. The SDK authenticates against ThetaData's Nexus API using your account credentials.\n\n## Highlights\n\n- **Typed everywhere.** 61 ThetaData endpoints exposed as typed methods across all five SDKs; no raw JSON or protobuf on the public surface.\n- **Arrow-backed DataFrames.** Python `to_arrow()` / `to_pandas()` / `to_polars()` pipe through shared Arrow buffers.\n- **SPKI-pinned FPSS TLS.** Public-key pinning on the FPSS streaming handshake.\n- **FIT decoder + SPSC ring buffer** on the FPSS path. Decode cost is measured in the benchmarks under `crates/thetadatadx/benches/`.\n- **Shared FFI layer.** Go, C++, and Node.js go through the same `extern \"C\"` layer; the Python wheel uses PyO3 ABI3 directly.\n- **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](docs/java-parity-checklist.md) and the [vendor flat-file reference](https://http-docs.thetadata.us/operations/get-v2-flat-file-getting-started.html).\n- **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\u003cFlatFileRow\u003e` in memory. Cross-language coverage is tracked under the binding issues; the Rust core is shipped today.\n\n## Quick start\n\n\u003e [!TIP]\n\u003e 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.\n\n### Rust\n\n```toml\n[dependencies]\nthetadatadx = \"8\"\ntokio = { version = \"1\", features = [\"rt-multi-thread\", \"macros\"] }\n```\n\n```rust\nuse thetadatadx::{ThetaDataDx, Credentials, DirectConfig};\n\n#[tokio::main]\nasync fn main() -\u003e Result\u003c(), thetadatadx::Error\u003e {\n    let creds = Credentials::from_file(\"creds.txt\")?;\n    let tdx = ThetaDataDx::connect(\u0026creds, DirectConfig::production()).await?;\n    let eod = tdx.stock_history_eod(\"AAPL\", \"20240101\", \"20240301\").await?;\n    for tick in \u0026eod {\n        println!(\"{}: O={} H={} L={} C={} V={}\",\n            tick.date, tick.open, tick.high, tick.low, tick.close, tick.volume);\n    }\n    Ok(())\n}\n```\n\nOpt into chainable DataFrame ergonomics by enabling the `polars` and/or `arrow` features. Both stay out of the default dep graph:\n\n```toml\n[dependencies]\nthetadatadx = { version = \"8\", features = [\"polars\"] }\n```\n\n```rust\nuse thetadatadx::frames::TicksPolarsExt;\n\nlet eod = tdx.stock_history_eod(\"AAPL\", \"20240101\", \"20240301\").await?;\nlet df = eod.as_slice().to_polars()?;\n```\n\nThe `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.\n\n### Python\n\n```sh\npip install thetadatadx\n```\n\n```python\nfrom thetadatadx import Credentials, Config, ThetaDataDx\n\ntdx = ThetaDataDx(Credentials.from_file(\"creds.txt\"), Config.production())\nfor tick in tdx.stock_history_eod(\"AAPL\", \"20240101\", \"20240301\"):\n    print(f\"{tick.date}: O={tick.open:.2f} H={tick.high:.2f} \"\n          f\"L={tick.low:.2f} C={tick.close:.2f} V={tick.volume}\")\n```\n\n### TypeScript / Node.js\n\n```sh\nnpm install thetadatadx\n```\n\n```typescript\nimport { ThetaDataDx } from 'thetadatadx';\n\nconst tdx = await ThetaDataDx.connectFromFile('creds.txt');\nfor (const t of tdx.stockHistoryEOD('AAPL', '20240101', '20240301')) {\n    console.log(`${t.date}: O=${t.open} H=${t.high} L=${t.low} C=${t.close} V=${t.volume}`);\n}\n```\n\n### Go\n\n```sh\ngo get github.com/userFRM/ThetaDataDx/sdks/go\n```\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    thetadata \"github.com/userFRM/ThetaDataDx/sdks/go\"\n)\n\nfunc main() {\n    tdx, err := thetadata.ConnectFromFile(\"creds.txt\", thetadata.Production())\n    if err != nil { panic(err) }\n    defer tdx.Close()\n    ticks, _ := tdx.StockHistoryEod(\"AAPL\", \"20240101\", \"20240301\")\n    for _, t := range ticks {\n        fmt.Printf(\"%d: O=%.2f H=%.2f L=%.2f C=%.2f V=%d\\n\",\n            t.Date, t.Open, t.High, t.Low, t.Close, t.Volume)\n    }\n}\n```\n\n### C++\n\n```cpp\n#include \u003cthetadx.hpp\u003e\n#include \u003ccstdio\u003e\n\nint main() {\n    auto tdx = thetadatadx::ThetaDataDx::connect_from_file(\"creds.txt\");\n    for (const auto\u0026 t : tdx.stock_history_eod(\"AAPL\", \"20240101\", \"20240301\")) {\n        std::printf(\"%d: O=%.2f H=%.2f L=%.2f C=%.2f V=%lld\\n\",\n            t.date, t.open, t.high, t.low, t.close, (long long)t.volume);\n    }\n}\n```\n\n## Streaming\n\nOne 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.\n\n```rust\nuse thetadatadx::fpss::{FpssData, FpssEvent};\nuse thetadatadx::fpss::protocol::Contract;\n\ntdx.start_streaming(|event: \u0026FpssEvent| {\n    match event {\n        FpssEvent::Data(FpssData::Quote { contract_id, bid, ask, .. }) =\u003e {\n            println!(\"Quote: {contract_id} bid={bid} ask={ask}\");\n        }\n        FpssEvent::Data(FpssData::Trade { contract_id, price, size, .. }) =\u003e {\n            println!(\"Trade: {contract_id} @ {price} x {size}\");\n        }\n        FpssEvent::Data(FpssData::Ohlcvc { contract_id, open, high, low, close, volume, .. }) =\u003e {\n            println!(\"OHLCVC: {contract_id} O={open} H={high} L={low} C={close} V={volume}\");\n        }\n        _ =\u003e {}\n    }\n})?;\n\ntdx.subscribe_quotes(\u0026Contract::stock(\"AAPL\"))?;\ntdx.subscribe_trades(\u0026Contract::stock(\"AAPL\"))?;\n```\n\nAll prices (`bid`, `ask`, `price`, `open`, `high`, `low`, `close`) are `f64`, decoded during parsing.\n\n## API coverage\n\n61 registry/REST endpoints plus 4 SDK-only historical stream variants, FPSS real-time streaming, and a full Black-Scholes Greeks calculator.\n\n| Category | Endpoints | Examples |\n|----------|-----------|----------|\n| Stock | 14 | EOD, OHLC, trades, quotes, snapshots, at-time |\n| Option | 34 | Same as stock + 5 Greeks tiers, open interest, contracts |\n| Index | 9 | EOD, OHLC, price, snapshots |\n| Calendar | 3 | Market open/close, holiday schedule |\n| Interest Rate | 1 | EOD rate history |\n\nAll endpoints return fully typed data in every language. See the [API Reference](docs/api-reference.md) for the complete method list.\n\n**Additional surfaces** (not REST/gRPC endpoints): FPSS real-time streaming (7 subscribe/unsubscribe methods per contract and per firehose type) and a local Greeks calculator (22 Black-Scholes Greeks plus an IV solver, callable individually or batched).\n\n## Architecture\n\n```mermaid\nflowchart TB\n    subgraph core[\"Rust core\"]\n        direction TB\n        thetadatadx[\"\u003cb\u003ethetadatadx\u003c/b\u003e\u003cbr/\u003eauth · MDDS gRPC · FPSS TCP · decode\"]\n        tdbe[\"\u003cb\u003etdbe\u003c/b\u003e\u003cbr/\u003etypes · FIT / FIE codec · Greeks · Price\"]\n        thetadatadx --\u003e tdbe\n    end\n\n    ffi[\"\u003cb\u003effi\u003c/b\u003e\u003cbr/\u003estable C ABI · panic boundary\"]\n    core --\u003e ffi\n\n    core --\u003e|PyO3 / maturin| python[\"Python SDK\u003cbr/\u003e(pyo3 · Arrow)\"]\n    ffi --\u003e|napi-rs| ts[\"TypeScript SDK\u003cbr/\u003e(N-API · BigInt)\"]\n    ffi --\u003e|cgo| go[\"Go SDK\"]\n    ffi --\u003e|extern C| cpp[\"C++ SDK\u003cbr/\u003e(RAII header-only)\"]\n    core --\u003e|tonic| rust[\"Rust consumer\u003cbr/\u003e(direct crate)\"]\n\n    classDef coreStyle fill:#1e3a8a,stroke:#0c1e5c,color:#fff\n    classDef ffiStyle fill:#7c2d12,stroke:#450a0a,color:#fff\n    classDef sdkStyle fill:#14532d,stroke:#052e16,color:#fff\n    class thetadatadx,tdbe coreStyle\n    class ffi ffiStyle\n    class python,ts,go,cpp,rust sdkStyle\n```\n\n| Layer | Crate / package | Purpose |\n|-------|-----------------|---------|\n| Encoding / types | [`crates/tdbe`](crates/tdbe/) | Tick structs, FIT/FIE codecs, Greeks, Price |\n| Core SDK | [`crates/thetadatadx`](crates/thetadatadx/) | MDDS gRPC client, FPSS streaming, auth |\n| C FFI | [`ffi/`](ffi/) | Stable `extern \"C\"` layer consumed by Go, C++, Node.js |\n| Python | [`sdks/python`](sdks/python/) | PyO3 / maturin wheel with Arrow DataFrame adapter |\n| TypeScript | [`sdks/typescript`](sdks/typescript/) | napi-rs prebuilt binary |\n| Go | [`sdks/go`](sdks/go/) | CGo bindings over the FFI layer |\n| C++ | [`sdks/cpp`](sdks/cpp/) | RAII header-only wrapper |\n| CLI | [`tools/cli`](tools/cli/) | `tdx` CLI — every generated historical endpoint from the command line |\n| MCP | [`tools/mcp`](tools/mcp/) | MCP server - gives clients access to every generated historical endpoint plus offline tools over JSON-RPC |\n| Server | [`tools/server`](tools/server/) | REST + WebSocket server exposing the `/v3/*` route surface |\n| Docs | [`docs/`](docs/) | API reference, architecture, Java parity checklist |\n| Website | [`docs-site/`](docs-site/) | VitePress documentation site (deployed to GitHub Pages) |\n| Notebooks | [`notebooks/`](notebooks/) | 7 Jupyter notebooks (101-107) |\n\n## Protocol parity\n\n`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`](docs/java-parity-checklist.md).\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [API Reference](docs/api-reference.md) | All typed methods, streaming builders, generated tick types, and configuration options |\n| [Architecture](docs/architecture.md) | System design, wire protocols, TOML codegen pipeline |\n| [Parity Checklist](docs/java-parity-checklist.md) | Feature-by-feature protocol and endpoint parity notes |\n| [Endpoint Schema](docs/endpoint-schema.md) | TOML codegen format for adding new types/columns |\n| [Proto Maintenance](crates/thetadatadx/proto/MAINTENANCE.md) | Guide for updating proto files |\n| [Changelog](CHANGELOG.md) | Release notes with breaking changes, features, and fixes |\n\n## Contributing\n\nContributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, pre-commit checks, and pull-request process. Community discussion happens on the [ThetaData Discord](https://discord.thetadata.us/).\n\n## License\n\nLicensed under the Apache License, Version 2.0. See [LICENSE](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuserfrm%2Fthetadatadx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuserfrm%2Fthetadatadx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuserfrm%2Fthetadatadx/lists"}