Skip to content

Commit 8a89ded

Browse files
userFRMclaude
andauthored
fix: audit round 2 -- Go price corruption, Python docs, Price panic, FFI safety, SDK parity
Blocker: - Go SDK priceToFloat() used wrong encoding, corrupting ALL prices. Now uses value * 10^(price_type - 10) matching Rust. Fixes #15. - Python README + docs-site streaming examples used event["type"] instead of event["kind"]. Fixes #16. Critical: - Price::new() assert! -> debug_assert! + clamp(0,19) with warn!. Corrupt frames no longer crash production. Fixes #17. - C++ FpssClient: added missing unsubscribe_quotes(). Fixes #18. High: - FFI FPSS: all 12 .lock().unwrap() -> .unwrap_or_else(poison recovery). Prevents UB on mutex poison across extern "C". Fixes #19. - Python README: removed ghost methods is_authenticated/server_addr. - Root README: "Stock (13)" -> "Stock (14)". Medium: - C++ MarketValueTick: 3 fields -> 7 (matches Go parity). - C++ CalendarDay: added status field. InterestRateTick: added ms_of_day. - Credentials.password: pub -> pub(crate) with accessor method. - WS handler: added OPEN_INTEREST + FULL_TRADES dispatch. Low: - greeks.rs: removed shadowed start variable. - Rebuilt mdBook from fixed sources. Fixes #20. 160 tests, zero warnings, all doc-tests pass. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2d79cbf commit 8a89ded

44 files changed

Lines changed: 145 additions & 103 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ async fn main() -> Result<(), thetadatadx::Error> {
121121

122122
61 typed methods covering all ThetaData MDDS endpoints (60 gRPC RPCs).
123123

124-
### Stock (13 methods)
124+
### Stock (14 methods)
125125

126126
| Category | Method | Description |
127127
|----------|--------|-------------|

crates/thetadatadx/src/auth/creds.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub struct Credentials {
2222
/// Email address, lowercased and trimmed (matches Java `toLowerCase().trim()`).
2323
pub email: String,
2424
/// Password, trimmed.
25-
pub password: String,
25+
pub(crate) password: String,
2626
}
2727

2828
impl std::fmt::Debug for Credentials {
@@ -87,6 +87,11 @@ impl Credentials {
8787
Ok(Self { email, password })
8888
}
8989

90+
/// Get the password.
91+
pub fn password(&self) -> &str {
92+
&self.password
93+
}
94+
9095
/// Construct credentials directly (e.g. from environment variables).
9196
pub fn new(email: impl Into<String>, password: impl Into<String>) -> Self {
9297
Self {

crates/thetadatadx/src/fpss/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
//! # use thetadatadx::fpss::{FpssClient, FpssData, FpssEvent};
2828
//! # use thetadatadx::auth::Credentials;
2929
//! # fn example() -> Result<(), thetadatadx::error::Error> {
30-
//! let creds = Credentials { email: "user@example.com".into(), password: "pw".into() };
30+
//! let creds = Credentials::new("user@example.com", "pw");
3131
//! let client = FpssClient::connect(&creds, 4096, |event: &FpssEvent| {
3232
//! // Runs on the Disruptor consumer thread -- keep it fast.
3333
//! // Push to your own queue for heavy processing.

crates/thetadatadx/src/greeks.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ fn iv_bisection(s: f64, x: f64, r: f64, q: f64, t: f64, o: f64, is_call: bool, o
320320
}
321321

322322
let mut guess = 0.5;
323-
let start = 0.0;
323+
let mut start = 0.0;
324324
let mut end = guess;
325325
let mut changer = 0.2;
326326

@@ -332,8 +332,6 @@ fn iv_bisection(s: f64, x: f64, r: f64, q: f64, t: f64, o: f64, is_call: bool, o
332332
}
333333
changer *= 2.0;
334334
}
335-
336-
let mut start = start;
337335
for _ in 0..MAX_TRIES {
338336
let v = value(s, x, guess, r, q, t, is_call);
339337
if (v - o).abs() < 0.001 {

crates/thetadatadx/src/types/price.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,22 @@ impl Price {
5555

5656
#[inline]
5757
pub fn new(value: i32, price_type: i32) -> Self {
58-
assert!(
58+
debug_assert!(
5959
(0..20).contains(&price_type),
6060
"price_type must be 0..20, got {price_type}"
6161
);
62-
Self { value, price_type }
62+
let clamped = price_type.clamp(0, 19);
63+
if clamped != price_type {
64+
tracing::warn!(
65+
price_type,
66+
clamped,
67+
"price_type out of range 0..20, clamping"
68+
);
69+
}
70+
Self {
71+
value,
72+
price_type: clamped,
73+
}
6374
}
6475

6576
pub fn is_zero(&self) -> bool {

docs-site/book/404.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
const path_to_root = "";
3737
const default_light_theme = "navy";
3838
const default_dark_theme = "coal";
39-
window.path_to_searchindex_js = "searchindex-d9431649.js";
39+
window.path_to_searchindex_js = "searchindex-dd8033fe.js";
4040
</script>
4141
<!-- Start loading toc.js asap -->
4242
<script src="toc-4b833958.js"></script>

docs-site/book/changelog.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
const path_to_root = "";
3636
const default_light_theme = "navy";
3737
const default_dark_theme = "coal";
38-
window.path_to_searchindex_js = "searchindex-d9431649.js";
38+
window.path_to_searchindex_js = "searchindex-dd8033fe.js";
3939
</script>
4040
<!-- Start loading toc.js asap -->
4141
<script src="toc-4b833958.js"></script>

docs-site/book/cpp/api-reference.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
const path_to_root = "../";
3636
const default_light_theme = "navy";
3737
const default_dark_theme = "coal";
38-
window.path_to_searchindex_js = "../searchindex-d9431649.js";
38+
window.path_to_searchindex_js = "../searchindex-dd8033fe.js";
3939
</script>
4040
<!-- Start loading toc.js asap -->
4141
<script src="../toc-4b833958.js"></script>

docs-site/book/cpp/getting-started.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
const path_to_root = "../";
3636
const default_light_theme = "navy";
3737
const default_dark_theme = "coal";
38-
window.path_to_searchindex_js = "../searchindex-d9431649.js";
38+
window.path_to_searchindex_js = "../searchindex-dd8033fe.js";
3939
</script>
4040
<!-- Start loading toc.js asap -->
4141
<script src="../toc-4b833958.js"></script>

docs-site/book/cpp/historical.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
const path_to_root = "../";
3636
const default_light_theme = "navy";
3737
const default_dark_theme = "coal";
38-
window.path_to_searchindex_js = "../searchindex-d9431649.js";
38+
window.path_to_searchindex_js = "../searchindex-dd8033fe.js";
3939
</script>
4040
<!-- Start loading toc.js asap -->
4141
<script src="../toc-4b833958.js"></script>

0 commit comments

Comments
 (0)