Enforces scalability, integration, and compatibility requirements when creating any new module in stochastic-rs — covers stochastic, quant, stats, distributions, copulas, and ai
Every new module must be scalable (trait-based extensibility), integrated (works with existing traits and pipelines), and compatible (derives, bounds, API conventions match the rest of the codebase).
Determine the correct top-level module first. Do NOT create a new top-level module without explicit approval.
| Domain | Top-level module | Registration file | Examples |
|---|---|---|---|
| Stochastic processes (diffusion, jump, volatility, noise, interest rate, autoregressive) | stochastic/ | src/stochastic.rs | GBM, Heston, CIR, fBM, GARCH |
| Quantitative finance (pricing, bonds, calibration, calendar, FX, portfolio, strategies, vol-surface) | quant/ | src/quant.rs | BSM pricer, schedule builder, FX forward |
| Statistical estimators & tests (MLE, KDE, stationarity, normality, spectral) | stats/ | src/stats.rs | Gaussian KDE, ADF test, Hurst estimator |
| Probability distributions | distributions/ | src/distributions.rs | Normal, Alpha-stable, NIG |
| Copula models | copulas/ | src/copulas.rs | Clayton, Gaussian, Student-t |
| Neural network / AI models | ai/ (feature-gated) | src/lib.rs | Vol calibration NN |
Three file patterns exist in the project — choose the simplest that fits:
Pattern A — Leaf file (single file, no subdirectory):
src/stats/my_estimator.rs
Use when the implementation is self-contained in one file. Most stats/ and distributions/ modules follow this.
Pattern B — Root file + directory (multiple subfiles):
src/quant/my_module.rs ← module root: doc header, pub mod, re-exports, shared traits
src/quant/my_module/
engine.rs
types.rs
Use when the module has 2+ logical components. Most quant/ modules (pricing, calibration, calendar, fx, bonds, vol_surface) follow this.
Pattern C — Directory with mod.rs (when root defines shared types):
src/stochastic/mc/
mod.rs ← defines McEstimate<T> + pub mod declarations
lsm.rs
mlmc.rs
Use when the module root itself defines shared types alongside submodule declarations. The mc/ module and noise/fgn/ follow this.
//! doc comment with LaTeX formula summarising the core conceptpub mod declarations for all submodulespub use re-exports of user-facing typespub mod my_module; in the parent's .rs file (alphabetical order)pub mod my_module; in src/lib.rs (requires approval per dev-rules)#[cfg(feature = "my_feature")] pub mod my_module;Before writing code, determine which existing traits the new types should implement.
stochastic/ modules| Type | Required trait | Effect |
|---|---|---|
| Any stochastic process | ProcessExt<T: FloatExt>: Send + Sync | Gets sample(), sample_par(m) (rayon parallel), sample_cuda(m) |
| Process with Malliavin support | MalliavinExt<T> or Malliavin2DExt<T> | Malliavin derivative computation |
| Probability distribution | DistributionExt | CF, PDF, CDF, moments |
| SIMD-accelerated distribution | DistributionSampler<T> (from distributions.rs) | Bulk fill_slice() + sample_matrix() |
quant/ modules| Type | Required trait | Effect |
|---|---|---|
| Option / derivative pricer | TimeExt + PricerExt | Date-aware pricing, calculate_call_put(), implied vol |
| Pricing model for (K, T) grids | ModelPricer | Enables vol-surface construction via ModelSurface blanket impl |
| Fourier / characteristic-function model | FourierModelExt | Auto-gets ModelPricer → ModelSurface via blanket impls |
| Calibration result | ToModel | Connects to build_surface_from_calibration() pipeline |
| Holiday / business-day calendar | CalendarExt | Plugs into BusinessDayConvention::adjust() and ScheduleBuilder |
| Type needing tau from dates | Use TimeExt::tau_with_dcc(DayCountConvention) | Proper day-count instead of hardcoded /365.0 |
copulas/ modules| Type | Required trait | Effect |
|---|---|---|
| Bivariate copula | BivariateExt | sample(), fit(), pdf(), cdf(), Kendall's tau |
| Multivariate copula | MultivariateExt | sample(), fit(), pdf(), cdf() |
FourierModelExt ──blanket──▸ ModelPricer ──blanket──▸ ModelSurface
Implement the lowest-level trait; upstream is automatic.
When a new module accepts a pluggable component, define or reuse a trait.
Pattern (from BusinessDayConvention::adjust):
pub fn my_function(calendar: &(impl CalendarExt + ?Sized)) -> NaiveDate {
// works with &Calendar AND &dyn CalendarExt (trait objects)
}
The + ?Sized bound is required to also accept &dyn Trait.
If the module creates a new extensibility point:
my_module.rs)&(impl MyTrait + ?Sized) in functions, not the concrete typeEvery new pub struct and pub enum must have:
| Requirement | How | Why |
|---|---|---|
Debug | #[derive(Debug)] | Debugging, error messages |
Clone | #[derive(Clone)] | Composability — users clone pricers, processes, calendars |
Send + Sync | Automatic for simple types; verify with Box<dyn …> or Rc | Required for ProcessExt, sample_par(), rayon |
Display (enums) | impl Display | Logging, error messages |
Default (where meaningful) | #[derive(Default)] + #[default] on variant | Ergonomic construction |
Copy (small value types) | #[derive(Copy)] | Enums and small structs without heap data |
Eq + Hash (identifier types) | #[derive(PartialEq, Eq, Hash)] | Map keys, dedup, comparisons |
Do NOT add Serialize / Deserialize — serde is not a dependency.
| Rule | Detail |
|---|---|
| Generic float | All numerical structs/functions use T: FloatExt. Never hardcode f64. Use T::from_f64_fast() for constants. |
| Arrays | Use ndarray::Array1<T>, Array2<T>. Never Vec<T> for numerical data. |
| Day fractions | Use DayCountConvention::year_fraction() or TimeExt::tau_with_dcc(). Never hardcode /365.0 or /360.0. |
| Annualisation | Accept the factor as a parameter. Never hardcode 252.0 or 365.0. |
| Random sampling | Use the project's SimdRng / SimdFloatExt infrastructure for SIMD-accelerated generation. |
| Complex numbers | Use num_complex::Complex<T>. |
In the module root, re-export user-facing types only:
pub use engine::MyEngine;
pub use types::{MyConfig, MyResult};
Keep internal helpers pub(crate) or private. Match the pattern of sibling modules in the same top-level module.
If the module produces a pricer, verify it works with:
build_surface_from_model(&dyn ModelPricer, …) — vol-surface constructionbuild_surface_from_calibration(&dyn ToModel, …) — calibration → vol-surfaceIf the module uses dates, verify it works with:
BusinessDayConvention::adjust(date, &calendar) — business day adjustmentScheduleBuilder::new(…).calendar(cal).build() — schedule generationTimeExt::tau_with_dcc(dcc) — year fraction from datesIf the module defines a stochastic process, verify:
sample() returns the correct Output typesample_par(m) works (all fields must be Send + Sync)SeedExt pattern if seededIf the module defines a distribution, verify:
DistributionSampler<T> is implemented for bulk samplingfill_slice() uses SIMD where possiblesample_matrix() works for multi-core benchmarksIf the module requires an optional external dependency:
optional = true in Cargo.tomlmy_feature = ["dep:my_crate"]#[cfg(feature = "my_feature")] pub mod my_module;#[cfg(feature = "my_feature")]Default features remain default = [].
Every new module must include:
Comparison test (tests/my_module_test.rs):
CalendarExt impl, sample_par correctness)Criterion benchmark (benches/my_module.rs):
Cargo.toml: [[bench]] name = "my_module" harness = falseIntegration test — verify end-to-end with existing pipelines where applicable
Every new file must have:
//! doc header citing the paper/reference (title, authors, DOI or arXiv ID)/// docs on all public itemsBefore marking a new module as done:
stochastic/, quant/, stats/, distributions/, copulas/).rs file (alphabetical order)FloatExt, arrays use ndarrayDebug, Clone, Display, Default derives on public typesSend + Sync verified (no Rc, Cell, or unshared interior mutability)/365.0, /360.0, or /252.0Cargo.tomlcargo clippy clean