Repository navigation
2.13.0 — the Risk Solver surface, a scale defect in irr, and six oracles
Risk Solver: 29 of 36 rows
§3 priorities 1, 3 and 4 complete — 29 distributions from DistributionPoisson through DistributionLogarithmic.
Those with a SciPy analogue are checked against a committed fixture of 38 parameterisations and 874 values, because a cdf/quantile pair bound to the wrong arguments round-trips perfectly and satisfies every self-consistency test. It found three cancellations on its first run: tan evaluated beside π/2 in Cauchy's quantile, and pow(x, small) − 1 in Burr12's and Dagum's.
Several bindings needed conversions the names do not suggest — PsiFrechet is invweibull, PsiLogLogistic is fisk with the arguments reordered, PsiInvNormal's first SciPy argument is the ratio mu/lambda, PsiHypSecant's scale is the standard deviation rather than SciPy's scale. Two contradictions in Frontline's own documentation are resolved in the open rather than silently.
irr and xirr could not compute a large model
Not a precision problem — a failure. The stopping rule compared the NPV residual against a fixed 1e-4 in currency units. Scale ordinary cash flows by 1e9 and the sum's own rounding noise exceeds that, so Newton reached machine precision and then threw Failed to converge while sitting on the exact answer. The error's own advice, "relax the tolerance", was the only workaround and made the answer worse.
IRR is scale-invariant; an absolute bound on the NPV is not. Both functions now converge on the Newton correction to the rate, which is scale-invariant because the cash-flow units cancel between the NPV and its derivative. Across twelve orders of magnitude the answer moves by at most the last bit of a Double.
tolerance: keeps its name and position and changes meaning — it now bounds the correction relative to the rate. Its default is √(ulpOfOne), derived from the numeric type rather than chosen.
Six external oracles, five defects
| Target | Oracle | Result |
|---|---|---|
| Risk Solver distributions | SciPy | 3 cancellations |
fitGeneralLME, fitRandomSlope |
statsmodels | projection bug, components 12–24% low |
fitRandomIntercept |
statsmodels | ML while documented as REML |
Cholesky / DenseMatrix |
LAPACK | clean |
| Holt-Winters | exact recovery | 2 defects |
G-study, twoWayANOVA |
statsmodels | clean |
| Moving averages | pandas | clean |
| Bayesian ICC | ANOVA decomposition | clean |
The clean results matter as much as the finds: the Cholesky factorisation is what the mixed models, regression and optimisation all solve through.
poisson(_:µ:) also trapped the process for any count above 20 — an Int factorial overflow on an entirely ordinary arrival rate. It had no tests at all.
The finding behind all of it
116 of 153 numerical-estimator test files — 1,359 tests — checked nothing against anything outside the package. Every one asserted self-consistency: a matrix is symmetric, residuals sum to zero, an information criterion is finite. All true of a correct implementation, and all equally true of a systematically wrong one.
The most uncomfortable detail: a test comparing estimates against the parameters the data was simulated from passed throughout the REML defect. A 24% bias in a variance component sits inside the sampling noise of any one dataset. Simulation-recovery is not a substitute for a reference implementation.
Known issues
regularizedIncompleteBetahas not moved toSpecialFunctions/with its two siblings.- Standard errors from
fitGeneralLMEdiffer from statsmodels by 0.1–2%, more than the variance components they are built from. Most likely a convention difference in how the fixed-effect covariance is formed, but that is not established and the test says so rather than asserting agreement that is not there.
7,023 tests. Quality gate 45/45, 0 errors, 0 warnings. CI green on all four jobs; Release Tests green including Thread Sanitizer.