Enforces scalability, integration, and compatibility requirements when creating any new module in stochastic-rs — covers stochastic, quant, stats, distributions, copulas, and ai
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Enforces scalability, integration, and compatibility requirements when creating any new module in stochastic-rs — covers stochastic, quant, stats, distributions, copulas, and ai
New Module Integration Rules
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).
1. Where to place new code
Determine the correct top-level module first. Do NOT create a new top-level module without explicit approval.
Code lives in sub-crates, not in the umbrella. The umbrella's own
src/ holds exactly three files — lib.rs, traits.rs, bridges.rs
— and lib.rs merely re-exports each sub-crate under a short alias
(pub use stochastic_rs_stochastic as stochastic;). There is no
src/stochastic.rs, src/quant.rs, src/stats.rs,
src/distributions.rs or src/copulas.rs; that was the pre-split
layout.
The sub-crate split is transparent to users: the umbrella keeps the
existing public API, so a new module in stochastic-rs-quant/src/foo.rs
is reachable as stochastic_rs::quant::foo::… with no umbrella edit at
all. You only touch the umbrella when adding a trait (mirror it in
src/traits.rs — tests/prelude_completeness.rs turns a dropped
re-export into a compile error) or a prelude item.
Adding a submodule within an existing top-level module
Three file patterns exist in the project — choose the simplest that fits:
Pattern A — Leaf file (single file, no subdirectory):
stochastic-rs-stats/src/my_estimator.rs
Use when the implementation is self-contained in one file. Most -stats
and -distributions modules follow this.
Pattern B — Sibling root file + directory (multiple subfiles):
Use when the module has 2+ logical components. This is the dominant
shape in -quant, where nearly every top-level module appears twice in
a directory listing — pricing.rs beside pricing/, calibration.rs
beside calibration/, and so on. Note that the root is a sibling.rs file, not a mod.rs inside the directory.
Pattern C — Directory with mod.rs (when root defines shared types):
Use when the module root itself defines shared types alongside submodule
declarations. In this workspace only mc/ actually follows Pattern
C — noise/fgn/ looks like it should but is Pattern B, with its root
in the sibling noise/fgn.rs and no mod.rs inside the directory.
Both B and C are in active use; pick whichever the surrounding crate
already uses rather than introducing the other one next to it.
Module root must contain
//! doc comment with LaTeX formula summarising the core concept
pub mod declarations for all submodules
pub use re-exports of user-facing types
Shared traits or types that submodules need (define at root, not in a subfile)
Registration
Submodule within an existing module: add pub mod my_module; in
the parent's root .rs (Pattern B) or mod.rs (Pattern C),
alphabetically.
New top-level module in a sub-crate: add pub mod my_module; to
that sub-crate'ssrc/lib.rs — e.g.
stochastic-rs-quant/src/lib.rs. Not the umbrella's. Requires
approval per dev-rules.
Feature-gated module:#[cfg(feature = "my_feature")] pub mod my_module;,
and propagate the feature from the sub-crate to the umbrella — see
feature-flag-management.
A new trait: additionally mirror it in the sub-crate's
src/traits.rsand the umbrella's src/traits.rs. (Caveat:
-stochastic, -quant, -stats, -distributions and -copulas
each have a src/traits.rs; -core and -ai do not — -core's
SeedExt / SimdRng live under src/simd_rng/ and are re-exported
from its lib.rs.) Decide
separately whether it belongs in src/lib.rs's prelude — hub
membership and prelude membership are independent (see CLAUDE.md).
2. Trait integration map
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_map(m, f), sample_par(m) (rayon parallel). GPU backends are selected with .on::<B>(), not by a sample_cuda method
Requires fill_slice() + fork(); sample_matrix() / sample_n() are provided
quant/ modules
Type
Required trait
Effect
Single-underlying option pricer
ModelPricer
price_call(s, k, r, q, tau) / price_put. Vol-surface construction additionally requires the VanillaEuropeanCall marker (which carries vanilla_call_forward); ModelSurface blanket-impls over that, not over ModelPricer
Short-rate / bond model
ShortRatePricer
zero_coupon_price(r0, tau) / zero_yield
Multi-asset or path-dependent pricer
none — convention only
Model params on the struct, query passed to inherent call_put(...) / price_call(...). A shared trait would abstract over nothing
Fourier / characteristic-function model
FourierModelExt
Auto-gets ModelPricerandVanillaEuropeanCall, hence 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
11 required methods; sample() / fit() / inversion are defaulted. Tau is tau() / set_tau() accessors, not a kendall_tau() method. See copula-bivariate
Keep internal helpers pub(crate) or private. Match the pattern of sibling modules in the same top-level module.
7. Integration with existing pipelines
Pricing pipeline (quant)
If the module produces a pricer, verify it works with:
build_surface_from_model<M: ModelSurface + ?Sized>(model: &M, s, r, q, strikes, maturities)
— vol-surface construction. Generic, not&dyn, and the bound is
ModelSurface, not ModelPricer: the Black inversion is only
meaningful for a European vanilla call, which is what ModelSurface's
VanillaEuropeanCall supertrait asserts.
build_surface_from_calibration<C: ToModel>(calibration: &C, s, r, q, strikes, maturities) where C::Model: ModelSurface — calibration → vol-surface. Note the
extra where clause: implementing ToModel is not enough on its own.
Calendar pipeline (quant)
If the module uses dates, verify it works with:
BusinessDayConvention::adjust(date, &calendar) — business day adjustment
TimeExt::tau_with_dcc(dcc) — year fraction from dates
Process pipeline (stochastic)
If the module defines a stochastic process, verify:
sample() returns the correct Output type
sample_par(m) works (all fields must be Send + Sync)
Noise inputs follow the SeedExt pattern if seeded
Distribution pipeline (distributions)
If the module defines a distribution, verify:
DistributionSampler<T> is implemented for bulk sampling
fill_slice() uses SIMD where possible
sample_matrix() works for multi-core benchmarks
8. Feature gating
If the module requires an optional external dependency:
Add dependency with optional = true in Cargo.toml
Add feature: my_feature = ["dep:my_crate"]
Gate module: #[cfg(feature = "my_feature")] pub mod my_module;
Gate imports in shared code: #[cfg(feature = "my_feature")]
Default features remain default = [].
9. Testing and benchmarks
Every new module must include:
Comparison test (tests/my_module_test.rs):
Validate output against reference (Python, R, MATLAB, or paper's tables/figures)
Test trait integrations (e.g., custom CalendarExt impl, sample_par correctness)
Test edge cases (zero maturity, degenerate parameters, boundary conditions)
Criterion benchmark (benches/my_module.rs):
Benchmark the hot path
Register in Cargo.toml: [[bench]] name = "my_module" harness = false
Integration test — verify end-to-end with existing pipelines where applicable
10. Documentation
Every new file must have:
//! doc header citing the paper/reference (title, authors, DOI or arXiv ID)
LaTeX formula in the doc header
/// docs on all public items
Quick checklist
Before marking a new module as done:
Placed in the correct sub-crate (stochastic-rs-stochastic, -quant, -stats, -distributions, -copulas, -core, -ai) — see §1; the umbrella src/ is not where code goes
Module root has LaTeX doc header and re-exports
Registered in the parent module's .rs file (alphabetical order)
All numerical code generic over FloatExt, arrays use ndarray
Correct domain traits implemented (see §2 trait integration map)
Extensibility points use traits, not concrete types (see §3)
Debug, Clone, Display, Default derives on public types
Send + Sync verified (no Rc, Cell, or unshared interior mutability)