# Validation protocol — FinancePy cash-settled annuity

Recorded 2026-09-14, before candidate correction.

Pinned upstream master: `2b9227fea9d832c4033421d6cd53a54316414fca`.
Hypothesis: `IborSwap.cash_settled_pv01` omits a payment for valuation on or before the effective date, even though `fixed_leg.payment_dts` already excludes that effective date.

Contract: for N remaining regular payments at frequency m and flat rate s, the forward annuity is the explicit cash-flow sum A = sum((1/m)/(1+s/m)**j, j=1..N). At zero rate A=N/m. A one-payment annuity must be positive for s > -m. The function returns an annuity factor; it does not itself scale by notional or 0.0001. This meaning is also documented by the maintainer in issue 227.

Primary grid: frequencies 1,2,4,12; payment counts 1,2,3,10,60; flat rates -0.02,0,1e-12,0.01,0.04,0.15; valuation one year before start, at start, and one day after start (before first payment). All dates are regular fifteenth-of-month dates with business-day adjustment NONE. Independent reference: 80-digit Decimal cash-flow sum. Tolerance: max(2e-12 absolute, 2e-12 relative).

Downstream: real IborSwaption.cash_settled_value with Black model, regular schedules, positive forwards/strikes/volatilities, valuation equal to constructor settlement so expiry-time conventions agree. Independent Black formula using standard-library erf, independent explicit annuity sum and flat exponential discounting. Test payer and receiver options, one and multiple payments, multiple frequencies. No market-calibrated data or production claims.

Verify identical inputs and source path in a released package and fresh source checkout; execute baseline, candidate and restored-original mutation in separate Python processes. Run relevant upstream unit tests and added regressions. Preserve any unrelated failures rather than modifying expectations to force a pass. Full source suite may be run if practical. Candidate should remove only the incorrect payment skip, leaving other settlement conventions alone.

Duplicate review: all publicly returned issue/PR title/body records, focused GitHub issue searches including comments, relevant source history and previous local registry. Report bounded search only, never absolute novelty. No public posting or upstream submission in this research task.

## Diagnostic amendment after the initial corrected run

The candidate passed all 360 independent Decimal annuity cases. Seven of 162 downstream cases exceeded the original independent Black comparison tolerance; max residual 0.04389522615 per 1,000,000 synthetic notional. The original failing run and original harness remain in corrected-initial.json and reproduce-v1.py. **The tolerance and original pass/fail flags are unchanged.**

An additional composition check holds the library Black kernel fixed and combines it with the independent full-payment annuity and independent exponential discount factor. This identifies the annuity contribution without asserting that the library kernel equals erf-based Black. The diagnostic maximum composition difference was 2.241e-9 across 162 cases. The remaining differences are explained by the existing normal-CDF approximation in Black. This is not presented as a newly discovered CDF defect.

The corrected-mode exit gate now requires all independent annuity checks and all composition checks; it explicitly permits and reports residual failures against the stricter independent Black oracle. No claim of 522/522 strict independent-oracle passes is allowed.
