fix(tdbe): reject non-positive spot/strike and size u8 layout fields correctly#812
Merged
Conversation
…correctly Black-Scholes is undefined for spot <= 0 or strike <= 0: the (spot / strike).ln() term goes non-finite and strike == 0 is an outright divide-by-zero. The fallible public entry points all_greeks and implied_volatility now reject a non-positive (or non-finite) spot or strike with Error::Config naming the offending value, so no SDK, CLI, or MCP surface can serialise NaN or null Greeks. The infallible compute_full_bundle_with_iv treats the same inputs as degenerate and returns an all-zero bundle rather than emitting NaN. The FPSS C-layout generator sized u8 fields as 4/4 by sharing the i32 match arm. The arm is split so u8 is 1/1 and i32 is 4/4, which keeps the generated offset static_assert correct for any future u8-before-smaller-aligned field; the build.rs run that emits the asserts still compiles. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two numeric-safety fixes in the core crate
Non-positive spot/strike no longer emit NaN or null Greeks
Black-Scholes is undefined for
spot <= 0orstrike <= 0: the(spot / strike).ln()term goes non-finite andstrike == 0is an outright divide-by-zero. The existing degeneracy guard only checked vol and time, so a non-positive spot or strike flowed straight intod1/d2, and the fields that did not route through the NaN-to-zero clamp serialised to JSONnull.all_greeksandimplied_volatility(the surface every SDK / CLI / MCP funnels through) now reject a non-positive or non-finite spot/strike up front withError::Config, naming the offending value.compute_full_bundle_with_ivtreats the same inputs as degenerate and returns an all-zero bundle rather than producing NaN/Inf.The positivity test is written as
value > 0.0, so aNaNspot or strike also routes to the rejection / degenerate path.u8sized correctly in the FPSS layout-assert generatorThe C-layout generator gave
u8a size and alignment of 4 by sharing thei32match arm. That is harmless today only because the singleu8field is followed by an 8-aligned field, but any futureu8-before-smaller-aligned field would have baked a wrong offset into a generatedstatic_assert. The arm is split sou8is1/1andi32is4/4. The other arms each map one logical width, so no further conflation remained to fix.Test evidence
cargo test -p thetadatadx --lib tdbe::greeks— 26 passed, 0 failed. New tests:all_greeks_errors_on_nonpositive_spotall_greeks_errors_on_nonpositive_strikeimplied_volatility_errors_on_nonpositive_spotimplied_volatility_errors_on_nonpositive_strikecompute_full_bundle_zeros_on_nonpositive_spot_or_strikeEach checks
spot/strikeof0.0and negatives return a cleanError::Config(no NaN, no panic), and that the infallible bundle path returns an all-zero, all-finite bundle.Also verified:
cargo fmt --all -- --checkclean,cargo build -p thetadatadxsucceeds (exercises the layout generator'sstatic_assertemission via build.rs),cargo clippy -p thetadatadx --lib -- -D warningsclean.🤖 Generated with Claude Code