Skip to content

Commit 6ed69ce

Browse files
userFRMclaude
andauthored
fix: correct documentation examples and align config template with code defaults (#824)
Several documented examples used call shapes that do not compile or run against the real surface: the Python OHLC example passed `interval` positionally though it is keyword-only, the concurrent-requests article reached for a `historical` view that the async client does not expose, the bulk-backfill Rust sample treated `historical` as a field rather than a method, and the CLI EOD-Greeks example listed positional arguments out of registry order. Each is fixed to the verified signature. The shipped `config.default.toml` wrote three tuning values that overrode the production defaults the moment a client copied the template, because the loader only backfills absent keys: read timeout, client ping interval, and the initial reconnect wait now match `DirectConfig::production()` exactly (3000 ms, 250 ms, 250 ms). A new `config_default_toml_matches_production_defaults` test pins every parsed value to the in-code defaults so the template can never silently drift again. Endpoint counts in the top-level and per-SDK READMEs are recounted from `endpoint_surface.toml`: 65 typed endpoints total (16 stock, 36 option, 9 index, 3 calendar, 1 interest rate). The unsourceable Greeks count is replaced with an accurate first- through third-order phrasing, the TypeScript "method on Client" sentence is corrected to `client.historical`, and the crate streaming example uses the real `.streaming.hosts` field. The Python streaming docs gain a feed-health snippet using the observability getters, and the OHLC interval examples standardize on the duration-string form across Python and TypeScript. The TypeScript doc-example extractor only matched column-0 fences, so it never saw the fenced blocks inside JSDoc comments and validated zero examples. It now strips the JSDoc gutter, scans the README as well, groups narrative blocks into compilable units, and type-checks each through `tsc --noEmit`. Co-authored-by: Claude <noreply@anthropic.com>
1 parent de6b44f commit 6ed69ce

15 files changed

Lines changed: 333 additions & 83 deletions

File tree

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ThetaDataDx
22

3-
High-performance market-data SDKs for [ThetaData](https://thetadata.us), in **Python, TypeScript, C++, and Rust** — one Rust engine under all four. Pull US stock, option, index, and rate data three ways: point-in-time **history**, real-time **streaming**, and whole-universe **flat files**, all from a single authenticated client. Connects straight to ThetaData — no Java terminal, no JVM.
3+
High-performance market-data SDKs for [ThetaData](https://thetadata.us), in **Python, TypeScript, C++, and Rust** — one Rust engine under all four. Pull US stock, option, index, and rate data three ways: point-in-time **history**, real-time **streaming**, and whole-universe **flat files**, all from a single authenticated client. Connects straight to ThetaData — nothing to install and run locally.
44

55
[![Rust CI](https://github.com/userFRM/ThetaDataDx/actions/workflows/ci.yml/badge.svg)](https://github.com/userFRM/ThetaDataDx/actions/workflows/ci.yml)
66
[![Python SDK](https://github.com/userFRM/ThetaDataDx/actions/workflows/python.yml/badge.svg)](https://github.com/userFRM/ThetaDataDx/actions/workflows/python.yml)
@@ -25,10 +25,10 @@ High-performance market-data SDKs for [ThetaData](https://thetadata.us), in **Py
2525
2626
## Features
2727

28-
- **Complete coverage** — stocks, options, indices, and rates across 61 typed endpoints.
28+
- **Complete coverage** — stocks, options, indices, and rates across 65 typed endpoints.
2929
- **Three access modes, one client** — point-in-time history, real-time streaming, and bulk flat-file downloads.
3030
- **DataFrames built in** — every result chains straight to Polars, pandas, or Arrow over a zero-copy boundary.
31-
- **Greeks without a round-trip**23 Black-Scholes Greeks and an implied-volatility solver, computed locally.
31+
- **Greeks without a round-trip**first- through third-order Black-Scholes Greeks and an implied-volatility solver, computed locally.
3232
- **The same surface in every language** — identical methods and identical typed errors, Python through Rust.
3333
- **No terminal to run** — a direct connection to ThetaData; nothing to install and babysit locally.
3434

@@ -224,13 +224,13 @@ with client.streaming(on_event) as session:
224224
225225
## Endpoint coverage
226226

227-
61 typed endpoints across stocks, options, indices, the market calendar, and
227+
65 typed endpoints across stocks, options, indices, the market calendar, and
228228
interest rates, plus real-time streaming and a local Greeks calculator.
229229

230230
| Category | Endpoints | Examples |
231231
|---|---|---|
232-
| Stock | 14 | EOD, OHLC, trades, quotes, snapshots, at-time |
233-
| Option | 34 | Every stock surface plus five Greeks tiers, open interest, contract lists |
232+
| Stock | 16 | EOD, OHLC, trades, quotes, snapshots, at-time |
233+
| Option | 36 | Every stock surface plus five Greeks tiers, open interest, contract lists |
234234
| Index | 9 | EOD, OHLC, price, snapshots |
235235
| Calendar | 3 | Market open/close, holidays, early closes |
236236
| Interest rate | 1 | EOD rate history |

crates/thetadatadx/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# thetadatadx
22

3-
The Rust SDK for [ThetaData](https://thetadata.us) market data. Pull US stock, option, index, and rate data three ways — point-in-time **history**, real-time **streaming**, and whole-universe **flat files** — from one async client. Connects straight to ThetaData; no Java terminal, no JVM, no local proxy.
3+
The Rust SDK for [ThetaData](https://thetadata.us) market data. Pull US stock, option, index, and rate data three ways — point-in-time **history**, real-time **streaming**, and whole-universe **flat files** — from one async client. Connects straight to ThetaData; nothing to install and run locally, no local proxy.
44

55
[![Crates.io](https://img.shields.io/crates/v/thetadatadx.svg?logo=rust)](https://crates.io/crates/thetadatadx)
66
[![docs.rs](https://img.shields.io/docsrs/thetadatadx?logo=docsdotrs)](https://docs.rs/thetadatadx)
@@ -12,9 +12,9 @@ The Rust SDK for [ThetaData](https://thetadata.us) market data. Pull US stock, o
1212
1313
## Features
1414

15-
- **Complete coverage** — stocks, options, indices, and rates across 61 typed endpoints.
15+
- **Complete coverage** — stocks, options, indices, and rates across 65 typed endpoints.
1616
- **Three access modes, one client** — point-in-time history, real-time streaming, and bulk flat-file downloads.
17-
- **Greeks without a round-trip**23 Black-Scholes Greeks and an implied-volatility solver, computed locally.
17+
- **Greeks without a round-trip**first- through third-order Black-Scholes Greeks and an implied-volatility solver, computed locally.
1818
- **Buffer or stream** — every history builder yields a `Vec<Tick>` on `.await`, or chunk-by-chunk via `.stream(handler)`.
1919
- **Typed errors** — one `Error` enum across every transport, plus a dedicated `FpssError` for the streaming path.
2020
- **DataFrames on demand** — opt into the `polars` / `arrow` features for a zero-copy conversion off any result.
@@ -64,7 +64,7 @@ async fn main() -> Result<(), thetadatadx::Error> {
6464
}
6565
```
6666

67-
61 typed endpoints span stocks, options, indices, the market calendar, and interest rates. Each builder accepts `.await` for a buffered `Vec<Tick>`, or `.stream(handler)` for chunk-by-chunk delivery — the right choice for multi-day backfills, where it holds peak memory flat instead of materialising the whole response.
67+
65 typed endpoints span stocks, options, indices, the market calendar, and interest rates. Each builder accepts `.await` for a buffered `Vec<Tick>`, or `.stream(handler)` for chunk-by-chunk delivery — the right choice for multi-day backfills, where it holds peak memory flat instead of materialising the whole response.
6868

6969
## Streaming
7070

@@ -148,7 +148,7 @@ use thetadatadx::fpss::protocol::Contract;
148148
use thetadatadx::fpss::{StreamingClient, StreamEvent};
149149

150150
let creds = Credentials::from_file("creds.txt")?;
151-
let hosts = DirectConfig::production().fpss.hosts;
151+
let hosts = DirectConfig::production().streaming.hosts;
152152
let client = StreamingClient::builder(&creds, &hosts).ring_size(8192).build()?;
153153

154154
client.subscribe(Contract::stock("AAPL").quote())?;
@@ -179,7 +179,7 @@ let path = thetadatadx::flatfile_request(
179179

180180
## Greeks calculator
181181

182-
A full Black-Scholes calculator — 23 Greeks plus an implied-volatility solver — runs locally, no request required.
182+
A full Black-Scholes calculator — first- through third-order Greeks plus an implied-volatility solver — runs locally, no request required.
183183

184184
## DataFrames
185185

crates/thetadatadx/config.default.toml

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,20 @@ hosts = [
3535
# Connection timeout per server attempt (ms)
3636
connect_timeout = 2000
3737

38-
# Read timeout — how long to wait for data before considering disconnected (ms)
39-
read_timeout = 10000
40-
41-
# Heartbeat interval (ms). The streaming protocol requires pings every 100ms.
42-
ping_interval = 100
43-
44-
# Reconnect wait after involuntary disconnect (ms)
45-
# FPSSClient.RECONNECT_DELAY_MS = 2000 at runtime in the Java terminal.
46-
reconnect_wait = 2000
38+
# Read timeout — how long to wait for data before the link is considered
39+
# dead (ms). The server heartbeats every ~100 ms on a quiet session, so this
40+
# default is ~30 missed heartbeats: a dead link is declared quickly.
41+
read_timeout = 3000
42+
43+
# Client heartbeat interval (ms). The server's own ~100 ms heartbeat is the
44+
# primary liveness signal; this client ping proves write-side health at a
45+
# 4 Hz cadence without adding inbound-frame pressure on a recovering upstream.
46+
ping_interval = 250
47+
48+
# Initial reconnect wait after an involuntary disconnect (ms). The auto-
49+
# reconnect driver doubles this per consecutive attempt up to its cap, then
50+
# applies jitter so a fleet does not reconnect in lockstep.
51+
reconnect_wait = 250
4752

4853
# Reconnect wait after TooManyRequests (ms). ThetaData enforces rate limits.
4954
reconnect_wait_rate_limited = 130000

crates/thetadatadx/src/config/mod.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,80 @@ mod tests {
12871287
assert_eq!(config.streaming.hosts.len(), 4);
12881288
}
12891289

1290+
#[test]
1291+
fn config_default_toml_matches_production_defaults() {
1292+
// The shipped template fills every tuning knob explicitly, and
1293+
// `#[serde(default)]` only backfills absent keys — so any value
1294+
// written here OVERRIDES the code default the moment an operator
1295+
// copies the file. Pin every parsed value to
1296+
// `DirectConfig::production()` so the template can never silently
1297+
// drift from the in-code defaults.
1298+
let default_toml = include_str!("../../config.default.toml");
1299+
let config = DirectConfig::from_toml_str(default_toml).unwrap();
1300+
let prod = DirectConfig::production();
1301+
1302+
// Historical (gRPC).
1303+
assert_eq!(config.historical.host, prod.historical.host);
1304+
assert_eq!(config.historical.port, prod.historical.port);
1305+
assert_eq!(config.historical.tls, prod.historical.tls);
1306+
assert_eq!(
1307+
config.historical.keepalive_secs,
1308+
prod.historical.keepalive_secs
1309+
);
1310+
assert_eq!(
1311+
config.historical.keepalive_timeout_secs,
1312+
prod.historical.keepalive_timeout_secs
1313+
);
1314+
assert_eq!(
1315+
config.historical.max_message_size,
1316+
prod.historical.max_message_size
1317+
);
1318+
assert_eq!(
1319+
config.historical.window_size_kb,
1320+
prod.historical.window_size_kb
1321+
);
1322+
assert_eq!(
1323+
config.historical.connection_window_size_kb,
1324+
prod.historical.connection_window_size_kb
1325+
);
1326+
assert_eq!(
1327+
config.historical.concurrent_requests,
1328+
prod.historical.concurrent_requests
1329+
);
1330+
1331+
// Streaming (TCP).
1332+
assert_eq!(config.streaming.hosts, prod.streaming.hosts);
1333+
assert_eq!(
1334+
config.streaming.connect_timeout_ms,
1335+
prod.streaming.connect_timeout_ms
1336+
);
1337+
assert_eq!(config.streaming.timeout_ms, prod.streaming.timeout_ms);
1338+
assert_eq!(
1339+
config.streaming.ping_interval_ms,
1340+
prod.streaming.ping_interval_ms
1341+
);
1342+
assert_eq!(config.streaming.ring_size, prod.streaming.ring_size);
1343+
assert_eq!(config.streaming.flush_mode, prod.streaming.flush_mode);
1344+
assert_eq!(config.streaming.wait_strategy, prod.streaming.wait_strategy);
1345+
assert_eq!(
1346+
config.streaming.wait_spin_iters,
1347+
prod.streaming.wait_spin_iters
1348+
);
1349+
assert_eq!(
1350+
config.streaming.wait_yield_iters,
1351+
prod.streaming.wait_yield_iters
1352+
);
1353+
assert_eq!(config.streaming.wait_park_us, prod.streaming.wait_park_us);
1354+
assert_eq!(config.streaming.consumer_cpu, prod.streaming.consumer_cpu);
1355+
1356+
// Reconnect cadence.
1357+
assert_eq!(config.reconnect.wait_ms, prod.reconnect.wait_ms);
1358+
assert_eq!(
1359+
config.reconnect.wait_rate_limited_ms,
1360+
prod.reconnect.wait_rate_limited_ms
1361+
);
1362+
}
1363+
12901364
#[test]
12911365
fn config_default_toml_uses_canonical_section_names() {
12921366
// The deserializer binds `[historical]` / `[streaming]`; the

docs-site/docs/articles/concurrent-requests.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ from thetadatadx import AsyncClient
2727
client = AsyncClient.from_file("creds.txt")
2828

2929
async def pull(day):
30-
return await client.historical.stock_history_trade_async("AAPL", day)
30+
return await client.stock_history_trade_async("AAPL", day)
3131

3232
results = asyncio.run(asyncio.gather(*(pull(d) for d in days)))
3333
```

docs-site/docs/articles/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: Install the SDK, save your credentials, and make your first request
55

66
# Getting Started
77

8-
ThetaDataDx connects directly to ThetaData's servers — no Java terminal process to install or babysit. Pick a language, install, save your credentials, and make a request.
8+
ThetaDataDx connects directly to ThetaData's servers — nothing to install and babysit locally. Pick a language, install, save your credentials, and make a request.
99

1010
## 1. Install
1111

docs-site/docs/cli.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ thetadatadx option list_expirations SPY
2626
thetadatadx option list_strikes SPY 20250321
2727

2828
# EOD Greeks for one pinned contract
29-
thetadatadx option history_greeks_eod SPY 20250321 570 C 20250303 20250306
29+
thetadatadx option history_greeks_eod SPY 20250321 20250303 20250306 570 C
3030

3131
# Snapshot quotes for several symbols
3232
thetadatadx stock snapshot_quote AAPL,MSFT,GOOGL

docs-site/docs/examples/bulk-backfill.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Every endpoint has a `<endpoint>_builder(...)` factory whose `.stream(...)` / `.
3939
```rust
4040
let days = ["20250303", "20250304", "20250305"];
4141
for day in days {
42-
client.historical.stock_history_trade("AAPL", day)
42+
client.historical().stock_history_trade("AAPL", day)
4343
.stream(|chunk| {
4444
// &[TradeTick] — persist, then the chunk is dropped.
4545
write_parquet(chunk);

docs-site/docs/server/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ description: Run the local HTTP REST and WebSocket server speaking the v3 route
99

1010
## Download and run
1111

12-
Prebuilt binaries are attached to each [GitHub Release](https://github.com/userFRM/ThetaDataDx/releases). No Rust toolchain and no Java terminal are required — download the archive for your platform, unpack it, and run the binary.
12+
Prebuilt binaries are attached to each [GitHub Release](https://github.com/userFRM/ThetaDataDx/releases). No Rust toolchain and nothing else to install locally — download the archive for your platform, unpack it, and run the binary.
1313

1414
The binaries are not code-signed yet, so each operating system asks for a one-time confirmation the first time you launch one.
1515

sdks/cpp/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# thetadatadx (C++)
22

3-
The C++ SDK for [ThetaData](https://thetadata.us) market data. Pull US stock, option, index, and rate data three ways — point-in-time **history**, real-time **streaming**, and whole-universe **flat files** — all from a single authenticated client. Connects straight to ThetaData; no Java terminal, no JVM, no local proxy.
3+
The C++ SDK for [ThetaData](https://thetadata.us) market data. Pull US stock, option, index, and rate data three ways — point-in-time **history**, real-time **streaming**, and whole-universe **flat files** — all from a single authenticated client. Connects straight to ThetaData; nothing to install and run locally, no local proxy.
44

55
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://github.com/userFRM/ThetaDataDx/blob/main/LICENSE)
66
[![C++](https://img.shields.io/badge/C%2B%2B-17-00599C.svg?logo=cplusplus&logoColor=white)](https://isocpp.org)
@@ -12,10 +12,10 @@ The C++ SDK for [ThetaData](https://thetadata.us) market data. Pull US stock, op
1212
1313
## Features
1414

15-
- **Complete coverage** — stocks, options, indices, and rates across 61 typed endpoints.
15+
- **Complete coverage** — stocks, options, indices, and rates across 65 typed endpoints.
1616
- **Three access modes** — point-in-time history, real-time streaming, and bulk flat-file downloads.
1717
- **Typed structs, no JSON** — every endpoint returns a `std::vector` of decoded structs; prices arrive as `double`.
18-
- **Greeks without a round-trip**23 Black-Scholes Greeks and an implied-volatility solver, computed locally.
18+
- **Greeks without a round-trip**first- through third-order Black-Scholes Greeks and an implied-volatility solver, computed locally.
1919
- **RAII throughout** — clients own their connections and clean up on scope exit; methods throw on failure.
2020
- **Header plus one library** — a single `thetadatadx.hpp` over a prebuilt C ABI shared library.
2121

@@ -157,7 +157,7 @@ fpss.subscribe(thetadatadx::SecType::option().full_trades()); // the callback
157157
158158
## Greeks calculator
159159

160-
A full Black-Scholes calculator — 23 Greeks plus an implied-volatility solver — runs locally, no connection required:
160+
A full Black-Scholes calculator — first- through third-order Greeks plus an implied-volatility solver — runs locally, no connection required:
161161

162162
```cpp
163163
auto g = thetadatadx::all_greeks(450.0, 455.0, 0.05, 0.015, 30.0 / 365.0, 8.50, "C");
@@ -191,12 +191,12 @@ The flat-file distribution serves a fixed set of datasets: option `trade_quote`
191191

192192
## Endpoint coverage
193193

194-
61 typed endpoints across stocks, options, indices, the market calendar, and interest rates, plus real-time streaming and the local Greeks calculator.
194+
65 typed endpoints across stocks, options, indices, the market calendar, and interest rates, plus real-time streaming and the local Greeks calculator.
195195

196196
| Category | Endpoints | Examples |
197197
|---|---|---|
198-
| Stock | 14 | EOD, OHLC, trades, quotes, snapshots, at-time |
199-
| Option | 34 | Every stock surface plus five Greeks tiers, open interest, contract lists |
198+
| Stock | 16 | EOD, OHLC, trades, quotes, snapshots, at-time |
199+
| Option | 36 | Every stock surface plus five Greeks tiers, open interest, contract lists |
200200
| Index | 9 | EOD, OHLC, price, snapshots |
201201
| Calendar | 3 | Market open/close, holidays, early closes |
202202
| Interest rate | 1 | EOD rate history |

0 commit comments

Comments
 (0)