Repository navigation
Measure geometric average-strike Asian times from the valuation date - #2983
Open
Jackmeson1 wants to merge 1 commit into
Open
Jackmeson1 wants to merge 1 commit into
Jackmeson1 wants to merge 1 commit into
Conversation
The analytic discrete geometric average-strike engine measured fixing and residual times from the first fixing, which omitted the dividend discount to a delayed first fixing for flat curves on a common clock. It also mixed day counters and could return NaN at zero effective variance. Take forwards from discount factors at the fixing and exercise dates and variances on the volatility clock from its reference date, accumulate the variance of log(S_T/G) from nonnegative time increments, and return the discounted intrinsic value when it is zero. Update the test reference that encoded the old value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JfvcPZyKcKQUG9fQGYfRMw
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.
AnalyticDiscreteGeometricAverageStrikeAsianEnginemeasures the fixing times and the residual time from the firstfixing date instead of the valuation date (
analytic_discr_geom_av_strike.cpp:57-76on70f240f29). With flat curvessharing the valuation date and day counter, a delayed first fixing causes the price to omit the dividend discount
factor D_q(0, t1). The engine also mixes clocks: fixing times use the volatility day counter, the residual time the
risk-free one, and the drift multiplies zero rates (each in its own day counter) by those times. Finally, the engine
divides by the effective standard deviation without handling zero variance; when all fixings are at maturity, this
produces NaN even though the payoff is identically zero.
This PR selects fixings on or after the risk-free curve's reference date, as
AnalyticDiscreteGeometricAveragePriceAsianEnginedoes. It measures fixing and exercise times using the volatilityday counter from the volatility reference date, and obtains forwards from discount factors at each fixing and
exercise date (ln(D_q/D_r)). The call price is the same two-lognormal formula, D_r(T)·(F_T·N(d1) - E[G]·N(d2)), now
evaluated with
BlackCalculator. The variance of ln(S_T/G) is accumulated from the nonnegative time incrementsbetween fixings (weight (i/N)^2 after the i-th fixing, 1 after the last), instead of as
Var[ln S_T] + Var[ln G] - 2 Cov[ln S_T, ln G], whose subtraction can leave a rounding residue; when it is exactly
zero the engine returns the discounted intrinsic value D_r(T)·max(±(F_T - E[G]), 0).
With flat curves sharing today as their reference date, a common day counter, the first fixing today, and positive
effective variance, the price is unchanged. On non-flat curves the forward to each fixing now comes from the curves at
that date instead of the zero rates to maturity. The volatility is still read once at the exercise date, and
pastFixingsmust still be 0.Flat curves, spot 100, r = 6%, q = 3%, 20% volatility, Actual/360, maturity in 360 days. References were calculated
independently in Python; the forward-start base values are reconstructed from those references and the MSVC
fail-before differences.
70f240f29For the ten-fixing case, t1 = 0.1 and the base/reference ratio is exp(0.03·0.1) = 1.0030045. For both forward-start
cases, t1 = 0.5 and the ratio is exp(0.03·0.5) = 1.0151131.
Tests (
test-suite/asianoptions.cpp):testAnalyticDiscreteGeometricAverageStrike: the reference changes from 4.97109, which encodes the defect, to4.95620, with the joint-lognormal moments in a comment (a Monte Carlo estimate agrees within its error; it is not
used as the reference).
...ForwardStart: one fixing halfway to maturity equals S·D_q(t1) times an at-the-money call/put on [t1, T],computed with
blackFormula, within 1e-12....AtMaturity: one, three or seven fixings at maturity, for maturities of 157 and 360 days, give a finite 0 within1e-12, call and put. An earlier, cancellation-based draft of this patch left about 1.5e-7 in price for each option
type in the 157-day, seven-fixing case.
...DayCounters: the risk-free, dividend and volatility curves switch independently between Actual/360 andActual/365 (Fixed) with rates scaled by 365/360 and volatility by sqrt(365/360), so every discount factor and
variance is unchanged; the price must agree within 1e-8 percent (1e-10 relative) in all eight combinations.
...FirstFixingToday: with the first fixing today, the price equals the previous formula's, computed independentlywith
blackFormula, within 1e-12. This one passes before and after the change....ZeroVolatility: with zero or 1e-14 volatility and positive, zero and negative carry, the price agrees with thediscounted deterministic payoff within 1e-12.
...SmallVolatility: one fixing today and 1e-9 volatility give an at-the-money option worth about 3.9e-8, whichmust match
blackFormulawithin 1e-2 percent (1e-4 relative) for both calls and puts and not be clamped to zero.This one passes before and after the change.
...NonFlatRates: a risk-free curve with the same 6% zero rate to maturity as a flat curve but 1% to the firstfixing; at zero volatility the price must equal the discounted payoff with G the geometric mean of the dated
forwards, within 1e-12.
With the engine from
70f240f29, the updated and added tests produce 46 failed assertions in my Windows MSVC run:one updated reference assertion, two forward-start comparisons, 24 maturity assertions (finiteness and zero for
each of 12 prices), 12 mixed day-counter comparisons, six zero/tiny-volatility comparisons, and the non-flat call.
With this patch, my runs of
QuantLibTests/AsianOptionTestspass all 35 test cases on Windows withMSVC 19.41.34123.0 (C++17) and on Linux with g++ 13.3.0 (Release,
QL_COMPILE_WARNING_AS_ERROR=ON).With a CMake build in
build/(Linux), run the suite with:AI disclosure: this was prepared with AI assistance (Claude Opus 5.5).
🤖 Generated with Claude Code