Skip to content

Commit 50ed4fb

Browse files
userFRMclaude
andcommitted
v4.3.0: expose start_time/end_time on all 25 endpoints
All endpoints that support time filtering now accept optional start_time and end_time parameters. Pass None for RTH defaults (09:30-16:00) or Some for pre-market/extended hours. Also: version pins updated, venue default documented. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0e53598 commit 50ed4fb

18 files changed

Lines changed: 289 additions & 182 deletions

File tree

CHANGELOG.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [4.3.0] - 2026-04-02
9+
10+
### Added
11+
12+
- **`start_time` and `end_time` parameters** exposed on all 25 endpoints that support time filtering. Pass `Some("04:00:00")` for pre-market, `Some("20:00:00")` for extended hours, or `None` for RTH defaults (09:30:00-16:00:00). Affects stock history/snapshot/at-time, option history, and index history endpoints.
13+
14+
### Fixed
15+
16+
- Version pins in README and getting-started docs updated to `"4.2"`
17+
- Default venue `"nqb"` (NASDAQ Best) documented in jvm-deviations.md
18+
819
## [4.2.0] - 2026-04-01
920

1021
### Fixed (battle-tested against live MDDS -- all 61 endpoints verified)
@@ -459,7 +470,8 @@ See [TODO.md](TODO.md) for the production readiness checklist and performance ro
459470
- FIT decoder uses i64 accumulator with i32 saturation (no silent overflow)
460471
- Price type range enforced with `assert!` in release builds
461472

462-
[Unreleased]: https://github.com/userFRM/ThetaDataDx/compare/v4.2.0...HEAD
473+
[Unreleased]: https://github.com/userFRM/ThetaDataDx/compare/v4.3.0...HEAD
474+
[4.3.0]: https://github.com/userFRM/ThetaDataDx/compare/v4.2.0...v4.3.0
463475
[4.2.0]: https://github.com/userFRM/ThetaDataDx/compare/v4.1.2...v4.2.0
464476
[4.1.2]: https://github.com/userFRM/ThetaDataDx/compare/v4.1.1...v4.1.2
465477
[4.1.1]: https://github.com/userFRM/ThetaDataDx/compare/v4.1.0...v4.1.1

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ No-JVM ThetaData Terminal - native Rust SDK for direct market data access.
4242

4343
```toml
4444
[dependencies]
45-
thetadatadx = "3.2"
45+
thetadatadx = "4.2"
4646
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
4747
```
4848

crates/thetadatadx/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "thetadatadx"
3-
version = "4.2.0"
3+
version = "4.3.0"
44
edition = "2021"
55
rust-version = "1.85"
66
authors = ["userFRM"]

crates/thetadatadx/src/direct.rs

Lines changed: 83 additions & 75 deletions
Large diffs are not rendered by default.

docs-site/docs/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ description: Install ThetaDataDx, configure credentials, and run your first quer
1111
```toml [Rust]
1212
# Add to your Cargo.toml
1313
[dependencies]
14-
thetadatadx = "3.2"
14+
thetadatadx = "4.2"
1515
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
1616
```
1717
```bash [Python]

docs/jvm-deviations.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,14 @@ As of v1.2.0:
203203
| **Source** | Decompiled request builders in `providers/` handlers | `direct.rs` gRPC query construction |
204204
| **Rationale** | The Java terminal always sends regular-trading-hours defaults when the user omits time bounds. Previous Rust versions sent no time bounds, causing the server to return pre-market and after-hours data by default. As of v4.2.0, the Rust implementation matches the Java terminal's defaults exactly. |
205205

206+
### Default Venue `"nqb"` on Stock Endpoints
207+
208+
| | Java | Rust | Impact |
209+
|---|---|---|---|
210+
| **Behavior** | Sends `venue: "nqb"` (NASDAQ Basic) on stock snapshot and stock history requests that accept a venue parameter | Matches Java: all stock snapshot and intraday history endpoints default to `venue: "nqb"` | Identical behavior |
211+
| **Source** | Decompiled request builders in `providers/` handlers | `direct.rs` gRPC query construction |
212+
| **Rationale** | The Java terminal always sends `"nqb"` as the default venue for stock endpoints (snapshots, OHLC, trades, quotes, trade-quotes). This selects NASDAQ Basic (UTP SIP) data, which is the standard consolidated tape for US equities. Previous Rust versions did not set a venue, which caused the server to return data from a different default source. As of v4.2.0, the Rust implementation matches the Java terminal's venue default exactly on all applicable stock endpoints. |
213+
206214
### FPSS TLS Certificate Verification Skip
207215

208216
| | Java | Rust | Impact |

examples/test_intervals.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
2222
for (desc, endpoint, interval) in tests {
2323
print!("{}: ", desc);
2424
let result = match endpoint {
25-
"stock" => tdx.stock_history_ohlc("AAPL", "20260325", interval).await,
26-
"index" => tdx.index_history_ohlc("SPX", "20260325", "20260325", interval).await,
25+
"stock" => tdx.stock_history_ohlc("AAPL", "20260325", interval, None, None).await,
26+
"index" => tdx.index_history_ohlc("SPX", "20260325", "20260325", interval, None, None).await,
2727
_ => unreachable!(),
2828
};
2929
match result {

ffi/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "thetadatadx-ffi"
3-
version = "4.2.0"
3+
version = "4.3.0"
44
edition = "2021"
55
description = "C FFI layer for thetadatadx — used by Go and C++ SDKs"
66
license = "GPL-3.0-or-later"

ffi/src/lib.rs

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,45 @@ macro_rules! ffi_snapshot_endpoint {
786786

787787
/// FFI wrapper for parsed tick endpoints with C string params.
788788
macro_rules! ffi_parsed_endpoint {
789+
// Variant with trailing extra args (e.g. None, None for optional time params)
790+
(
791+
$(#[$meta:meta])*
792+
$ffi_name:ident => $method:ident, $tick_to_json:ident ( $($param:ident),+ ) [ $($trailing:expr),* ]
793+
) => {
794+
$(#[$meta])*
795+
#[no_mangle]
796+
pub unsafe extern "C" fn $ffi_name(
797+
client: *const TdxClient,
798+
$($param: *const c_char),+
799+
) -> *mut c_char {
800+
if client.is_null() {
801+
set_error("client handle is null");
802+
return ptr::null_mut();
803+
}
804+
let client = unsafe { &*client };
805+
$(
806+
let $param = match unsafe { cstr_to_str($param) } {
807+
Some(s) => s,
808+
None => {
809+
set_error(concat!(stringify!($param), " is null or invalid UTF-8"));
810+
return ptr::null_mut();
811+
}
812+
};
813+
)+
814+
match runtime().block_on(client.inner.$method($($param,)+ $($trailing),*)) {
815+
Ok(ticks) => {
816+
let json =
817+
serde_json::Value::Array(ticks.iter().map($tick_to_json).collect());
818+
json_to_cstring(&json)
819+
}
820+
Err(e) => {
821+
set_error(&e.to_string());
822+
ptr::null_mut()
823+
}
824+
}
825+
}
826+
};
827+
// Original variant without trailing args (for endpoints that don't need them)
789828
(
790829
$(#[$meta:meta])*
791830
$ffi_name:ident => $method:ident, $tick_to_json:ident ( $($param:ident),+ )
@@ -911,31 +950,31 @@ ffi_parsed_endpoint! {
911950
// 8. stock_history_ohlc
912951
ffi_parsed_endpoint! {
913952
/// Fetch stock intraday OHLC bars. Returns JSON array of OHLC ticks.
914-
tdx_stock_history_ohlc => stock_history_ohlc, ohlc_tick_to_json(symbol, date, interval)
953+
tdx_stock_history_ohlc => stock_history_ohlc, ohlc_tick_to_json(symbol, date, interval) [None, None]
915954
}
916955

917956
// 8b. stock_history_ohlc_range
918957
ffi_parsed_endpoint! {
919958
/// Fetch stock intraday OHLC bars across a date range. Returns JSON array.
920-
tdx_stock_history_ohlc_range => stock_history_ohlc_range, ohlc_tick_to_json(symbol, start_date, end_date, interval)
959+
tdx_stock_history_ohlc_range => stock_history_ohlc_range, ohlc_tick_to_json(symbol, start_date, end_date, interval) [None, None]
921960
}
922961

923962
// 9. stock_history_trade
924963
ffi_parsed_endpoint! {
925964
/// Fetch all trades on a date. Returns JSON array of trade ticks.
926-
tdx_stock_history_trade => stock_history_trade, trade_tick_to_json(symbol, date)
965+
tdx_stock_history_trade => stock_history_trade, trade_tick_to_json(symbol, date) [None, None]
927966
}
928967

929968
// 10. stock_history_quote
930969
ffi_parsed_endpoint! {
931970
/// Fetch NBBO quotes. Returns JSON array of quote ticks.
932-
tdx_stock_history_quote => stock_history_quote, quote_tick_to_json(symbol, date, interval)
971+
tdx_stock_history_quote => stock_history_quote, quote_tick_to_json(symbol, date, interval) [None, None]
933972
}
934973

935974
// 11. stock_history_trade_quote
936975
ffi_parsed_endpoint! {
937976
/// Fetch combined trade + quote ticks. Returns JSON array.
938-
tdx_stock_history_trade_quote => stock_history_trade_quote, trade_quote_tick_to_json(symbol, date)
977+
tdx_stock_history_trade_quote => stock_history_trade_quote, trade_quote_tick_to_json(symbol, date) [None, None]
939978
}
940979

941980
// ═══════════════════════════════════════════════════════════════════════
@@ -1065,25 +1104,25 @@ ffi_parsed_endpoint! {
10651104
// 30. option_history_ohlc
10661105
ffi_parsed_endpoint! {
10671106
/// Fetch intraday OHLC bars for an option contract. Returns JSON array.
1068-
tdx_option_history_ohlc => option_history_ohlc, ohlc_tick_to_json(symbol, expiration, strike, right, date, interval)
1107+
tdx_option_history_ohlc => option_history_ohlc, ohlc_tick_to_json(symbol, expiration, strike, right, date, interval) [None, None]
10691108
}
10701109

10711110
// 31. option_history_trade
10721111
ffi_parsed_endpoint! {
10731112
/// Fetch all trades for an option contract on a date. Returns JSON array.
1074-
tdx_option_history_trade => option_history_trade, trade_tick_to_json(symbol, expiration, strike, right, date)
1113+
tdx_option_history_trade => option_history_trade, trade_tick_to_json(symbol, expiration, strike, right, date) [None, None]
10751114
}
10761115

10771116
// 32. option_history_quote
10781117
ffi_parsed_endpoint! {
10791118
/// Fetch NBBO quotes for an option contract on a date. Returns JSON array.
1080-
tdx_option_history_quote => option_history_quote, quote_tick_to_json(symbol, expiration, strike, right, date, interval)
1119+
tdx_option_history_quote => option_history_quote, quote_tick_to_json(symbol, expiration, strike, right, date, interval) [None, None]
10811120
}
10821121

10831122
// 33. option_history_trade_quote
10841123
ffi_parsed_endpoint! {
10851124
/// Fetch combined trade + quote ticks for an option contract. Returns JSON array.
1086-
tdx_option_history_trade_quote => option_history_trade_quote, trade_quote_tick_to_json(symbol, expiration, strike, right, date)
1125+
tdx_option_history_trade_quote => option_history_trade_quote, trade_quote_tick_to_json(symbol, expiration, strike, right, date) [None, None]
10871126
}
10881127

10891128
// 34. option_history_open_interest
@@ -1105,61 +1144,61 @@ ffi_parsed_endpoint! {
11051144
// 36. option_history_greeks_all
11061145
ffi_parsed_endpoint! {
11071146
/// Fetch all Greeks history (intraday). Returns JSON array.
1108-
tdx_option_history_greeks_all => option_history_greeks_all, greeks_tick_to_json(symbol, expiration, strike, right, date, interval)
1147+
tdx_option_history_greeks_all => option_history_greeks_all, greeks_tick_to_json(symbol, expiration, strike, right, date, interval) [None, None]
11091148
}
11101149

11111150
// 37. option_history_trade_greeks_all
11121151
ffi_parsed_endpoint! {
11131152
/// Fetch all Greeks on each trade. Returns JSON array.
1114-
tdx_option_history_trade_greeks_all => option_history_trade_greeks_all, greeks_tick_to_json(symbol, expiration, strike, right, date)
1153+
tdx_option_history_trade_greeks_all => option_history_trade_greeks_all, greeks_tick_to_json(symbol, expiration, strike, right, date) [None, None]
11151154
}
11161155

11171156
// 38. option_history_greeks_first_order
11181157
ffi_parsed_endpoint! {
11191158
/// Fetch first-order Greeks history. Returns JSON array.
1120-
tdx_option_history_greeks_first_order => option_history_greeks_first_order, greeks_tick_to_json(symbol, expiration, strike, right, date, interval)
1159+
tdx_option_history_greeks_first_order => option_history_greeks_first_order, greeks_tick_to_json(symbol, expiration, strike, right, date, interval) [None, None]
11211160
}
11221161

11231162
// 39. option_history_trade_greeks_first_order
11241163
ffi_parsed_endpoint! {
11251164
/// Fetch first-order Greeks on each trade. Returns JSON array.
1126-
tdx_option_history_trade_greeks_first_order => option_history_trade_greeks_first_order, greeks_tick_to_json(symbol, expiration, strike, right, date)
1165+
tdx_option_history_trade_greeks_first_order => option_history_trade_greeks_first_order, greeks_tick_to_json(symbol, expiration, strike, right, date) [None, None]
11271166
}
11281167

11291168
// 40. option_history_greeks_second_order
11301169
ffi_parsed_endpoint! {
11311170
/// Fetch second-order Greeks history. Returns JSON array.
1132-
tdx_option_history_greeks_second_order => option_history_greeks_second_order, greeks_tick_to_json(symbol, expiration, strike, right, date, interval)
1171+
tdx_option_history_greeks_second_order => option_history_greeks_second_order, greeks_tick_to_json(symbol, expiration, strike, right, date, interval) [None, None]
11331172
}
11341173

11351174
// 41. option_history_trade_greeks_second_order
11361175
ffi_parsed_endpoint! {
11371176
/// Fetch second-order Greeks on each trade. Returns JSON array.
1138-
tdx_option_history_trade_greeks_second_order => option_history_trade_greeks_second_order, greeks_tick_to_json(symbol, expiration, strike, right, date)
1177+
tdx_option_history_trade_greeks_second_order => option_history_trade_greeks_second_order, greeks_tick_to_json(symbol, expiration, strike, right, date) [None, None]
11391178
}
11401179

11411180
// 42. option_history_greeks_third_order
11421181
ffi_parsed_endpoint! {
11431182
/// Fetch third-order Greeks history. Returns JSON array.
1144-
tdx_option_history_greeks_third_order => option_history_greeks_third_order, greeks_tick_to_json(symbol, expiration, strike, right, date, interval)
1183+
tdx_option_history_greeks_third_order => option_history_greeks_third_order, greeks_tick_to_json(symbol, expiration, strike, right, date, interval) [None, None]
11451184
}
11461185

11471186
// 43. option_history_trade_greeks_third_order
11481187
ffi_parsed_endpoint! {
11491188
/// Fetch third-order Greeks on each trade. Returns JSON array.
1150-
tdx_option_history_trade_greeks_third_order => option_history_trade_greeks_third_order, greeks_tick_to_json(symbol, expiration, strike, right, date)
1189+
tdx_option_history_trade_greeks_third_order => option_history_trade_greeks_third_order, greeks_tick_to_json(symbol, expiration, strike, right, date) [None, None]
11511190
}
11521191

11531192
// 44. option_history_greeks_implied_volatility
11541193
ffi_parsed_endpoint! {
11551194
/// Fetch IV history (intraday). Returns JSON array.
1156-
tdx_option_history_greeks_implied_volatility => option_history_greeks_implied_volatility, iv_tick_to_json(symbol, expiration, strike, right, date, interval)
1195+
tdx_option_history_greeks_implied_volatility => option_history_greeks_implied_volatility, iv_tick_to_json(symbol, expiration, strike, right, date, interval) [None, None]
11571196
}
11581197

11591198
// 45. option_history_trade_greeks_implied_volatility
11601199
ffi_parsed_endpoint! {
11611200
/// Fetch IV on each trade. Returns JSON array.
1162-
tdx_option_history_trade_greeks_implied_volatility => option_history_trade_greeks_implied_volatility, iv_tick_to_json(symbol, expiration, strike, right, date)
1201+
tdx_option_history_trade_greeks_implied_volatility => option_history_trade_greeks_implied_volatility, iv_tick_to_json(symbol, expiration, strike, right, date) [None, None]
11631202
}
11641203

11651204
// ═══════════════════════════════════════════════════════════════════════
@@ -1229,13 +1268,13 @@ ffi_parsed_endpoint! {
12291268
// 54. index_history_ohlc
12301269
ffi_parsed_endpoint! {
12311270
/// Fetch intraday OHLC bars for an index. Returns JSON array.
1232-
tdx_index_history_ohlc => index_history_ohlc, ohlc_tick_to_json(symbol, start_date, end_date, interval)
1271+
tdx_index_history_ohlc => index_history_ohlc, ohlc_tick_to_json(symbol, start_date, end_date, interval) [None, None]
12331272
}
12341273

12351274
// 55. index_history_price
12361275
ffi_parsed_endpoint! {
12371276
/// Fetch intraday price history for an index. Returns JSON array.
1238-
tdx_index_history_price => index_history_price, price_tick_to_json(symbol, date, interval)
1277+
tdx_index_history_price => index_history_price, price_tick_to_json(symbol, date, interval) [None, None]
12391278
}
12401279

12411280
// ═══════════════════════════════════════════════════════════════════════

sdks/python/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "thetadatadx-py"
3-
version = "4.2.0"
3+
version = "4.3.0"
44
edition = "2021"
55
description = "Python bindings for thetadatadx — native ThetaData SDK powered by Rust"
66

0 commit comments

Comments
 (0)