# Exponential NIG option pricing
The `nig` feature provides a fully on-chain European call/put engine for the
exponential Normal Inverse Gaussian model. It accepts spot, strike, rates,
time, and NIG parameters; constructs the martingale correction and density;
evaluates the option integral; and returns both sides of put-call parity with a
quote-local numerical allowance.
There is no live QuantLib call, uploaded matrix, sampled price surface,
operator account, or trusted off-chain builder. The embedded data consists of
parameter-independent quadrature geometry and scaled-Bessel approximation
coefficients.
## Model
For elapsed NIG scale `d = delta_per_year * T`, define
```text
gamma = sqrt(alpha^2 - beta^2)
gamma1 = sqrt(alpha^2 - (beta + 1)^2)
k = ln(S/K) + (r-q)T + d(gamma1-gamma)
h = -k
```
The `gamma1-gamma` term is the exponential-moment correction that makes the
discounted asset a martingale. Moving to the stock numeraire shifts `beta` to
`beta + 1`.
The engine integrates only the smaller out-of-the-money leg:
```text
C_otm = K exp(-rT) integral_0^inf (exp(y)-1) f_beta(h+y) dy
P_otm = K exp(-rT) integral_0^inf (1-exp(-y)) f_beta(h-y) dy
```
The other leg follows from fixed-point put-call parity. This avoids subtracting
two large, nearly equal CDF terms. The density is evaluated as
```text
f_beta(x) = alpha*d/(pi*omega)
* [exp(alpha*omega) K1(alpha*omega)]
* exp(d*gamma + beta*x - alpha*omega)
omega = hypot(d, x)
```
The scaled `exp(x) K1(x)` form prevents a large intermediate Bessel value.
Piecewise Chebyshev/asymptotic kernels are generated by
`scripts/generate_nig_k1_coeffs.py`; the canonical coefficient payload SHA-256
is `77e439688b161d544e786a78cbd7256b1364e133abba217bc08b83e0145b60dc`.
The half-line map `y = L*t/(1-t)` feeds an embedded Gauss–Kronrod 15 / Gauss 7
pair. Deep out-of-the-money cases can use a parameter-derived Chernoff bound
and return through the cheaper tail tier. The tail tier is capped at `$0.005`
per `$100` of discounted notional regardless of a looser caller request.
## API
```rust
use solmath::{nig_price_certified, NigParams, SCALE};
let quote = nig_price_certified(
100 * SCALE, // spot
100 * SCALE, // strike
50_000_000_000, // continuously compounded rate = 5%
20_000_000_000, // continuous dividend yield = 2%
SCALE, // one year
NigParams {
alpha: 15 * SCALE,
beta: -2 * SCALE as i128,
delta_per_year: SCALE,
},
5_000_000_000, // requested absolute error = 0.005
)?;
let _ = (quote.call, quote.put, quote.max_abs_error, quote.tier);
# Ok::<(), solmath::SolMathError>(())
```
```rust,ignore
pub struct CertifiedNigPrice {
pub call: u128,
pub put: u128,
pub max_abs_error: u128,
pub tier: u8, // 0 expiry, 1 Chernoff tail, 15 full quadrature
}
```
All fields use `SCALE = 1e12`. `alpha` and `beta` are inverse log-return units;
`delta_per_year` scales linearly with time. Compatibility functions
`nig_call_price`, `nig_call_64`, and `nig_put_64` use `q = 0` and the standard
`$0.005 / $100` request.
Enable the engine independently:
```toml
solmath = { version = "0.2", default-features = false, features = ["nig"] }
```
## Runtime domain
| `spot`, `strike` | `(0, 100,000]` |
| `time` | `(0, 5]` years |
| `rate`, `dividend_yield` | `[-0.25, 0.25]` |
| `alpha` | `[2, 100]` |
| `abs(beta) / alpha` | `<= 0.65` |
| `abs(beta + 1) / alpha` | `<= 0.65` |
| `delta_per_year` | `(0, 15]` |
| `delta_per_year * time` | `[0.001, 15]` |
| absolute log-forward moneyness | `<= 2` |
At expiry the result is exact intrinsic value with tier `0`. Inputs outside the
runtime domain return `DomainError`; a computed allowance above the caller's
request returns `NoConvergence`.
## Accuracy
The release corpus compares the compiled Rust path with a high-precision
two-measure NIG CDF identity. The reference reflects upper tails to avoid
`1-CDF` cancellation and cross-checks difficult points with adaptive direct
density integration.
| Production | 100,000 | 87,715 | 12,285 | `$4.02e-9` | `$1.73e-5` | `$0.000565278` | 0 |
| Adversarial | 10,000 | 6,898 | 3,102 | `$5.31e-9` | `$0.000170265` | `$0.001396550` | 0 |
There were also zero violations of the caller's requested maximum error. The
production/adversarial input SHA-256 values are
`61cb4bd21a99928fde3fd0355d33ef48678bb45e4de342b7e1b534c70fdb097c`
and `8853de248219801b23eca772f3613caf011d1f8b0408ddd877645bb0c35e9340`.
An independent 50-digit check uses direct Bessel-density integration and Lewis
characteristic-function inversion. Those two reference methods differed by at
most `1.775e-16` dollars; the fixed-point engine differed by at most
`$0.000103316` on the six independent-oracle regimes.
`max_abs_error` combines the embedded-rule estimate with a fixed-point floor.
The release corpora and independent oracle support that allowance throughout
the measured domain; it is an empirical numerical contract rather than a
symbolic all-domain Gauss–Kronrod remainder theorem.
## Compute and footprint
The Agave 2.3.0 campaign executed 2,000 generated quotes against the current
composite SBF artifact:
| Median | 28,261 | — |
| P99 | 367,321 | 368,377 |
| Maximum | 381,385 | 382,441 |
The inexpensive median is the Chernoff tail tier; full quadrature determines
the upper end. The measured composite artifact is `1,083,408` bytes with
SHA-256 `685d49886179ca0bec80e31d9e9b878f3d044a47869cfd2f70cc2cf194c05161`.
In the isolated footprint harness, the Anchor baseline is `184,848` bytes and
the NIG variant is `311,464` bytes, a `126,616`-byte linked delta.
## Reproduction
```bash
python3 scripts/generate_nig_k1_coeffs.py
python3 scripts/nig_reference.py
python3 scripts/validate_nig_runtime.py --production 100000 --adversarial 10000
NO_DNA=1 cargo build-sbf --manifest-path benchmark/sbf-composite/Cargo.toml
```
The machine-readable evidence lives in:
- `benchmark/nig_release_report.json`
- `benchmark/nig_independent_oracle_report.json`
- `benchmark/nig_cu_report.json`
- `benchmark/nig_footprint_report.json`
## Model scope
- The engine prices European options under an exponential NIG Lévy process.
- Rates, yields, and NIG parameters are constant over the contract horizon.
- Quotes outside the published runtime domain are represented as errors rather
than extrapolated values.
- American exercise is handled separately by `american-kbi`.
The model convention follows Barndorff-Nielsen's exponential NIG process. The
Esscher/CDF identity and independent inversion are consistent with the modern
NIG CDF and option-pricing literature:
- <https://pure.au.dk/portal/en/publications/processes-of-normal-inverse-gaussian-type/>
- <https://arxiv.org/abs/2502.16015>
- <https://arxiv.org/abs/2006.04659>