RustyQLib 0.0.3

RustyQLib is a lightweight yet robust quantitative finance library designed to price derivatives and perform risk analysis
Documentation
# Runnable examples

One file per equity product. Each builds the product in Rust (no JSON),
prices it on every applicable engine and model, prints NPV and Greeks in a
single table, and verifies the identities that must hold for that product.

```bash
cargo run --release --example vanilla_option
```

Release mode matters: the Monte Carlo examples run 50k–100k paths.

| Example | Product | What it demonstrates |
|---|---|---|
| `vanilla_option` | European / American vanilla | all four engines side by side; American early-exercise premium; put-call parity; implied vol round trip; analytic vs bumped Greeks |
| `binary_option` | Cash- and asset-or-nothing digitals | both settlement types; cash scaling; the replication identity across all Greeks; digital risk blowing up near expiry |
| `binomial_tree` | All six tree schemes compared | pricing table across products, log-log convergence diagrams (HTML), per-scheme order/performance stats, diagnostic engine with exercise boundary |
| `barrier_option` | All eight barrier types | analytic vs FD vs bridge-corrected MC; in-out parity; barrier sweep; skew effect under local vol |
| `asian_option` | Asian options | geometric (exact) vs arithmetic (Turnbull-Wakeman); the geometric control variate cutting MC variance ~15x; floating strike; AM-GM ordering |
| `forward_start_option` | Forward-start options | Rubinstein closed form vs MC; **the forward smile** (Heston vs Black-Scholes); strike-fraction and fixing-date sweeps |
| `autocallable_option` | Autocallable note with coupon | GBM vs local vol vs Heston; coupon / barrier / frequency sensitivity; exact degenerate cases (Phoenix conditional/memory coupons via `.phoenix(...)`) |
| `heston_option` | Heston stochastic vol | semi-analytic characteristic function vs MC; binaries and barriers; **how rho and vol-of-vol shape the smile** |
| `rainbow_option` | Multi-asset rainbows | best-of, worst-of, spread (Kirk), basket (moment matching), exchange (Margrabe); correlation sweep; per-asset Greeks |
| `local_vol_calibration` | Local vol workflow | quotes -> implied vols -> surface -> Dupire -> reprice, end to end with checks at each step |
| `futures_option` | Options on futures (Black-76) | discounted vs margined settlement; zero rho when margined; Black-76 on the forward = spot Black-Scholes; strike skew |
|  `convert_format` (needs `--features xml`) | JSON <-> XML conversion | transcoding contract documents between the two supported formats |
| `dividends_and_borrow` | Carry inputs | borrow cost as carry; escrowed vs jump dividend models per engine; where the difference matters |
| `portfolio_pnl` | Book of options on one underlying | quantity-weighted Greek aggregation; second-order PnL attribution (delta/gamma/vega/volga/vanna/theta/rho) vs full reprice; the unexplained residual growing with the move |
| `cliquet_option` | Cliquet / ratchet / reverse / Napoleon | closed form vs MC; local cap sweep; global floor/cap coupling; **the Heston forward-smile discount on capped strips**; the floored Napoleon's vol-of-vol convexity |
|  `stress_mtm` (needs `--features stress-config`) | Stress MtM from TOML scenarios | shock config (relative/absolute, per-underlying) -> bumped market -> full revaluation; trade-level table and portfolio aggregation per scenario |
| `american_baw` | American vanillas, analytic approximations | Barone-Adesi-Whaley and Bjerksund-Stensland 2002 vs binomial / FD / LSMC; early-exercise premium and critical boundary; the BS2002 lower-bound property; the exact Merton perpetual as the T -> infinity limit; true American Greeks; ~cents of error for a huge speed-up |
| `sample_paths` | Raw model paths (no pricer) | the public `sample_paths` API over the process traits; GBM Sobol paths vs the lognormal law; max-drawdown scenario statistics; Heston `(S, v)` paths under Andersen QE and the rho = -0.7 crash/vol signature |

## Reading the output

- Engines that refuse a combination by design (analytic + American, tree +
  barrier, FD + Heston) print `unsupported` with the reason instead of
  aborting — the tables double as a support matrix.
- `std err` is populated for Monte Carlo rows only.
- `[OK ]` / `[BAD]` lines are identity checks with an explicit tolerance.

## Greek surfaces (interactive 3D plots)

`vanilla_option` and `binary_option` also render **interactive 3D surfaces of
the Greeks over (moneyness, maturity)** and save them as self-contained Plotly
HTML files under `runs/` (git-ignored). Open one in a browser to rotate, zoom
and hover the surface — the ideal way to inspect the shape and smoothness of a
Greek:

```
runs/vanilla_option/delta_surface.html   runs/vanilla_option/gamma_surface.html
runs/vanilla_option/vega_surface.html    runs/vanilla_option/theta_surface.html
runs/binary_option/delta_surface.html    runs/binary_option/gamma_surface.html
```

The contrast is the point: the vanilla call delta is the smooth monotone
`0 -> 1` S-curve and vanilla gamma is a single clean ATM ridge, while the cash
**digital** delta spikes into a tall near-expiry bump at the strike and its
gamma flips sign right across it — the visual signature of a non-smooth payoff.

The plots are generated by [`common/plot3d.rs`](common/plot3d.rs), which builds
the Plotly figure spec directly with `serde_json` (a core dependency) and emits
a single HTML file with all data embedded inline and an interactive Plotly
`surface` trace. The Plotly JavaScript library is loaded from its CDN (the
standard for Plotly HTML exports); to view fully offline, replace the one
`<script src=...>` line with a local copy of `plotly.min.js`.

## Building your own

All ten use [`EquityOptionBuilder`](../src/equity/builder.rs):

```rust
let option = EquityOptionBuilder::new()
    .spot(100.0)
    .strike(100.0)
    .flat_vol(0.30)
    .flat_rate(0.05)
    .dividend_yield(0.02)
    .years_to_maturity(1.0)
    .vanilla(PutOrCall::Call)
    .engine(Engine::MonteCarlo)
    .paths(100_000)
    .build();

println!("{} +/- {}", option.npv(), montecarlo::npv_with_stats(&option).std_err);
```

Swap `.vanilla(...)` for `.binary(...)`, `.barrier(...)`, `.asian(...)`,
`.forward_start(...)` or `.autocallable(...)`; swap `.engine(...)` and
`.model(...)` to change pricer and dynamics. JSON contract equivalents for
the CLI live in [`../src/examples/`](../src/examples/).