Skip to content

Price continuous lookbacks when the carry is zero - #2856

Open
mkzung wants to merge 1 commit into
lballabio:masterfrom
mkzung:fix/lookback-zero-carry
Open

mkzung wants to merge 1 commit into
lballabio:masterfrom
mkzung:fix/lookback-zero-carry

Conversation

@mkzung

@mkzung mkzung commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

AnalyticContinuousFloatingLookbackEngine and AnalyticContinuousFixedLookbackEngine return NaN whenever the risk-free rate equals the dividend yield, at any volatility. Both formulas divide by lambda = 2(r - q)/sigma^2, and the ratio being divided is zero there too.

The limit of that ratio is simple: stdDev * (eta n(d1) - d1 N(-eta d1)) in the floating case and -stdDev * (d1 N(eta d1) + eta n(d1)) in the fixed one, which gives the usual zero-carry lookback formulas. The engines use it for |lambda| < 1e-7. The threshold is where the error of the limit and the cancellation in the division cross: near zero the division alone was 2e-5 off at a carry of 1e-12.

Over 792 options, with carries between -3% and 3% including 0 and values down to 1e-12, master gives 72 NaN, all at zero carry. With this change there are none, and every price is within 4e-9 of the same formulas evaluated in 50-digit arithmetic.

testAnalyticContinuousLookbackZeroCarry checks two floating and four fixed lookbacks at r = q = 5%, and all six are NaN on master. LookbackOptionTests and the full suite pass.

The partial-time lookback engines divide by the carry as well and are left as they are.

The fixed- and floating-strike lookback formulas divide by lambda =
2(r - q)/sigma^2, and with r equal to q both engines returned NaN. The
ratio they divide is itself zero there, and its limit is stdDev times a
combination of N(d1) and n(d1), which the engines now use for
|lambda| < 1e-7. Near zero the old division also lost digits: at a carry
of 1e-12 it was 2e-5 off.

Over 792 options with carries between -3% and 3%, including 0 and values
down to 1e-12, the prices are within 4e-9 of the same formulas evaluated
in 50-digit arithmetic.
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 78.252% (+0.001%) from 78.251% — mkzung:fix/lookback-zero-carry into lballabio:master

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.

2 participants