Skip to content

v2.0.0

Choose a tag to compare

@dancixx dancixx released this 11 May 16:10
· 140 commits to main since this release

stochastic-rs v2.0.0

First stable 2.0 release. Six prereleases (beta.1beta.2beta.3rc.0rc.1rc.2) consolidated; the surface and numerics are identical to v2.0.0-rc.2. Changes since v2.0.0-rc.2 are docs-site and CI polish only (commits cd4f874405f094).

What v2 brings

Workspace. Single stochastic-rs crate split into a 9-crate Cargo workspace at edition 2024 (stochastic-rs-core, -distributions, -stochastic, -copulas, -stats, -quant, -ai, -viz, -py). The umbrella stochastic-rs re-exports everything — every existing import path still works. Sub-crate-only consumers can now skip the quant/stats/ai compilation cost.

New trait surface.

  • prelude with 20 items in 5 groups (trait core / pricing / calibration / instrument-engine / option types).
  • Calibrator / CalibrationResult are now Result-based with type Params and type Error = anyhow::Error. 9 Calibrator + 12 CalibrationResult impls.
  • GreeksExt covers first- and second-order Greeks (vanna / charm / volga / veta), aggregated into a named-field Greeks struct; MC pricers override greeks() for single-pass consistency.
  • Instrument / PricingEngine (AnalyticBSEngine, AnalyticHestonEngine) — QuantLib-style decoupling between payoff and valuation.
  • DistributionExt defaults flipped from silent 0.0 to unimplemented!(). 18/19 distributions provide closed-form pdf / cdf / cf / moments.
  • PricerExt::implied_volatility default 0.0f64::NAN.

New primitives.

  • Reactive market cache (Cached<T> / MarketObserver).
  • FX module (delta conventions, ATM conventions, Vanna-Volga smile).
  • Variance swap (Carr-Madan replication + Brockhaus-Long Heston closed form + Bernard-Cui discrete correction).
  • Total Return Swap (proper TR forward F_TR(t) = S · exp(r t)).
  • interest::lmm::Lmm — drift-coupled LIBOR Market Model (spot-LIBOR measure, log-Euler positivity-preserving).
  • numerics namespace (HaltonSeq, SobolSeq, RlKernel, MarkovLift, Mlmc).
  • HypothesisTest trait + 8 implementations (ADF, KPSS, ERS, PhillipsPerron, LeybourneMcCabe, JarqueBera, AndersonDarling, ShapiroFrancia).

Python (stochastic-rs-py). 210-entry PyO3 surface (was 102 in rc.0): 198 classes + 12 pyfunctions across distributions, stochastic, quant pricers, Fourier engines, calibrators, vol surface, risk, microstructure, curves, factors, copulas, stats. All wrappers seed-aware via Deterministic::new(seed). AI bindings deferred to 2.x.

Silent-correctness fixes

If you held cached results from 1.x or any 2.0.0-beta.*, please re-compute:

  • tau * 365-vs-years bug in BSMPricer / HestonPricer / SabrPricer / HestonStochCorrPricer / AsianPricer / Vasicek-bond implied vols (v1 IVs were understated by √365).
  • variance_swap::fair_strike_replication sign error on rT and ln(K0/S0) correction.
  • bonds/cir.rs closed form: A·exp(+B·r)A·exp(-B·r) (ZCB was increasing with the short rate).
  • bonds/hull_white.rs rewritten against Brigo-Mercurio §3.3.2 / Hull-White (1990) extended-Vasicek using a DiscountCurve (v1 used Utc::now().year() in the price — non-deterministic).
  • calibration/heston_stoch_corr.rslet _ = slsqp::minimize(...) discarded the calibrated params; HscmCalibrationResult returned the initial guess. Now carries real converged + final_objective.
  • calibration/levy.rs NIG calibration wrapped NIG params in CGMYFourier with hardcoded y = 0.5. New NigFourier (Barndorff-Nielsen 1997 ChF) and rewired NIG path.
  • pricing/heston_stoch_corr.rs characteristic function used iu·r in the drift instead of iu·(r−q). Threaded q through the ODE drift + ModelPricer impl.
  • pricing/rbergomi.rs discarded the dividend yield. Drift now uses (r-q-0.5·v)·dt; RBergomiCalibrator::with_dividend_yield(q) builder added.
  • microstructure/kyle.rs multi-period Kyle 1985 backward recursion was non-canonical (disagreed with single_period_kyle at n_periods = 1). Re-derived against Cetin-Larsen 2023 (arXiv:2307.09392).
  • vol_surface/ssvi.rs::is_calendar_spread_free only checked the ATM term structure; missed off-ATM violations. Now verifies the full Gatheral & Jacquier 2014 Theorem 4.2 over a strike grid.
  • pricing/fourier.rs::CarrMadanPricer::price_call silently returned 0.0 for out-of-grid log-strikes — now returns f64::NAN so calibration objectives are poisoned and detection is forced; new strike_in_grid() helper.
  • portfolio/optimizers.rs::empirical_cvar alpha is the tail proportion (0.05 = worst 5%). assert!(alpha < 0.5) so users passing confidence-style 0.95 crash loudly.
  • traits/time.rs::tau_or_from_dates / tau_with_dcc return f64::NAN (was panic) when neither tau nor dates are set.
  • Heston switched to "Little Heston Trap" form (Albrecher-Mayer-Schoutens-Tistaert 2007) for long-maturity high-|ρ| principal-branch logarithm continuity.

Build & packaging

  • Edition 2024 across the workspace.
  • Feature flags propagate correctly: gpu, cuda-native, metal, accelerate, openblas, python. If you previously built with --features gpu on v1 expecting GPU samplers, re-build on v2 — you'll now actually get them.
  • docs.rs config pinned to ["openblas", "ai", "yahoo"] (all-features = true was pulling native GPU SDKs and breaking the docs build).
  • statrs is gone from production dependencies (closed-form rewrites in stochastic-rs-distributions); kept as [dev-dependencies] for cross-validation tests only.
  • PyPI workflow now builds macos-13 + x86_64 alongside aarch64 — Intel Mac users can pip install stochastic-rs again.

SKILLs

16 maintenance SKILLs shipped in .claude/skills/ to keep extensions consistent:

  • Tier 1 (release-level): release-checklist, feature-flag-management, calibration-pattern, greeks-pattern.
  • Tier 2 (domain): add-diffusion-process, add-fractional-process, add-jump-process, adding-distribution, adding-python-binding, stats-estimator.
  • Tier 3 (niche): copula-bivariate, add-gpu-sampler, add-mc-variance-reduction, vol-surrogate-nn, integration-test-writing, bench-writing.

Migration checklist

  • Bump stochastic-rs = "2.0" in Cargo.toml.
  • Add ? after every calibrator.calibrate(None) (now Result).
  • Replace pricer.derivatives()[i] reads with pricer.greeks().delta / .gamma / .vega / etc.
  • Replace iv == 0.0 checks with iv.is_nan().
  • If you implement CalibrationResult: add type Params and fn params(&self).
  • If you implement DistributionExt: override every method you call (defaults now unimplemented!()).
  • If you stored implied vols from BSMPricer / HestonPricer / SabrPricer: recompute (v1 IVs were understated by √365).

Install

[dependencies]
stochastic-rs = "2.0"
pip install stochastic-rs==2.0.0

Per-rc rollup: rc.0 · rc.1 · rc.2

Full Changelog: v1.5.0...v2.0.0