fix(simulation,pricing): fallible RandomWalk/Simulator constructors + Telegraph guard (#349, #351)#352
Merged
joaquinbejar merged 3 commits intomainfrom Apr 17, 2026
Conversation
…#351) The branch `if lambda_dt < dec!(11.7)` was always true for non-negative lambda and dt, forcing probability = 1.0 every step and degenerating the chain into a deterministic alternation. Correct guard is `if lambda_dt < dec!(-11.7)` (underflow at very-negative exponent), with the normal branch computing 1 - exp(-lambda * dt) per the module docs. Adds a Monte-Carlo regression test that asserts the empirical flip rate at (lambda=0.5, dt=0.01) matches 1 - exp(-0.005) ≈ 0.00499 within 5σ over 100k samples.
#349) Both constructors now accept a fallible generator `F: Fn(&WalkParams<X, Y>) -> Result<Vec<Step<X, Y>>, E>` and return `Result<Self, E>`, propagating any generator error unchanged. This removes the `|p| generator_positive(p).unwrap()` wrappers required since PR #348 made the chain generators fallible, restoring panic-free end-to-end pipelines per the M1 — Panic-Free Core milestone. Also adds `From<ChainError> for SimulationError` (symmetric with the existing reverse impl) so callers can `?`-propagate chain-generator errors through simulation contexts. Negative tests for both constructors verify the error surfaces unchanged and that `Simulator::new` short-circuits on the first failing generator invocation rather than building a partial simulator. All in-tree callers updated (strategy tests, simulator/randomwalk test mods, integration tests, examples). Test helpers using ad-hoc generators bumped to `Result<_, Infallible>` with `let-else` / `unreachable!()` patterns where appropriate.
Codecov Report❌ Patch coverage is
... and 1 file with indirect coverage changes 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Updates the simulation APIs to propagate generator errors instead of panicking, and fixes an always-true underflow guard in TelegraphProcess::next_state so transition probabilities follow the intended Poisson semantics.
Changes:
- Make
RandomWalk::newandSimulator::newfallible (Result<_, E>) by accepting fallible generators and propagating generator errors. - Fix
TelegraphProcess::next_stateunderflow guard (lambda_dt < -11.7) and add an empirical regression test validating the flip rate. - Update in-tree tests/examples to remove
unwrap()/expect()generator wrappers and use?/ explicitOk(...)handling; addFrom<ChainError> for SimulationError.
Reviewed changes
Copilot reviewed 13 out of 25 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/simulation/model_and_randomwalk_tests.rs | Updates unit tests for fallible constructors (but introduces a mispositioned inner attribute). |
| tests/unit/pricing/unified_pricing_test.rs | Converts Monte Carlo tests to return Result and propagates simulator construction errors. |
| tests/unit/chain/random_walk_chain.rs | Updates chain random-walk generator to be fallible and propagate errors via ?. |
| src/strategies/short_put.rs | Updates strategy simulation tests to use fallible Simulator::new without generator unwrap(). |
| src/strategies/short_call.rs | Same as above for short call strategy tests. |
| src/strategies/long_put.rs | Same as above for long put strategy tests. |
| src/strategies/long_call.rs | Same as above for long call strategy tests. |
| src/simulation/simulator.rs | Makes Simulator::new fallible; propagates generator errors; adds short-circuit regression test. |
| src/simulation/randomwalk.rs | Makes RandomWalk::new fallible; adds error-propagation regression test; updates unit tests. |
| src/pricing/telegraph.rs | Fixes transition probability guard and adds empirical flip-rate regression test. |
| src/pricing/monte_carlo.rs | Updates Monte Carlo tests to handle fallible simulator construction. |
| src/error/simulation.rs | Adds From<ChainError> for SimulationError to ease error propagation. |
| src/chains/generators.rs | Updates chain generator tests to use fallible RandomWalk::new. |
| examples/examples_simulation/src/bin/unified_pricing.rs | Updates demo generator and example main to propagate constructor errors (?). |
| examples/examples_simulation/src/bin/strategy_simulator.rs | Updates simulator construction to propagate errors (?). |
| examples/examples_simulation/src/bin/simulator.rs | Updates simulator construction to propagate errors (?). |
| examples/examples_simulation/src/bin/short_put_strategy_simulation.rs | Updates simulator construction to propagate errors (?). |
| examples/examples_simulation/src/bin/short_put_simulation.rs | Updates simulator construction to propagate errors (?). |
| examples/examples_simulation/src/bin/random_walk_chain.rs | Updates random-walk construction to propagate errors (?). |
| examples/examples_simulation/src/bin/random_walk_build_series.rs | Wraps infallible series generator to match new fallible constructor signature. |
| examples/examples_simulation/src/bin/random_walk_build_chain.rs | Updates random-walk construction to propagate errors (?). |
| examples/examples_simulation/src/bin/random_walk.rs | Updates random-walk construction to propagate errors (?). |
| examples/examples_simulation/src/bin/position_simulator.rs | Updates simulator construction to propagate errors (?). |
| examples/examples_simulation/src/bin/long_call_strategy_simulation.rs | Updates simulator construction to propagate errors (?). |
| examples/examples_simulation/src/bin/historical_build_chain.rs | Updates random-walk construction to propagate errors (?). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Owner
Author
|
Thanks for the review. The single inline finding is addressed in 6c01261. |
6 tasks
joaquinbejar
added a commit
that referenced
this pull request
Apr 17, 2026
Change `generator_optionseries` signature from `Vec<Step<Positive, OptionSeries>>` to `Result<Vec<Step<Positive, OptionSeries>>, ChainError>`, propagating errors from the underlying walker, volatility-estimation and chain-construction primitives via `?`. Same precedent as PR #348 for `generator_optionchain` / `generator_positive`, and PR #352 already updated `RandomWalk::new` / `Simulator::new` to accept fallible generators. Init invariant fix: when `prices.is_empty()` or insufficient for Historical walk type, now returns `Ok(vec![init_step])` instead of `vec![]`, matching the contains-init-step contract used by the other chain-family generators. Tests updated accordingly. Removed the dead-code if/else expression at lines 170-174 (its result was discarded); the cleaned-up form binds `volatility` to the unwrapped or default value before the loop. Doc comment switched from `# Panics` to `# Errors`.
This was referenced Apr 17, 2026
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.
Summary
RandomWalk::newandSimulator::neware now fallible, accepting a generatorF: Fn(&WalkParams<X, Y>) -> Result<Vec<Step<X, Y>>, E>and returningResult<Self, E>. Removes the|p| generator_positive(p).unwrap()wrappers introduced in M1: Eliminate .unwrap()/.expect() from src/chains/ (#317) #348 across strategy tests, integration tests, and examples.TelegraphProcess::next_state. Previouslyif lambda_dt < dec!(11.7)was always true (lambda_dt is non-positive for valid inputs), forcingprobability = 1.0every step and making the chain a deterministic alternation. Now guards against the underflow region withif lambda_dt < dec!(-11.7)and computes the standard1 - exp(-lambda * dt)Poisson transition otherwise.From<ChainError> for SimulationError(symmetric with the existing reverse impl) so chain-generator errors propagate naturally through simulation contexts.Test plan
cargo clippy --all-targets --all-features --workspace -- -D warningscargo fmt --all --checkcargo test --all-features --workspace(3724 lib + 416 integration + plotly + static_export combos)cargo build --release+ workspace examplesgenerator_positive(...).unwrap()/generator_optionchain(...).unwrap()wrappers inRandomWalk::new/Simulator::newinvocations acrosssrc/,tests/,examples/test_next_state_empirical_flip_rate_matches_poissonasserts empirical flip rate at(lambda=0.5, dt=0.01)matches1 - exp(-0.005) ≈ 0.00499within 5σ over 100k samples (vs. previous buggy 1.0)RandomWalk::newandSimulator::newverifying error propagation and short-circuit behaviourPublic-surface notes
RandomWalk::newandSimulator::newchange return type fromSelftoResult<Self, E>with a new generic error parameter. Breaking minor — same precedent as PR M1: Eliminate .unwrap()/.expect() from src/strategies/ (#316) #347 (strategy::new) and PR M1: Eliminate .unwrap()/.expect() from src/chains/ (#317) #348 (chain generators), still on the 0.16.x line.TelegraphProcess::next_statesignature unchanged; output distribution corrected (now actually obeys the documented Poisson semantics).Closes #349
Closes #351