Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [8.0.33] - 2026-05-07

### Added

- **Seven Architecture Decision Records** under `docs/architecture/`:
ADR-001 (Java terminal parity sourcing), ADR-002 (FPSS ring power-of-two
capacity), ADR-003 (MDDS `2^tier` concurrent-request mapping), ADR-004
(Eastern-time DST cutover), ADR-005 (OCC-21 century scope, expires
2099-12-31), ADR-006 (FPSS reconnect policy with rate-limit-aware backoff),
ADR-007 (flatfiles MDDS SPKI pin rotation policy).
- **`tdbe::json_canon`** — JSON canonicalisation (non-finite f64 to `null`)
is now a `tdbe` submodule. Existing `json_canon::*` callers in the CLI,
MCP, and server crates migrate to `tdbe::json_canon::*`.

### Changed

- **`ParsedRight::from_wire_byte` is now wired at the four `is_call` /
`is_put` magic-number sites in `crates/tdbe/src/types/tick.rs`.** The
`right == 67` / `right == 80` raw integer comparisons go through the
typed parser; behaviour is identical, the magic numbers are gone.

### Removed

- **`crates/json_canon` workspace member** folded into `tdbe::json_canon`.
External consumers should switch to `tdbe = "0.12.9"` and import
`tdbe::json_canon::{canonicalize, canonicalize_and_serialize, finite_or_null}`.
- **Internal version references in source comments** (`v8.0.10`, `v7.2.0`,
`v8.0.3`, `v8.0.2`, `v6.0.1+`). Semantic content preserved; release
metadata pruned out of code paths where it adds no maintenance value.
- **Banned vocabulary `firehose`** removed from source doc comments,
README.md, and ROADMAP.md. Replaced with `full-stream` / `full-type`.
CHANGELOG history is intentionally untouched.

## [8.0.32] - 2026-05-06

### Fixed
Expand Down
15 changes: 4 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["crates/json_canon", "crates/tdbe", "crates/thetadatadx", "tools/cli", "ffi"]
members = ["crates/tdbe", "crates/thetadatadx", "tools/cli", "ffi"]
exclude = ["sdks/python", "sdks/typescript", "tools/mcp", "tools/server"]
resolver = "2"

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ All prices (`bid`, `ask`, `price`, `open`, `high`, `low`, `close`) are `f64`, de

All endpoints return fully typed data in every language. See the [API Reference](docs/api-reference.md) for the complete method list.

**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).
**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

Expand Down
8 changes: 4 additions & 4 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The SDK exposes three independent ways to consume data:
| Surface | Purpose | Status |
|---------|---------|--------|
| **MDDS** | Request / response history + reference data | Verified |
| **FPSS** | Live streaming firehose (trades, quotes, OI) | Verified |
| **FPSS** | Live streaming full-stream (trades, quotes, OI) | Verified |
| **FLATFILES** | Server-pre-built whole-universe daily blobs delivered over the legacy MDDS auth path | Verified |

Each surface has a separate authentication flow and a separate transport. All three are reachable from the same `ThetaDataDx` client; consumers pick which surface they need on a per-call basis.
Expand Down Expand Up @@ -156,9 +156,9 @@ Server retention window: 7 calendar days. Older history: contact ThetaData sales
| Option quote subscription | Standard | Verified |
| Option trade subscription | Standard | Verified |
| Open interest subscription | Pro | Verified |
| Full trade firehose (Option) | Pro | Verified |
| Full trade firehose (Stock) | Pro | Verified |
| Full OI firehose | Pro | Verified |
| Full trade stream (Option) | Pro | Verified |
| Full trade stream (Stock) | Pro | Verified |
| Full OI stream | Pro | Verified |
| Index price subscription | Indices subscription | Subscription-tier-blocked |
| Dev server replay | — | Verified |
| Reconnection (per-read deadline, Java-parity) | — | Verified |
Expand Down
16 changes: 0 additions & 16 deletions crates/json_canon/Cargo.toml

This file was deleted.

1 change: 1 addition & 0 deletions crates/tdbe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ categories = ["encoding", "finance"]
workspace = true

[dependencies]
sonic-rs = "0.5.8"
thiserror = "2.0.18"

[dev-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion crates/tdbe/benches/bench_tick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use tdbe::types::tick::{OhlcTick, QuoteTick, TradeTick};
// ═══════════════════════════════════════════════════════════════════════════
// Tick operation benchmarks
//
// Post-f64 migration (v6.0.1+): price fields are `f64`, decoded at parse time.
// Post-f64 migration: price fields are `f64`, decoded at parse time.
// These benches measure direct field access and simple arithmetic rather than
// the old helper-method decoding path.
// ═══════════════════════════════════════════════════════════════════════════
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions crates/tdbe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub mod error;
pub mod exchange;
pub mod flags;
pub mod greeks;
pub mod json_canon;
pub mod latency;
pub mod right;
pub mod sequences;
Expand Down
18 changes: 10 additions & 8 deletions crates/tdbe/src/types/tick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,24 @@

include!("tick_generated.rs");

pub use crate::right::ParsedRight;

// ─────────────────────────────────────────────────────────────────────────────
// Contract identification helpers
// ─────────────────────────────────────────────────────────────────────────────

macro_rules! impl_contract_id {
($ty:ident) => {
impl $ty {
/// `true` when `right` == 'C' (ASCII 67).
/// `true` when `right` decodes to `Call` (ASCII `'C'`).
#[inline]
pub fn is_call(&self) -> bool {
self.right == 67
ParsedRight::from_wire_byte(self.right) == Some(ParsedRight::Call)
}
/// `true` when `right` == 'P' (ASCII 80).
/// `true` when `right` decodes to `Put` (ASCII `'P'`).
#[inline]
pub fn is_put(&self) -> bool {
self.right == 80
ParsedRight::from_wire_byte(self.right) == Some(ParsedRight::Put)
}
/// `true` when the server populated contract identification fields.
#[inline]
Expand Down Expand Up @@ -95,15 +97,15 @@ impl TradeTick {
}

impl OptionContract {
/// `true` when `right` == 'C' (ASCII 67).
/// `true` when `right` decodes to `Call` (ASCII `'C'`).
#[inline]
pub fn is_call(&self) -> bool {
self.right == 67
ParsedRight::from_wire_byte(self.right) == Some(ParsedRight::Call)
}
/// `true` when `right` == 'P' (ASCII 80).
/// `true` when `right` decodes to `Put` (ASCII `'P'`).
#[inline]
pub fn is_put(&self) -> bool {
self.right == 80
ParsedRight::from_wire_byte(self.right) == Some(ParsedRight::Put)
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/thetadatadx/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "thetadatadx"
version = "8.0.32"
version = "8.0.33"
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
Expand Down
6 changes: 3 additions & 3 deletions crates/thetadatadx/build_support/endpoints/render/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//!
//! # Three variants per endpoint (sync / async / fluent builder)
//!
//! The v8.0.2 Python-UX surface exposes every historical endpoint in three
//! The Python-UX surface exposes every historical endpoint in three
//! forms without duplicating the spec:
//!
//! 1. **Sync `fn name(...)`** — original blocking signature; every kwarg is
Expand Down Expand Up @@ -204,7 +204,7 @@ pub(super) fn render_python_historical_methods(endpoints: &[GeneratedEndpoint])
.iter()
.filter(|endpoint| !is_streaming_endpoint(endpoint))
{
// Sync — preserves the pre-v8.0.2 signature byte-for-byte.
// Sync — preserves the original blocking signature byte-for-byte.
out.push_str(&render_python_endpoint_sync(endpoint));
out.push('\n');
// Async — awaitable via pyo3-async-runtimes.
Expand All @@ -218,7 +218,7 @@ pub(super) fn render_python_historical_methods(endpoints: &[GeneratedEndpoint])
out
}

// ───────────────────────── Sync (pre-v8.0.2 signature) ─────────────────────
// ───────────────────────── Sync (original blocking signature) ─────────────

fn render_python_endpoint_sync(endpoint: &GeneratedEndpoint) -> String {
let method_params = method_params(endpoint);
Expand Down
6 changes: 3 additions & 3 deletions crates/thetadatadx/build_support/ticks/python_arrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ pub(super) fn render_python_tick_arrow(schema: &Schema) -> String {

// Schema map + slice-to-Arrow converters. The pyclass-list dispatcher
// and the `ArrowFromPyclassList` trait that used to live here have
// been removed along with every free-function DataFrame surface in
// v8.0.3 — the chained `<TickName>List` terminals are the sole path
// from decoded ticks to DataFrame output.
// been removed along with every free-function DataFrame surface — the
// chained `<TickName>List` terminals are the sole path from decoded
// ticks to DataFrame output.
out.push_str(&render_python_arrow_schema_map(schema));
out.push('\n');
out.push_str(&render_record_batch_to_pyarrow_helper());
Expand Down
2 changes: 1 addition & 1 deletion crates/thetadatadx/src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1731,7 +1731,7 @@ mod tests {

#[test]
fn parse_greeks_all_ticks_decodes_price_encoded_greeks() {
// Regression: v7.2.0 strict decode rejected Price cells for Greek
// Regression: an earlier strict decode rejected Price cells for Greek
// columns, but the v3 MDDS server sends Greeks as Price-encoded
// values (mirroring Java's `dataValue2Object` -> BigDecimal path).
// Live run #24520486541 on main surfaced this as
Expand Down
4 changes: 2 additions & 2 deletions crates/thetadatadx/src/fpss/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ pub struct FpssClient {
next_req_id: AtomicI32,
/// Active per-contract subscriptions for reconnection.
pub(in crate::fpss) active_subs: Arc<Mutex<Vec<(SubscriptionKind, Contract)>>>,
/// Active full-type (firehose) subscriptions for reconnection.
/// Active full-type (full-stream) subscriptions for reconnection.
pub(in crate::fpss) active_full_subs:
Arc<Mutex<Vec<(SubscriptionKind, tdbe::types::enums::SecType)>>>,
/// Server-assigned contract ID mapping.
Expand Down Expand Up @@ -774,7 +774,7 @@ impl FpssClient {
.clone()
}

/// Get a snapshot of currently active full-type (firehose) subscriptions.
/// Get a snapshot of currently active full-type (full-stream) subscriptions.
pub fn active_full_subscriptions(
&self,
) -> Vec<(SubscriptionKind, tdbe::types::enums::SecType)> {
Expand Down
6 changes: 3 additions & 3 deletions crates/thetadatadx/src/unified.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,15 +337,15 @@ impl ThetaDataDx {
self.with_streaming(|s| s.subscribe_all(contract))
}

/// Subscribe to all trades for a security type (firehose).
/// Subscribe to all trades for a security type (full-stream).
/// # Errors
///
/// Returns an error on network, authentication, or parsing failure.
pub fn subscribe_full_trades(&self, sec_type: SecType) -> Result<(), Error> {
self.with_streaming(|s| s.subscribe_full_trades(sec_type))
}

/// Subscribe to all open interest for a security type (firehose).
/// Subscribe to all open interest for a security type (full-stream).
/// # Errors
///
/// Returns an error on network, authentication, or parsing failure.
Expand Down Expand Up @@ -424,7 +424,7 @@ impl ThetaDataDx {
self.with_streaming(|s| Ok(s.active_subscriptions()))
}

/// Get all active full-type (firehose) subscriptions.
/// Get all active full-type (full-stream) subscriptions.
/// # Errors
///
/// Returns an error on network, authentication, or parsing failure.
Expand Down
4 changes: 2 additions & 2 deletions crates/thetadatadx/src/wire_semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
//! `#[path]` reuse of this file)

// The `venue=nqb` default used to live here as a runtime constant applied
// at query-assembly time. In v8.0.10 the default moved into the SSOT
// at query-assembly time. The default now lives in the SSOT
// (`endpoint_surface.toml` -> `stock_venue_filter.default = "nqb"`) so it
// flows through every emitted SDK builder uniformly. `modes.rs` now reads
// flows through every emitted SDK builder uniformly. `modes.rs` reads
// `param.default` directly; no runtime bridge needed.

/// Canonicalize the `expiration` parameter for the MDDS server.
Expand Down
33 changes: 33 additions & 0 deletions docs-site/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [8.0.33] - 2026-05-07

### Added

- **Seven Architecture Decision Records** under `docs/architecture/`:
ADR-001 (Java terminal parity sourcing), ADR-002 (FPSS ring power-of-two
capacity), ADR-003 (MDDS `2^tier` concurrent-request mapping), ADR-004
(Eastern-time DST cutover), ADR-005 (OCC-21 century scope, expires
2099-12-31), ADR-006 (FPSS reconnect policy with rate-limit-aware backoff),
ADR-007 (flatfiles MDDS SPKI pin rotation policy).
- **`tdbe::json_canon`** — JSON canonicalisation (non-finite f64 to `null`)
is now a `tdbe` submodule. Existing `json_canon::*` callers in the CLI,
MCP, and server crates migrate to `tdbe::json_canon::*`.

### Changed

- **`ParsedRight::from_wire_byte` is now wired at the four `is_call` /
`is_put` magic-number sites in `crates/tdbe/src/types/tick.rs`.** The
`right == 67` / `right == 80` raw integer comparisons go through the
typed parser; behaviour is identical, the magic numbers are gone.

### Removed

- **`crates/json_canon` workspace member** folded into `tdbe::json_canon`.
External consumers should switch to `tdbe = "0.12.9"` and import
`tdbe::json_canon::{canonicalize, canonicalize_and_serialize, finite_or_null}`.
- **Internal version references in source comments** (`v8.0.10`, `v7.2.0`,
`v8.0.3`, `v8.0.2`, `v6.0.1+`). Semantic content preserved; release
metadata pruned out of code paths where it adds no maintenance value.
- **Banned vocabulary `firehose`** removed from source doc comments,
README.md, and ROADMAP.md. Replaced with `full-stream` / `full-type`.
CHANGELOG history is intentionally untouched.

## [8.0.32] - 2026-05-06

### Fixed
Expand Down
Loading
Loading