feat(greeks): expose pub fn vera + compute_full_bundle_with_iv#466
Merged
Conversation
Closes #465. Two missing exports were forcing downstream IV-cache fast paths to either (a) duplicate the `vera` closed form locally, or (b) issue 17+ separate per-Greek calls instead of one bundle pass. ## Changes * `pub fn vera(s, x, v, r, q, t) -> f64` — placed next to `vomma` / `veta`. Mirrors the inline computation already in `all_greeks` (line 668). Returns `0.0` when `is_degenerate(v, t)`, matching every other Greek's behaviour on zero-IV / zero-tenor inputs. * `pub fn compute_full_bundle_with_iv(s, x, v, r, q, t, is_call) -> GreeksResult` — the full bundle computation factored out of `all_greeks` so consumers with a pre-solved IV can skip the bisection. One Tier-0 intermediates pass shared across every Greek; ~2× faster than calling each Greek's free fn separately. * `all_greeks` refactored to a thin wrapper: parses the right, runs the bisection IV solver, delegates to `compute_full_bundle_with_iv`, and overwrites `iv_error` with the residual the solver produced (the new helper does not run the solver and intentionally leaves `iv_error` at `0.0`). ## Tests 109 lib tests (was 105, +4): * `vera_free_fn_matches_inline_value_in_all_greeks` — bit-stable match with `GreeksResult.vera` at the same IV. * `vera_free_fn_zeros_on_degenerate_inputs` — degenerate guard. * `compute_full_bundle_with_iv_matches_all_greeks_with_solved_iv` — every field of the bundle matches `all_greeks` output (modulo `iv_error` which only the solver-driven path populates). * `compute_full_bundle_with_iv_zeros_greeks_on_degenerate_iv` — degenerate guard. Existing tests including `vera_matches_textbook_dvega_dr` and `all_greeks_precomputed_matches_individual` still pass — refactor is bit-stable for the public `all_greeks` surface. ## Downstream consumer `thetadatadx-analytics` v0.3-alpha will drop its private `vera_closed_form` helper and switch its IV-cache hot path from 17+ per-Greek calls to a single `compute_full_bundle_with_iv` invocation. Expected throughput recovery from 636 ns/tick to ~300 ns/tick (the cached path's post-PR regression tracked at the analytics-crate level). ## Out of scope No version bump in this PR — patch increment handled separately per project convention. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds missing public entry points in tdbe::greeks to support downstream IV-cache fast paths and avoid redundant per-Greek recomputation.
Changes:
- Exposes
pub fn vera(s, x, v, r, q, t)as a standalone closed-form Greek (matching the bundle computation). - Factors the post-IV-solve bundle computation out of
all_greeksintopub fn compute_full_bundle_with_iv(..., is_call) -> GreeksResult. - Adds tests to pin
verabehavior and to ensure the new bundle helper matchesall_greekswhen fed the solver-produced IV.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+602
to
+604
| /// new option price should compute it externally via | ||
| /// `(value(...) - option_price) / option_price` and overwrite the | ||
| /// field. |
Comment on lines
+592
to
+596
| /// Use this when the caller already has a recent IV and just wants | ||
| /// the full bundle re-evaluated at new `(s, x, ...)` inputs — the | ||
| /// typical IV-cache hot path. One Tier-0 intermediates pass is | ||
| /// shared across every Greek in the bundle, so this is roughly 2× | ||
| /// faster than issuing 17+ separate per-Greek calls. |
| let standalone = vera(s, x, g.iv, r, q, t); | ||
| assert!( | ||
| (standalone - g.vera).abs() < 1e-12, | ||
| "free-fn vera ({standalone}) must match all_greeks().vera ({}) bit-for-bit at the same IV", |
- Document compute_full_bundle_with_iv's bool right argument: it is the lower-level helper for callers who already have the parsed side; all_greeks / implied_volatility remain the str right surface. - Caveat the iv_error residual snippet: the relative form divides by zero when option_price == 0; the docstring now points to the absolute residual as the zero-priced fallback. - Test assertion message: "bit-for-bit" -> "within 1e-12" so the tolerance-based comparison and the message agree.
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.
Closes #465.
Summary
Two missing exports in
tdbe::greeksthat were forcing downstream IV-cache fast paths to duplicate theveraclosed form and issue 17+ separate per-Greek calls instead of one bundle pass.pub fn vera(s, x, v, r, q, t)— placed next tovomma/veta. Mirrors the inline computation already inall_greeks.is_degenerate(v, t)guard matches every other Greek.pub fn compute_full_bundle_with_iv(s, x, v, r, q, t, is_call) -> GreeksResult— the full bundle factored out ofall_greeksso consumers with a pre-solved IV can skip the bisection. One Tier-0 intermediates pass shared across every Greek.Refactor
all_greeksbecomes a thin wrapper: parses the right, runs the bisection, delegates tocompute_full_bundle_with_iv, overwritesiv_errorwith the solver residual. Bit-stable for callers —all_greeks_precomputed_matches_individualstill passes unchanged.Tests
109 lib tests passing (was 105, +4):
vera_free_fn_matches_inline_value_in_all_greeksvera_free_fn_zeros_on_degenerate_inputscompute_full_bundle_with_iv_matches_all_greeks_with_solved_ivcompute_full_bundle_with_iv_zeros_greeks_on_degenerate_ivDownstream
thetadatadx-analyticsv0.3-alpha (https://github.com/userFRM/thetadatadx-analytics) will drop its privatevera_closed_formhelper and switch its IV-cache hot path from 17+ per-Greek calls to onecompute_full_bundle_with_ivinvocation. Expected throughput recovery from 636 ns/tick to ~300 ns/tick on the cached path.Test plan
cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspaceOut of scope
No version bump in this PR — patch increment handled separately per project convention.
🤖 Generated with Claude Code