Fix Merton kurtosis formula, GARCH standard errors, LSM order parameter, and SciPy compatibility; add regression tests#27
Open
SatishRockzz wants to merge 1 commit into
Conversation
Fixes from a systematic audit (all numerically verified): - Merton kurtosis: 3*sigJ**3 -> 3*sigJ**4 (correct 4th cumulant; was ~2x off) - GARCH fit: objective now true NLL (0.5 factor) so Hessian-based standard errors are no longer understated by sqrt(2); optimum unchanged - LSM: 'order' parameter now passed to polyfit (was hardcoded to 2); honest error message for unsupported call options - scipy compat: scp.mean -> np.mean in all five MC pricers; scipy.linalg.misc import -> scipy.linalg (runs on current SciPy) - mesh_plt in Merton/VG/NIG pricers: PDE_price -> PIDE_price (method exists) - VG fit_from_data: always-true `elif "MM":` -> proper comparison + else raise - probabilities: Q1/Q2 docstrings corrected to P(X>k); normalizer comment New tests/test_regressions.py locks in: kurtosis vs cumulant formula, put-call parity, MC-vs-closed-form agreement, LSM order sensitivity, Merton closed-vs-Fourier. 5/5 passing on NumPy 2.5 / SciPy 1.18. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR fixes several verified bugs found during a systematic audit of the package, and adds a small regression test suite that locks the fixes in. Each fix was confirmed numerically (hand-derivation + Monte Carlo cross-check) before being applied.
Math / inference fixes
Processes.py): the excess-kurtosis formula used3*sigJ**3where the 4th cumulant of compound-Poisson-normal jumps requires3*sigJ**4(λ·E[J⁴] = λ·(μJ⁴ + 6μJ²σJ² + 3σJ⁴)). With (λ=0.8, μJ=0.1, σJ=0.5, σ=0.2) the old code returned 5.074; the true value is 2.635 (MC-confirmed 2.639). The sibling VG/NIG formulas were verified correct — this was a lone typo.Processes.py): the objective minimized infit_from_datawas 2× the true Gaussian NLL (missing ½ factor), so the Hessian-based standard errors were understated by √2 (~29%), narrowing CIs and overstating significance. The optimum (MLE) is unchanged; only inference scales. This also makes the objective consistent with the class's ownlog_likelihoodmethod.BS_pricer.py): the Longstaff–Schwartzorderargument was silently ignored —np.polyfitwas hardcoded to degree 2, so basis-order sensitivity studies returned identical results for everyorder. Now passed through. The error message for call options was also corrected (calls are unsupported, not "invalid type").Compatibility / correctness fixes
scp.mean(...)→np.mean(...)in all five MC pricers (scipy.meanwas removed from SciPy years ago; the MC methods crash on any current SciPy).from scipy.linalg.misc import LinAlgError→from scipy.linalg import LinAlgError.mesh_pltin the Merton/VG/NIG pricers calledself.PDE_price(...), which doesn't exist on those classes →self.PIDE_price(...).elif "MM":in VGfit_from_datais an always-true string literal, silently routing unknown method names into method-of-moments → proper comparison plus an explicitValueErrorfor unknown methods.probabilities.py: Q1/Q2 docstrings said P(X<k) while the integral computes P(X>k); corrected. Added a comment explaining thecf(-1.0000000000001j)normalizer (numerics untouched).New tests (
tests/test_regressions.py)Codifies the cross-method checks the notebooks already perform interactively: kurtosis vs the cumulant formula, put–call parity to 1e-8, MC within 3 standard errors of the closed form (seeded), LSM order sensitivity (order=2 vs 4 now differ under identical seeds), Merton closed-form vs Fourier inversion. 5/5 passing on NumPy 2.5 / SciPy 1.18.
No behavior changes outside the fixes; all public APIs unchanged.
🤖 Generated with Claude Code