2 releases
| new 0.1.1 | Feb 17, 2026 |
|---|---|
| 0.1.0 | Feb 17, 2026 |
#268 in Math
210KB
5.5K
SLoC
sanos
Rust implementation of SANOS: smooth, arbitrage-aware option surface calibration.
This crate provides:
- market data structures (
OptionBook,OptionChain,CallQuote) - calibration pipeline (
calibrate,calibrate_with_stats) - resulting surface object (
SanosSurface)
API docs: https://docs.rs/sanos
Installation
[dependencies]
sanos = "0.1"
Input Conventions
- Quotes are forward-normalized call prices in
[0, 1]. - Strikes are forward moneyness (
k > 0). - Maturities must be strictly increasing in
OptionBook. - Use at least 2 maturities if you want to query interpolated surface prices (
surface.call).
Quick Start
use sanos::calibration::{calibrate, CalibrationConfig};
use sanos::error::SanosResult;
use sanos::market::OptionBook;
fn run(book: &OptionBook, cfg: &CalibrationConfig) -> SanosResult<f64> {
let surface = calibrate(book, cfg)?;
surface.call(1.0, 1.0)
}
End-to-End Example (OptionBook + Config)
use sanos::backbone::{bs_call_forward_norm, BackboneConfig, BsTimeChangedConfig};
use sanos::calibration::{calibrate, CalibrationConfig, ConvexOrderValidationMode};
use sanos::error::SanosResult;
use sanos::fit::FitConfig;
use sanos::grid::StrikeGridPolicyConfig;
use sanos::interp::TimeInterpConfig;
use sanos::market::{CallQuote, OptionBook, OptionChain};
fn build_synthetic_book() -> SanosResult<OptionBook> {
// Two maturities with synthetic ATM total variances.
let maturities = [0.5, 1.0];
let total_vars = [0.04, 0.09];
let strikes = [0.8, 0.9, 1.0, 1.1, 1.2];
let mut chains = Vec::new();
for (t, w) in maturities.into_iter().zip(total_vars) {
let mut quotes = Vec::new();
for k in strikes {
let mid = bs_call_forward_norm(k, w)?;
let spread = 0.01;
let bid = (mid - 0.5 * spread).clamp(0.0, 1.0);
let ask = (mid + 0.5 * spread).clamp(0.0, 1.0);
quotes.push(CallQuote::new(k, bid, ask, 1.0)?);
}
chains.push(OptionChain::new(t, quotes)?);
}
OptionBook::new(chains)
}
fn build_config() -> CalibrationConfig {
CalibrationConfig {
backbone: BackboneConfig::BsTimeChanged(BsTimeChangedConfig::default()),
grid: StrikeGridPolicyConfig::default(),
fit: FitConfig::default(),
time_interp: TimeInterpConfig::default(),
convex_order_validation: ConvexOrderValidationMode::Error,
}
}
fn main() -> SanosResult<()> {
let book = build_synthetic_book()?;
let cfg = build_config();
let surface = calibrate(&book, &cfg)?;
let c = surface.call(0.75, 1.0)?;
println!("Interpolated call(T=0.75, K=1.0) = {c:.6}");
Ok(())
}
Config Example
use sanos::backbone::{BackboneConfig, BsTimeChangedConfig};
use sanos::calibration::{CalibrationConfig, ConvexOrderValidationMode};
use sanos::fit::FitConfig;
use sanos::grid::StrikeGridPolicyConfig;
use sanos::interp::TimeInterpConfig;
let cfg = CalibrationConfig {
backbone: BackboneConfig::BsTimeChanged(BsTimeChangedConfig::default()),
grid: StrikeGridPolicyConfig::default(),
fit: FitConfig::default(), // default solver = Microlp
time_interp: TimeInterpConfig::default(),
convex_order_validation: ConvexOrderValidationMode::Error,
};
Feature Flags
lp-microlp(default): pure-Rust LP solver backend.lp-cbc: CBC backend viagood_lp/lp-solvers(requires CBC runtime).iv-jaeckel(default): implied-vol inversion support.serde: serialization support for config/runtime types.
When selecting a solver in configuration, the matching crate feature must be enabled.
Scope
This crate is self-contained and usable as-is for building option books, calibrating SANOS surfaces, and querying interpolated prices.
Roadmap
Additional tooling and integrations may be published later, after further validation.
Research Attribution
This crate is an independent implementation of the SANOS methodology described in:
- "SANOS: Smooth strictly Arbitrage-free Non-parametric Option Surfaces" (arXiv:2601.11209)
- URL: https://arxiv.org/abs/2601.11209
The code in this repository is original Rust code released under MIT (LICENSE), and is not a copy of the paper text.
Non-Affiliation
This project is not affiliated with, endorsed by, or maintained by the authors of the SANOS paper.
Pre-publish Checklist
cargo test -p sanos
cargo test -p sanos --no-default-features
RUSTDOCFLAGS="-D warnings" cargo doc -p sanos --no-deps
cargo package -p sanos
Dependencies
~6–12MB
~261K SLoC