You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
v1.0.2: additive transparency + standard-grid benchmark coverage; no
algorithmic change to the IV kernel (implied_vol_fast and friends are
bit-identical to v1.0.1).
New:
- bench/cly_3d.rs + bench/python/cly_3d_compare.py: CLY-3D standard
grid (51,321 cases, Cui-Liu-Yao 2021; same grid the May 2026 FlashIV
and ThiopheneIV preprints benchmark on). voltic implied_vol_fast at
89 ns/option, max abs sigma error 1.539e-9 (LBR-parity at the f64
reverse-Black floor at deep-OTM near-expiry); 36.7x faster than LBR
scalar, 4.2x faster than py_vollib_vectorized. volfi 0.1.8 reproduces
its v1.0.1 SplitMix64 catastrophic-tail finding independently on
CLY-3D: 4,836 NaN + 5,488 catastrophic out of 51,321 (concentrated
in K/S > 2 band, 42,290 cases).
- README 'Verification methodology' section: the five independent
diligence checks behind the v1.0.1 volfi finding (hand-coded direct
repro outside the oracle adapter, put-call parity via two paths,
alternate volfi entry point iv_otm, volfi-self-priced volfi-self-
inverted, bench pattern equivalence to volfi's own bench_vollib.py).
- README 'Benchmarks: CLY-3D' subsection: the five-row results table
alongside the existing SplitMix64 and volfi vxD tables.
Refined:
- README 'Known gaps' rewritten as 'Accuracy: known gap and v1.1
roadmap'. New empirical disclosure: on 44.6% of deep_otm rows voltic
ties LBR within 1.5x of the f64 inversion floor; on 17.8% voltic
beats LBR by 2x or more; on 33.6% voltic loses by 2x or more. The
v1.0.1 headline 2.19e-11 vs 2.01e-11 lives in the |h|>=4 tail (n=230,
1.8% of deep_otm). Root cause: an erfcx cancellation at |h|~4.3 in
b_normalized. v1.1 roadmap cites FlashIV (arxiv 2605.29102, May 27
2026) log-price residual decomposition as the structural fix.
13 voltic NaN on CLY-3D implied_vol_fast: by-design rejection in the
f64-double-underflow regime where ln(c) < -708; the FlashIV Bachelier-
microscopic branch handles this regime, queued for v1.1.
Cargo.toml bumped to 1.0.2; new [[bin]] cly_3d entry.
Signed-off-by: Ryan Stewart <47729789+RyanJamesStewart@users.noreply.github.com>
Bands are oracle bucketing by N(-d2): the `deep_otm` and `deep_itm` labels reflect very-low / very-high OTM-call probability and both correspond to the **deep wings of the (moneyness, vega) plane**. voltic and LBR have zero rows above 1e-3 anywhere. volfi's 913 catastrophic rows concentrate in those two deep-wing bands at 3-4% rate each.
41
41
42
-
Voltic carries a mild 2-4× residual vs LBR in the deep_otm tail (sub-picovol absolute — max 9.9e-12) — see [Known gaps](#known-gaps).
42
+
Voltic carries a mild 2-4× residual vs LBR in the deep_otm tail (sub-picovol absolute — max 9.9e-12) — see [Accuracy: known gap and v1.1 roadmap](#accuracy-known-gap-and-v11-roadmap).
43
+
44
+
---
45
+
46
+
## Verification methodology
47
+
48
+
Claims of the form "library X has a numerical bug" are usually wrong: nine times out of ten the user fed X the wrong inputs through a misconfigured adapter. Before publishing the volfi finding we ran five independent checks designed to catch exactly that class of mistake. All five agreed.
49
+
50
+
### 1. Hand-coded direct repro outside the oracle adapter
51
+
52
+
We pulled the top 10 worst volfi rows from the oracle output and called `volfi.iv_call(F, K, disc, T, c)` directly in a standalone script, with no adapter layer of any kind. All 10 rows reproduced ULP-identical to the oracle run. Maximum disagreement across the 10 rows was 0.0 floats.
53
+
54
+
### 2. Put-call parity via two independent paths
55
+
56
+
For each put-side row we computed σ two ways. Path A: our oracle's parity transform `c = p + S - K*disc`, then `volfi.iv_call(c)`. Path B: volfi's own `bs_call` from their published `bench_vollib.py` evaluated at `sigma_true` to produce a call price, then `volfi.iv_call` on that price. Path A and Path B agreed to better than 1e-13 absolute σ on every row tested, and both produced the same catastrophic answer. The error does not depend on which side of parity the row originated on.
57
+
58
+
### 3. Alternate volfi entry point
59
+
60
+
We re-ran the worst rows through `volfi.iv_otm` instead of `volfi.iv_call`. The error reproduced on both paths. On Row 10 (true σ ≈ 0.786), `iv_otm` returned 0.4903 and `iv_call` returned 0.4961; both are off by roughly 0.29-0.30 absolute. The failure is not confined to a single volfi entry point.
61
+
62
+
### 4. volfi-self-priced, volfi-self-inverted
63
+
64
+
To remove our BS-pricer from the loop entirely, we used volfi's own `bs_call` formula to construct the call price `c` at `sigma_true`, then fed that price back into `volfi.iv_call`. The returned σ was the same wrong value. The failure mode is independent of which Black-Scholes formula produced the input price.
65
+
66
+
### 5. Bench pattern equivalence to volfi's own `bench_vollib.py`
67
+
68
+
The call shape used in our benchmark, `volfi.iv_call(F, K, disc, T, c)`, is the same pattern volfi's own published benchmark `bench_vollib.py` uses. The prices we feed volfi agree with what volfi's own `bs_call` produces to within 3.55e-15 absolute, which is the f64 ULP at the relevant magnitudes.
69
+
70
+
The failure mode is intrinsic to volfi at this regime; 913 of 99,996 rows show err > 1e-3, with floor-ratio (volfi_err / f64_BS_inversion_floor) median 1.34e+11, max 3.04e+15.
71
+
72
+
---
43
73
44
74
### Speed (single-threaded, znver5, taskset -c 0)
45
75
@@ -70,6 +100,26 @@ median ns/option (median of 7, 5000 reps each): 81.3
70
100
71
101
The 2 NaN are pre-existing f64 conditioning failures at **(v=0.01, Δ∈{0.30, 0.70})** — tiny-σ near-ATM puts where the BS price is below 1e-7 (no meaningful f64 inverse). Pinned by the `volfi_wing_grid_nan_set_bounded_to_two` regression test so a future inner-iteration edit can't silently expand the NaN set.
72
102
103
+
### Benchmarks: CLY-3D (Cui-Liu-Yao 2021 standard grid)
104
+
105
+
The CLY-3D grid (51,321 deep-OTM-weighted points; defined in Cui, Liu, Yao 2021 and used as the standard benchmark in the May 2026 FlashIV and ThiopheneIV preprints) provides a second independent dataset alongside SplitMix64. Grid: `S=100`, `r=0.03`, `K ∈ linspace(105, 800, 40)`, `T ∈ linspace(0.01, 2, 40)`, `σ ∈ linspace(0.01, 0.99, 40)`, filtered to call price > 1e-20 (matches FlashIV Table 3 and ThiopheneIV Table 3 cell count exactly).
106
+
107
+
| solver | impl | ns/option | wall (s) | max abs err | NaN | catastrophic (≥ 1e-3) |
voltic ≈ LBR ≈ py_vollib_vectorized at 1.539e-9 max abs σ error (all three sit at the f64 reverse-Black floor at the deep-OTM near-expiry corner) while voltic is **36.7× faster than LBR scalar** and **4.2× faster than py_vollib_vectorized**.
116
+
117
+
The volfi catastrophic-tail reproduces on CLY-3D: 4,836 NaN + 5,488 catastrophic out of 51,321 cases, concentrated in the K/S > 2 band (42,290 cases). This is the same defect class as the v1.0.1 SplitMix64 finding, observed independently on the CLY-3D grid.
118
+
119
+
Voltic's 13 NaN are by-design rejection in the f64-double-underflow regime where `ln(c) < -708`. The Bachelier-microscopic branch FlashIV §3 defines handles this regime; queued for v1.1. See [Accuracy: known gap and v1.1 roadmap](#accuracy-known-gap-and-v11-roadmap).
120
+
121
+
† `implied_vol_with_context_batch` trades accuracy for raw throughput by skipping the rational-fallback path; this is the documented split-context API contract. Use `implied_vol_fast` for accuracy-critical paths.
@@ -205,10 +259,38 @@ The wing seed replaces a v1.0.0 path that extrapolated the Chebyshev seed beyond
205
259
206
260
---
207
261
208
-
## Known gaps
262
+
## Accuracy: known gap and v1.1 roadmap
263
+
264
+
The v1.0.1 README described a "mild 2-4x gap to LBR in the deep_otm tail." That framing was too coarse. The actual picture is sharper and worth stating precisely: voltic is at LBR parity across most of deep_otm, and the headline gap lives in a thin n=230 tail.
On 44.6% of deep_otm rows, voltic and LBR tie within 1.5x of the f64 BS-inversion floor (i.e. neither solver has room to do better given input price round-off). On another 17.8% of rows voltic genuinely outperforms LBR by a factor of 2 or more. On the remaining 33.6% voltic genuinely underperforms LBR by 2x or more. Median (voltic_err - lbr_err) is +8.42e-15, mean is +9.66e-14, and the Pearson correlation between voltic_err and lbr_err across all 12,730 rows is 0.746.
269
+
270
+
**Stratification by |h| = |ln(F/K)| / σ_total**
271
+
272
+
|\|h\| band | n | voltic_max | LBR_max | f64_floor_max |
In the |h| ∈ [3, 4) middle of deep_otm, voltic's worst row beats LBR's worst row. The v1.0.1 headline 2.19e-11 vs 2.01e-11 lives entirely in the n=230 |h|≥4 tail, which is 1.8% of deep_otm rows.
279
+
280
+
**Root cause**
281
+
282
+
At |h| ≈ 4.3, the cancellation-free residual evaluator `b_normalized` in `src/black.rs` computes a difference of two `erfcx` values that agree to roughly 1.5 significant digits, then multiplies the difference by ½·exp(-9). The f64 rounding of that inner subtraction is the catastrophic step: the surviving bits of the residual are dominated by round-off rather than by the analytic signal. LBR sidesteps this by switching to an explicit 17-term asymptotic series once |h| crosses its threshold, so its high-|h| path never executes the cancellation.
283
+
284
+
**v1.1 roadmap**
285
+
286
+
Le Floc'h and Healy's "FlashIV" preprint (arxiv 2605.29102, May 27 2026) publishes a log-price residual decomposition `c = ½ [erfcx((-h - t)/√2) − e^(−x) · erfcx((-h + t)/√2)]` that structurally avoids the cancellation: the two `erfcx` terms enter as a scaled combination rather than as a raw subtraction at near-equal magnitudes. Voltic v1.1 will implement this evaluator in SIMD f64x8 alongside the existing path, gated on |h|. Expected outcome: voltic matches or beats LBR on the |h|≥4 tail at unchanged throughput. The residual rewrite costs under 1 ns per option amortized across the lane, well below the householder iteration cost that dominates the inner loop.
287
+
288
+
Both voltic and LBR are within roughly 2x of the physical f64 BS-inversion floor in this regime. The engineering target is at-LBR-parity, not the floor itself; the floor is a property of input price round-off, not of the solver.
289
+
290
+
Other known gaps:
209
291
210
-
-**Mild voltic–LBR residual in deep_otm.** Voltic carries a 2-4× median ratio vs py_lets_be_rational in the deep_otm tail (max absolute 9.9e-12, sub-picovol). Jäckel's rational guess wins by design in that corner; tightening voltic's deep_otm seed is v1.1 work. The ratio is well below the band's f64 conditioning floor for all but the outermost rows — see the per-band table above.
211
292
-**Two NaN at (v=0.01, Δ∈{0.30, 0.70}) on the wing v×Δ stress grid.** Tiny-σ near-ATM puts at the f64 BS price floor (< 1e-7). No meaningful f64 inverse exists for these inputs; they're pinned by the `volfi_wing_grid_nan_set_bounded_to_two` regression test.
293
+
-**13 NaN on CLY-3D `implied_vol_fast`.** Deep-OTM near-expiry double-underflow regime where `ln(c) < -708`. By-design rejection; the Bachelier-microscopic branch FlashIV §3 defines handles this regime, queued for v1.1.
0 commit comments