← Research index
INDEPENDENT NUMERICAL AUDIT13 September 2026

FinancePy BAW pricing divides by zero at a zero rate

The Barone–Adesi–Whaley coefficient has a finite limit as the risk-free rate tends to zero. FinancePy 1.0.1 forms its numerator and denominator separately, so exact zero becomes 0/0; a nearby put can also exceed the boundary solver's iteration limit.

Xamit Kadirbekov
Xamit KadirbekovIndependent verification · GERO Research
Quantitative financeFinancePy 1.0.1American options
STATUS · REPORTED UPSTREAM — CORRECTION SUBMITTEDReproduced from the published PyPI wheel. FinancePy PR #261 is open and mergeable; both official workflows pass. The correction has not been accepted or merged.

A one-minute explanation

Synthetic English narration using macOS Samantha. Original motion cards, no music or third-party imagery. Download the script, source ledger, renderer and QA record.

Released-wheel reproduction

The BAW path uses the coefficient

mm / kk = (2r / v²) / (1 - exp(-rt)).

For synthetic S=K=100, T=1 and v=20%, the official FinancePy 1.0.1 wheel produces:

American call, r=0, q=2%      ZeroDivisionError
American put,  r=0, q=0       ZeroDivisionError
American put,  r=1e-12, q=0   FinError: Failed to converge

The wheel SHA-256 is 110e784122f485ae207239f44af473334f418d81bcbb958f5eda4e76956feca5. The same direct quotient remains at upstream base commit 2b9227fea9d832c4033421d6cd53a54316414fca.

The limit is finite

Since 1-exp(-rt) ~ rt, the quotient has the ordinary limit

(2r/v²) / (1-exp(-rt))  →  2/(v²t).

Pull request #261 uses -expm1(-rt) away from zero and the analytic limit at zero. For a zero-rate put with a non-negative dividend yield, the European put already dominates immediate exercise, so that exact case returns the European value. The nearby put boundary receives 100 rather than 50 secant iterations; the tolerance and solver are otherwise unchanged.

Independent controls

A separate 2,000-step Cox–Ross–Rubinstein implementation imports no FinancePy code. For the zero-rate call with a 2% dividend yield it gives 7.110251189598. Corrected BAW gives 7.098257767528, a difference of about 0.012. BAW remains an approximation; the relevant result is that its value is finite and continuous at zero.

At r=q=0, the corrected BAW put equals FinancePy's European value 7.965579241666. A standard-erf Black–Scholes control gives 7.965567455406. That roughly 1.18e-5 normal-CDF approximation difference predates this change and is outside the finding.

Validation and falsification

  • The focused model file reports 4 passes.
  • The complete local unit suite reports 959 passes, with four pre-existing LSMC conditioning warnings.
  • The unmodified released wheel reproduces two division errors and the near-zero convergence failure.
  • After the correction, zero and near-zero call values agree within 1.1e-7; zero and near-zero put values agree within 5.4e-11.
  • Both official upstream workflows report success on commit 03b31c40976c907729b05a0e32ead0fe706ccd51.

At publication time the pull request remains open and unmerged. Passing checks establish the state of the submitted code, not maintainer acceptance.

Evidence and limits

Four bounded searches of FinancePy issue and pull-request history found no matching report. This is duplicate screening, not a worldwide priority guarantee.

All prices and market inputs are synthetic. The report establishes a library-level singularity and convergence boundary. It does not establish institutional use, a customer position, production deployment, financial loss, or the exactness of the BAW approximation.

The public reproducer and report are supplied under GPL-3.0-or-later.