Skip to content

fix(simulation,pricing): fallible RandomWalk/Simulator constructors + Telegraph guard (#349, #351)#352

Merged
joaquinbejar merged 3 commits intomainfrom
issue-349-fallible-simulation-generators-and-telegraph-fix
Apr 17, 2026
Merged

fix(simulation,pricing): fallible RandomWalk/Simulator constructors + Telegraph guard (#349, #351)#352
joaquinbejar merged 3 commits intomainfrom
issue-349-fallible-simulation-generators-and-telegraph-fix

Conversation

@joaquinbejar
Copy link
Copy Markdown
Owner

Summary

  • Make Simulator::new and RandomWalk::new accept fallible generators #349RandomWalk::new and Simulator::new are now fallible, accepting a generator F: Fn(&WalkParams<X, Y>) -> Result<Vec<Step<X, Y>>, E> and returning Result<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.
  • Fix lambda_dt branch in TelegraphProcess::next_state (always-true guard) #351 — Fixes the inverted underflow guard in TelegraphProcess::next_state. Previously if lambda_dt < dec!(11.7) was always true (lambda_dt is non-positive for valid inputs), forcing probability = 1.0 every step and making the chain a deterministic alternation. Now guards against the underflow region with if lambda_dt < dec!(-11.7) and computes the standard 1 - exp(-lambda * dt) Poisson transition otherwise.
  • Adds 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 warnings
  • cargo fmt --all --check
  • cargo test --all-features --workspace (3724 lib + 416 integration + plotly + static_export combos)
  • cargo build --release + workspace examples
  • Acceptance grep — no generator_positive(...).unwrap() / generator_optionchain(...).unwrap() wrappers in RandomWalk::new / Simulator::new invocations across src/, tests/, examples/
  • Telegraph regression — new test test_next_state_empirical_flip_rate_matches_poisson asserts empirical flip rate at (lambda=0.5, dt=0.01) matches 1 - exp(-0.005) ≈ 0.00499 within 5σ over 100k samples (vs. previous buggy 1.0)
  • Negative tests for RandomWalk::new and Simulator::new verifying error propagation and short-circuit behaviour

Public-surface notes

Closes #349
Closes #351

…#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
Copy link
Copy Markdown

codecov bot commented Apr 17, 2026

Codecov Report

❌ Patch coverage is 81.81818% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/error/simulation.rs 0.00% 2 Missing ⚠️
Files with missing lines Coverage Δ
src/chains/generators.rs 84.37% <ø> (ø)
src/pricing/monte_carlo.rs 73.17% <ø> (ø)
src/pricing/telegraph.rs 81.35% <100.00%> (+0.84%) ⬆️
src/simulation/randomwalk.rs 56.60% <100.00%> (+0.83%) ⬆️
src/simulation/simulator.rs 88.31% <100.00%> (+0.31%) ⬆️
src/strategies/long_call.rs 70.88% <ø> (ø)
src/strategies/long_put.rs 71.65% <ø> (ø)
src/strategies/short_call.rs 74.00% <ø> (ø)
src/strategies/short_put.rs 72.36% <ø> (ø)
src/error/simulation.rs 12.00% <0.00%> (-1.05%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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::new and Simulator::new fallible (Result<_, E>) by accepting fallible generators and propagating generator errors.
  • Fix TelegraphProcess::next_state underflow 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 ? / explicit Ok(...) handling; add From<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.

Comment thread tests/unit/simulation/model_and_randomwalk_tests.rs
@joaquinbejar
Copy link
Copy Markdown
Owner Author

Thanks for the review. The single inline finding is addressed in 6c01261.

@joaquinbejar joaquinbejar merged commit 41ac310 into main Apr 17, 2026
11 checks passed
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`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix lambda_dt branch in TelegraphProcess::next_state (always-true guard) Make Simulator::new and RandomWalk::new accept fallible generators

2 participants