feat(american-option): log-spot Dynamic Chebyshev variant (Stage F1 front-fixing)#228
Merged
Merged
Conversation
…ront-fixing) Add a default-off LogSpot build option that interpolates the continuation in x = log(S) instead of linear S. The GBM transition is additive in x, so the Gauss-Hermite images stay bounded, and the narrow uniform-in-x grid is far better conditioned than the wide linear [5,250] grid at high node counts. Two measured wins vs the linear grid (StandardPut, oracle Gamma(82)=0.033689): (1) Robustness - log-spot stays finite at n=321 where the linear build throws 'function returned non-finite values', and at n=161 the linear spot-82 row wrongly collapses into the exercise region (Gamma 0) while log-spot gives 0.027767. (2) Accuracy - the spot-82 Gamma error converges monotonically with n (0.009807 -> 0.005922 -> 0.002755), more than halving it, so the boundary Gamma error was resolution-limited, not intrinsic. At low n=81 log-spot is marginally behind linear near the boundary, where its nodes cluster at the domain ends. Greeks use the chain rule from u(x)=V(e^x): Delta = u'(x)/S, Gamma = (u''-u')/S^2 (the -u' term is required). The OFF path is bit-identical (additive branch; existing linear code verbatim in the else arm). This recovers most of the boundary Gamma without the heavyweight boundary-tracking (Landau) re-architecture, now optional. Docs: case-study subsection 'A log-spot variant recovers the boundary Gamma'. Tests: OFF bit-identical lock; log-spot ATM price vs oracle; chain-rule Greeks vs linear baseline; finite-at-high-n where linear throws; spot-82 Gamma convergence measurement. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…the boundary finder Now that the log-spot variant is the real boundary-aware path, retire the naive BoundarySplit flag. It splits a smooth continuation at a non-singularity and only relocates the Gamma query onto the ill-conditioned Chebyshev piece edge (non-physical negative Gamma). The documented finding stays in the case study; the reusable FindExerciseBoundary (Math.NET Brent) is kept. Removed: the BoundarySplit settings flag, the split branch in Build, BuildContinuationSpline, EvaluateSpline, the now-unused firstContinuationFunction/firstFunc plumbing, and the two split-specific tests. Kept: FindExerciseBoundary + its test (renamed AmericanOptionBoundaryFinderTests). Docs: added the concrete global-vs-split Gamma-ringing table to the negative-result note (preserving the evidence now that the runnable flag is gone), and fixed the high-n failure description (ill-conditioning of the wide grid, not quadrature overflow). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
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
Stacked on #227 (base =
feature/american-boundary-split). Stage F1 of the front-fixing track: a default-offLogSpotbuild option that interpolates the continuation inx = log(S)instead of linearS— and it retires the naiveBoundarySplitexperiment from #227 now that log-spot supersedes it.This answers the open question from #227's negative result: the boundary Gamma error was resolution-limited, not intrinsic.
Why log-spot
The GBM transition
S' = S·exp(drift + √2·σ√dt·z)becomes additive inx = log(S):x' = x + drift + √2·σ√dt·z. So the Gauss–Hermite images stay bounded, and the grid is narrow ([log5, log250], ~24× tighter span) and uniform-in-x, hence far better conditioned than the wide linear[5,250]grid.Measured (StandardPut, oracle Γ(82) = 0.033689)
nn=321where the linear build throws "function returned non-finite values".n=81log-spot trails linear near the boundary, where its Type-I nodes cluster at the domain ends.This makes the heavyweight F2 (boundary-tracked Landau transform) optional.
Also retires the
BoundarySplitexperiment (from #227)Now that log-spot is the real boundary-aware path, this PR retires the naive
BoundarySplitflag — it split a smooth continuation at a non-singularity and only relocated the Gamma query onto the ill-conditioned piece edge (non-physical negative Gamma).BuildContinuationSpline/EvaluateSpline, dead plumbing, and the two split tests.FindExerciseBoundary(Brent, reusable) + its test (renamedAmericanOptionBoundaryFinderTests).Net: published
main(after the stack merges) gets the log-spot fix and the documented lesson, not the broken flag.Implementation
LogSpotflag (default off); the OFF path is bit-identical (additive branch — regression-locked).u(x) = V(e^x):Δ = u'(x)/S,Γ = (u''(x) − u'(x))/S²(the−u'term is required).Tests / gates
OFF bit-identical lock; log-spot ATM price vs oracle; chain-rule Greeks vs linear baseline; finite-at-high-
nwhere linear throws; spot-82 Gamma convergence measurement; boundary-finder test. Full suite 1804 passed,dotnet formatclean,docfx0/0.Sequencing
Stacked on #227. Merge order: #226 → #227 → this. GitHub retargets this to
mainonce #227 merges.🤖 Generated with Claude Code