regit-svi 2.0.0

Arbitrage-free SVI volatility surfaces in pure Rust. Raw, Jump-Wings and SSVI parametrisations, calibration, and static-arbitrage checks. Zero dependencies.
Documentation
<!-- Copyright 2026 Regit.io — Nicolas Koenig -->
<!-- SPDX-License-Identifier: Apache-2.0 -->

# Contributing to regit-svi

Thank you for improving regit-svi. The crate sits on a model-validation
boundary, so a contribution is judged on mathematical scope, evidence, and
reproducibility as well as code quality.

By participating, follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). Report a
suspected vulnerability or exploitable numerical defect privately through
[SECURITY.md](SECURITY.md).

## Before opening a change

For a bug, first reduce the failure to finite decimal input parameters. Include
the exact crate version, target, toolchain, requested/effective numerical
domain, tolerances, status/evidence, and termination record.

For a public API or formula change, open an issue before investing in a large
patch. State:

- the user problem and intended scope;
- the primary mathematical source and exact theorem/equation;
- whether the proposed condition is necessary, sufficient, both, or numerical;
- compatibility and migration consequences;
- adversarial boundary and degeneration cases;
- expected normal, build, and development dependency impact.

Small documentation corrections and isolated tests can go directly to a pull
request.

## Local setup

The shipped library MSRV is Rust 1.85. Criterion 0.8 requires Rust 1.86 or
newer, so all-target development uses the pinned repository toolchain or a
current stable compiler. The repository toolchain also installs rustfmt,
Clippy, and wasm32-unknown-unknown.

Minimum Rust loop:

~~~sh
cargo fmt --all --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets --locked
cargo test --doc --locked
RUSTDOCFLAGS="-D warnings -D missing-docs -D rustdoc::broken-intra-doc-links -D rustdoc::bare-urls" \
  cargo doc --no-deps --locked
~~~

The justfile exposes the same gates:

~~~sh
just fmt-check
just lint
just test
just doctest
just doc
~~~

Checks that need separately installed tools:

~~~sh
cargo deny check --hide-inclusion-graph
cargo shear --deny-warnings --check-test-targets
cargo build --lib --target wasm32-unknown-unknown --release --locked
cargo package --locked --allow-dirty
~~~

Verify the library MSRV independently:

~~~sh
rustup toolchain install 1.85.0 --profile minimal
cargo +1.85.0 check --lib --locked
~~~

Do not run all development targets at the library MSRV: that would test
Criterion's compiler contract rather than the shipped library contract.

## Repository structure

| Path | Responsibility |
| --- | --- |
| src/market | validated coordinates, quotes, conventions |
| src/smile | Raw, Jump-Wings, and conversions |
| src/surface | SSVI, term structure, interpolation |
| src/no_arb | butterfly/calendar diagnostics and evidence |
| src/calibration | configs, fits, reports |
| src/density.rs | log-strike density and bounded integration |
| src/numerics | private solvers |
| tests | cross-module, published, adversarial, and oracle checks |
| tools/oracle | independent high-precision environment |
| benches | Criterion benchmarks |
| MATH.md | normative formula/evidence/traceability contract |

Keep numerical primitives private unless a separate stable numerical-utilities
contract is intentionally designed.

## Mathematical contribution standard

Every new or changed formula must have:

1. a primary citation, with equation/theorem/section when available;
2. a derivation or normalization in MATH.md;
3. a statement of parameter and support domains;
4. strict/non-strict boundary behavior;
5. flat, zero, singular, and non-identifiable cases;
6. binary64 evaluation strategy and failure behavior;
7. a formula-to-module-to-test traceability entry;
8. an independent oracle case when ordinary binary64 self-comparison would be
   circular or weak.

Do not strengthen a source while paraphrasing it. In particular:

- failure of a necessary condition is a violation; passing is inconclusive;
- passing a sufficient condition supports freedom; failure is inconclusive;
- a finite scan says nothing outside its effective domain;
- optimizer convergence is not a global optimum;
- arbitrary precision is not global verification;
- a value within a recorded uncertainty band is indeterminate.

ArbitrageAssessment status and evidence are independent axes. New APIs must
preserve both when aggregating or transforming a result.

## Numerical implementation standard

Prefer stable algebra before adding tolerances. Examples already used in the
crate include hypot, exp_m1, small-argument series, transformed feasible
coordinates, sign-preserving root brackets, and explicit scaled uncertainty
bands.

For a tolerance:

- name the mathematical boundary it protects;
- state whether it is absolute, relative, ULP-based, or combined;
- scale it from relevant quantities rather than unrelated constants;
- test just inside, at, and just outside the boundary;
- expose it in evidence/configuration when it changes caller conclusions.

Validated constructors and fallible public workflows must reject non-finite
input. Infallible formula kernels that intentionally accept raw `f64` must
state their finite/model-domain preconditions and IEEE-754 propagation
behavior. Distinguish a mathematical domain failure from floating-point
ill-conditioning. Do not silently sort, clamp, or repair unless that behavior
is part of the documented contract and the final result is recomputed and
reported after repair.

Library code forbids unsafe Rust. Avoid panic, unwrap, and expect on a public
input path. A private invariant should still return a typed failure when a
floating-point operation can invalidate it.

## Testing

Add the narrowest test that would fail before the change, then add boundary
coverage proportional to the risk:

- unit tests for formulas, errors, and private numerical states;
- integration tests for public workflows and evidence propagation;
- published-source fixtures for recognizable literature cases;
- property tests for invariants over valid generated domains;
- oracle fixtures for cancellation, overflow, extreme scale, or theorem
  boundaries;
- doc tests for public examples.

Do not weaken tolerances just to admit a result. Explain the numerical scale
and compare against an independent reference. Avoid hand-maintained global test
counts in documentation because they become stale.

Property tests must be deterministic under failure reproduction. Print or
retain the seed/case, and avoid assumptions so restrictive that the important
boundaries are never generated.

## High-precision oracle

Set up the isolated environment as documented in
[tools/oracle/README.md](tools/oracle/README.md). The usual no-write gate is:

~~~sh
.oracle-venv/bin/python tools/oracle/check.py
.oracle-venv/bin/python -m unittest discover -s tools/oracle -p 'test_*.py'
.oracle-venv/bin/ruff check --config tools/oracle/pyproject.toml tools/oracle
.oracle-venv/bin/ruff format --check --config tools/oracle/pyproject.toml tools/oracle
~~~

Fixture generation consumes decimal strings and emits decimal strings.
Changing a fixture with the write mode requires a reviewed change to its
formula, source, precision, or tolerance. Never update expected values merely
because Rust output changed.

Oracle dependencies are external tooling. They must not enter Cargo normal,
build, runtime, test-harness, example, or benchmark graphs.

## Documentation

Public items need focused rustdoc, an Errors section when fallible, and a
runnable example where useful. Keep these layers consistent:

- README: user choice, first workflow, scope, and evidence warning;
- MATH: exact derivation and implementation contract;
- MIGRATION: before/after breaking changes;
- CHANGELOG: release-level effect;
- BENCHMARKS: reproducible performance claims;
- source rustdoc: item-local semantics.

Use relative links for repository files. Preserve the established copyright,
SPDX, license, notice, author/contact, and branding text exactly.

## Dependencies

The normal and build dependency graph is intentionally empty. A proposal to
add either needs a concrete benefit, alternatives analysis, license/advisory
review, MSRV and WASM impact, and explicit maintainer approval.

Development dependencies must be used, permissively licensed under deny.toml,
and audited with cargo-deny and cargo-shear. Commit Cargo.lock changes that
belong to the patch. Do not mix an unrelated dependency refresh into a
mathematical change.

## Benchmarks

Follow [BENCHMARKS.md](BENCHMARKS.md). Benchmark changes should establish a
stable workload, use validated pre-built inputs outside the timed loop when
construction is not under study, and report environment plus statistical
uncertainty. Performance never justifies changing a theorem boundary or
evidence label without an explicit contract change.

## Pull requests

Keep a pull request reviewable and single-purpose. The description should
include:

- problem and user-visible outcome;
- source/formula impact;
- public API and migration impact;
- tests and oracle evidence;
- benchmark impact when relevant;
- dependency/MSRV/WASM impact;
- known limitations and evidence strength.

Complete the repository pull-request checklist. A reviewer should be able to
trace an output from input validation through formula and numerical algorithm
to status/evidence and test.

Do not commit generated benchmark HTML, local virtual environments, target
artifacts, editor state, credentials, proprietary market data, or unreviewed
oracle fixture rewrites.