Skip to content

Changelog

All notable changes to this project will be documented here.

The format follows Keep a Changelog, and this project adheres to Semantic Versioning.

Only tagged public releases are recorded here. Development snapshots published from main to TestPyPI use VCS-derived .devN versions and are not tracked as separate changelog entries.


[Unreleased]


[0.1.7] — 2026-07-03

Added

  • Surface arbitrage-evaluation harness (fast_vollib.surface) — a generator-agnostic, backend-pluggable, differentiable evaluator for implied -volatility surfaces. Takes an arbitrary surface on an arbitrary (log-moneyness × maturity) mesh and returns calibrated, dimensionless arbitrage diagnostics.
    • IVSurface / SurfaceSequence containers with from_logmoneyness, from_strikes, from_total_variance, and from_call_prices constructors; numpy / torch / jax arrays preserved with dtype and device.
    • validate_surface()ArbitrageReport: price-space discrete checks (convexity / slope / box / calendar; Davis–Hobson 2007) and total-variance checks (∂_T w ≥ 0, Durrleman g ≥ 0; Gatheral–Jacquier 2014), with normalized metrics (ndm, bfly_frac, cal_depth_max, cal_frac, vert_frac, bound_frac) and the SAS composite (reported only alongside its components).
    • Artifact-vs-arbitrage separation: violations whose stencil touches an interpolated node are bucketed as interpolation_induced rather than counted as model arbitrage.
    • Round-trip trust mask: per-node σ→C→σ' Jäckel LBR fixed-point residual, machine-tight where the quote is well-posed.
    • Butterfly violations gate on the per-slice-normalized density magnitude vs the dimensionless tolerance (never raw density < 0), so O(h²) truncation noise at near-degenerate wings cannot manufacture spurious violations on an arbitrage-free surface. Severity bands key off the normalized magnitude; an empty / all-NaN surface reports passed=False (context["coverage"]).
    • arbitrage_penalty() — a differentiable soft form of the same checks that stays in the input tensor's namespace (no host round-trip), so it is autograd-traceable on torch/jax and matches the numpy report to machine precision. A reusable replacement for the inline VolGAN / deep-smoothing penalty functions.
    • Backend parity verified numpy == torch == jax to fp tolerance; SVI closed-form oracles validate the non-uniform divided-difference stencils (second-order convergence) and Durrleman g; models.fast_black validates the surface's own normalized-Black pricing to machine epsilon.
  • fast_vollib.diagnostics — six publication-quality figures (total-variance slices, Durrleman g, risk-neutral density, violation heatmap, calendar map, round-trip trust map), gated behind a new [viz] extra (pip install "fast-vollib[viz]"). Matplotlib stays out of the numerics core dependencies.

[0.1.6] — 2026-06-27

Fixed

  • CUDA tensor inputs to fast_implied_volatility — passing a CUDA-resident torch.Tensor (or any CPU tensor with requires_grad=True) raised TypeError: can't convert cuda:0 device type tensor to numpy because to_numpy() fell through to np.asarray(value), which invoked Tensor.__array__().numpy() — illegal for both cases. to_numpy() now detects torch tensors via type(value).__module__ and calls .detach().cpu().numpy() before the conversion. All other input types (numpy arrays, pandas, scalars, lists, JAX arrays) are unaffected. Note: .detach() means gradients do not flow through IV inversion; the compute still round-trips through host numpy. A fully differentiable GPU- resident IV path remains a separate feature request.

[0.1.5] — 2026-05-29

Added

  • Python 3.10 support — lowered requires-python from >=3.11 to >=3.10, added the Programming Language :: Python :: 3.10 classifier, and extended the CI test matrix to cover 3.10 alongside 3.11–3.13.
  • Opt-in shape-aware runtime type checking — pure-annotation layer (jaxtyping + beartype) applied to the public API (fast_black, fast_black_scholes, fast_black_scholes_merton, fast_implied_volatility, fast_implied_volatility_black, get_all_greeks, price_dataframe, the vectorized_* Greeks) and to the four backend dispatch entry points (price_*, greeks, implied_volatility).
    • Annotations are stored as PEP 563 strings (every annotated module uses from __future__ import annotations) — zero runtime cost when not enabled.
    • Runtime checking is scoped to the public dispatch layer only via fast_vollib._typing.enable_runtime_checks(). Inner torch.compile closures, Triton kernels, Numba @njit factories, and JAX @jax.jit-traced functions are never decorated or rewritten, so the hot paths are bit-identical to the un-annotated build (verified with sha256 fingerprints of the jackel_iv numpy / torch / triton outputs before and after).
    • Install via the new [typecheck] extra: pip install "fast-vollib[typecheck]" (adds jaxtyping>=0.2 and beartype>=0.18). Default installs do not pull either package into sys.modules.

[0.1.4] — 2026-04-10

Added

  • fast_vollib.jackel module — full implementation of Peter Jäckel's "Let's Be Rational" (2016) algorithm with four backends:
    • jackel_iv_black — NumPy + Numba (six parallel kernels; ~8.5 ms / 100k)
    • jackel_iv_black_torch — PyTorch with torch.compile(dynamic=True) (~2.7 ms GPU compute)
    • jackel_iv_black_jax — JAX lax.fori_loop + @jax.jit (~2.4 ms GPU compute)
    • jackel_iv_triton — single-pass Triton kernel; entire pipeline in registers (0.056 ms GPU compute / 100k)
  • Dedicated test package tests/test_jackel/ with parity tests against py_lets_be_rational (oracle); max relative error < 10⁻⁸.
  • py-lets-be-rational added to the dev dependency group so CI installs the oracle automatically.
  • scripts/jackel_triton_bench.py — correctness + CUDA-event timing script for the Triton kernel.

  • Numba backend (backend="numba"): JIT-compiled CPU kernels via @numba.njit(parallel=True). Pricing, Greeks, and the full Halley+bisection IV solver run as a single native-code dispatch per batch. Enabled by pip install "fast-vollib[numba]" (requires numba>=0.60.0). Kernels are compiled on first call and cached to __pycache__ for subsequent runs.

  • Isolated numba test suite under tests/numba/ (skipped automatically when numba is not installed).

Fixed

  • get_all_greeks(..., return_native=True) now returns native torch/JAX arrays instead of formatting the result back into pandas containers.
  • Below-intrinsic IV handling now honors on_error= consistently across the NumPy, PyTorch, and JAX backends.
  • The compare_against_py_vollib_vectorized.py helper now imports the current upstream vectorized_* entry points correctly.

[0.1.3] — 2026-04-04

  • Added backend_parity tests for torch
  • Updated tutorial notebook with Mac MPS backend (for Apple silicon chips).

0.1.2 — 2026-03-26

Release focused on packaging automation, public release channels, and broader compatibility coverage.

Added

  • Development and nightly-style build publishing to TestPyPI from main using trusted publishing via GitHub Actions OIDC.
  • Additional test coverage for backend parity, packaging consistency, and release workflow support.
  • Monkey-patching support for baseline replacement workflows, including py_vollib_vectorized compatibility-oriented patch helpers.

Changed

  • Versioning is now derived from Git tags via VCS-based build metadata, so stable PyPI releases are tag-driven and development snapshots use .devN versions automatically.

0.1.1 — 2026-03-26

First public release after the initial beta version. This release improves runtime correctness, tightens packaging and typing metadata, and aligns backend behaviour across NumPy, PyTorch, and JAX.

Fixed

  • price_dataframe now raises explicit ValueError exceptions instead of relying on bare assert guards.
  • The JAX implied-volatility backend now returns NaN for below-intrinsic and zero-price inputs, matching NumPy and PyTorch behaviour.
  • Backend configuration is now standardized on FAST_VOLLIB_BACKEND;

Added

  • py.typed marker for PEP 561-compatible downstream type-checking.
  • Packaging metadata improvements, including explicit mypy configuration and updated Python version support metadata.

0.1.0 — 2026-03-22

Features

  • Pricingfast_black, fast_black_scholes, fast_black_scholes_merton with full NumPy vectorization and broadcasting.
  • Implied Volatilityfast_implied_volatility and fast_implied_volatility_black using Halley's method with a compiled bisection fallback (~10 M solves / s on CPU).
  • Greeksvectorized_delta, vectorized_gamma, vectorized_theta, vectorized_rho, vectorized_vega, and get_all_greeks.
  • Backend routing — pluggable NumPy, PyTorch, and JAX backends with automatic resolution (FAST_VOLLIB_BACKEND env var, set_backend(), per-call backend= kwarg).
  • DataFrame helperprice_dataframe for end-to-end pricing, IV solving, and Greek computation on a pandas.DataFrame.
  • Compatibility — patch helpers for py_vollib and py_vollib_vectorized namespaces at runtime.

Fixed

  • Corrected Black-76 forward pricing formula (q = r, not q = 0).
  • Added below-intrinsic NaN guard in the PyTorch IV solver.

Performance

  • Pre-computed CDF symmetry (N(-x) = 1 - N(x)) eliminating 5 redundant CDF evaluations per option in the Greeks hot path.
  • Reduced CDF calls in pricing hot path using the same symmetry identity.
  • Compiled bisection fallback yields a 16× throughput improvement on large WRDS-scale datasets compared to the pure Python fallback.