Skip to content

Use the value-maximising flat trigger in Bjerksund-Stensland - #2963

Merged
lballabio merged 3 commits into
lballabio:masterfrom
himanshug9119:fix/bjs-maximise-trigger
Nov 2, 2026
Merged

lballabio merged 3 commits into
lballabio:masterfrom
himanshug9119:fix/bjs-maximise-trigger

Conversation

@himanshug9119

Copy link
Copy Markdown
Contributor

Fixes #2903, implementing option (a1) as discussed there.

Every flat trigger gives a lower bound for the American price; the published trigger is only a heuristic for the best one, and for negative carry it drops below the strike as T approaches T* = (2σ/|b|)², so the price collapses to the European value. The engine now checks whether the value still increases just above max(I, S); if so, it finds the best trigger by golden-section search on log(I) up to B∞ (about 88% of options stop at the check and keep today's price).

Greeks: at the optimum the value is stationary in I, so the trigger-derivative terms in rho, dividend rho and vega drop out. The optimal trigger moves with the spot, so gamma gets a −V_SI²/V_II term (finite differences in I). The existing finite-difference greek test covers 406 options that go through the search; without the gamma term, 90 of its gamma checks fail.

Tests:

On 10k random options (S/K 0.8–1.2, r, q 0–10%, vol 10–50%, T 30d–3y), 9.9% change (at most 0.68%); every changed price moves towards QdFp, and none goes above it. The full test suite passes.

AI assistance was used for the implementation and analysis; I reviewed every line.

The published trigger is a heuristic that falls below the strike as T
approaches T* = (2 sigma/|b|)^2 for negative carry, and the price then
collapses to the European one. Every flat trigger gives a lower bound
for the American price, so when the value still increases above the
published trigger, search for the best one. The trigger drops out of
the first-order greeks at the optimum; gamma gets a -V_SI^2/V_II term.
The very-high-volatility put in testBjerksundStenslandValues was
priced at its European value; QdFp and CRR give 99.2035. Two Margrabe
values from Haug move towards the QdFp values of the equivalent call.
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 79.468% (+0.01%) from 79.456% — himanshug9119:fix/bjs-maximise-trigger into lballabio:master

@lballabio
lballabio merged commit 899946d into lballabio:master Nov 2, 2026
45 checks passed
@boring-cyborg

boring-cyborg Bot commented Nov 2, 2026

Copy link
Copy Markdown

Congratulations on your first merged pull request!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BjerksundStensland returns the European value (~97% too low) when the trigger falls below the strike (negative carry, long maturity)

3 participants