Repository navigation
Conversation
detail::QdPutCallParityEngine::calculate() -- shared by both QdPlusAmericanEngine and QdFpAmericanEngine -- checked only that the exercise type is American, never inspecting AmericanExercise::payoffAtExpiry(). Every other closed-form American engine (Barone-Adesi-Whaley, Bjerksund-Stensland, Ju quadratic) explicitly rejects that flag, since their formulas assume the standard immediate-early-exercise convention, not the payoff-deferred-to-expiry one. Without the same guard, QD+/QD-FP silently priced such an option as a standard American option instead of raising an error. Added a regression test covering both engines: confirmed it fails (computes a result instead of throwing) without the fix and passes with it, while a plain American exercise is unaffected. Co-worked with Claude Code
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues remain for the shared QD American exercise-validation change.
No open issues 🎉
What changed in this PR
Adds validation to the shared QD American pricing engine so QD+ and QD-FP reject payoff-at-expiry exercises instead of pricing them under unsupported assumptions.
Changes:
- Checks the American exercise’s
payoffAtExpiryflag in the shared calculation path. - Adds regression coverage for both engines, checking that standard American exercises price without throwing and payoff-at-expiry exercises raise an error.
| File | Description |
|---|---|
test-suite/americanoption.cpp |
Adds exercise-validation regression coverage for both QD engines. |
ql/pricingengines/vanilla/qdplusamericanengine.cpp |
Rejects unsupported payoff-at-expiry exercises in the shared engine. |
Review effort: Balanced
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
detail::QdPutCallParityEngine::calculate()— shared by bothQdPlusAmericanEngineandQdFpAmericanEngine— checks only that the exercise type is American:It never inspects
AmericanExercise::payoffAtExpiry(). Every other closed-form American engine explicitly rejects that flag, since their analytic formulas assume the standard immediate-early-exercise convention, not the payoff-deferred-to-expiry one:BaroneAdesiWhaleyApproximationEngineBjerksundStenslandApproximationEngineJuQuadraticApproximationEngineMcAmericanEngine(viaEarlyExercise::payoffAtExpiry())Without the same guard, QD+/QD-FP silently price a
payoffAtExpiry-flagged American option as if it were a standard American option — a confidently wrong result with no indication anything is off, rather than the clean rejection every sibling closed-form engine gives.Fix
Added the same guard pattern used by the sibling engines (downcast to
AmericanExercise, reject ifpayoffAtExpiry()is set), in the single sharedcalculate()so bothQdPlusAmericanEngineandQdFpAmericanEngineare covered.Test
Added
testQdEnginesRejectPayoffAtExpirytotest-suite/americanoption.cpp, covering both engines: confirms a plain American exercise still prices normally, and apayoffAtExpiry-flagged one throws. Without the fix, both engines compute a result instead of throwing; with the fix, both throw as expected. FullAmericanOptionTestssuite (39 cases) passes with no regressions.🤖 Co-worked with Claude Code