Skip to content

jlmoya/jquantlib

Repository files navigation

JQuantLib

A pure-Java port of QuantLib — the de-facto open-source library for quantitative finance — being systematically rebuilt from C++ v1.42.1 with tier-stratified, cross-validated precision (EXACT / TIGHT / LOOSE) against the pinned C++ source.

Tag Tests C%2B%2B%20surface Warnings JDK Scanner C%2B%2B%20pin License


What is JQuantLib?

JQuantLib provides Java developers and quants with the mathematical, statistical, and modelling toolset needed to value equities, options, futures, swaps, fixed-income instruments, and a wide range of derivatives. It mirrors QuantLib's C++ API as closely as Java idioms allow, offering a smooth bridge for organizations running JVM-based pricing infrastructure.

The original Java port began ~2007, stalled in 2021, and is now being revived as a multi-phase, precision-first migration from C++ QuantLib v1.42.1.

Project posture (2026-04 → present)

This is not a maintenance branch. It is a systematic, full-fidelity port with five operating principles:

Principle What it means in practice
C++ is source of truth Where Java diverges from QuantLib v1.42.1 — signatures, implementations, constants, behavior — the Java code is updated to match C++. The pre-existing Java API is starting material, not a design to preserve.
Cross-validation before commit Every functional change is backed by a C++ "probe" (a small program linked against the pinned QuantLib submodule) that emits reference values to JSON. Java tests load those JSONs and assert against them. No expected value is invented inline.
Tier-stratified tolerances Comparisons land in one of three tiers — EXACT (bit-identical via Double.doubleToRawLongBits), TIGHT (abs 1e-14 + rel 1e-12), LOOSE (abs 1e-8 + rel 1e-8). Per-test exceptions require an inline written justification.
Bulletproof, not fast Every commit compiles and passes the full suite. One stub fix = one commit. No --no-verify, no skipped hooks. Mid-port architectural divergence becomes a separate align(...) commit, never bundled.
Direct-to-main Solo single-owner repo; no PR overhead. Each phase ends with a signed git tag (jquantlib-phase<N>-complete) and a completion document under docs/migration/.

Migration status

2026-05-29 — Full C++ v1.42.1 ql/ surface functional coverage. All 2024 C++ classes are accounted for via the reproducible audit migration-harness/check_coverage.py: 1933 ported & C++-cross-validated, 91 allowlisted with a written rationale (case-rename / inner-class / C++-template-idiom / traits-folded / commented-out-upstream), 0 unflagged. Full suite green (676 test classes / 3678 tests). Generic numerics are kept native by evidence — the C++ cross-validation pins internal algorithmic state (MINPACK fjac/fvec, exact Sobol, bit-exact transcendentals), so a different-algorithm library fails our existing tests; even the Levenberg–Marquardt lineage-match (Hipparchus) fails substitution. Nothing was re-baselined away from C++. This is functional coverage, not a 1:1-class claim. Detail: docs/migration/full-cpp-surface-completion.md.

2026-05-31 — Parity-safe performance optimization (observer registry). Profiling pinned the dominant cost in the slowest test (LiborMarketModelTest, ~537 s) not to the LMM math but to the Observable base class: DefaultObservable held observers in a CopyOnWriteArrayList, which copies its whole backing array on every register/unregister — O(n²) as observer lists grow during calibration. Replacing it with a plain ArrayList guarded by the instance monitor + snapshot-on-notify — preserving the exact iteration-during-mutation and multi-thread semantics CoW gave (ObservableTest.testMultiThreadingGlobalSettings), and touching zero floating-point — cut that test 537 s → 5.94 s (~90×) and the full suite from ~21 min to ~12 min, with all 3678 tests bit-identical. Commit 5baabea2; detail: docs/migration/perf-observer-optimization.md.

Phase Tag What landed Tests Date
1 jquantlib-phase1-complete Finished 80 started stubs across 61 existing packages 2026-04-24
2a jquantlib-phase2a-complete MINPACK + LM, Heston QuadraticExponential, 56 numerical-suspect markers swept 626/0/0/25 2026-04-24
2b jquantlib-phase2b-complete One-factor model Parameter-ref refactor (Vasicek, HullWhite, BK, CIR), Simplex 1D, SABR sentinel fix 632/0/0/22 2026-04-25
2c jquantlib-phase2c-complete Chi-squared CDF + CIR.discountBondOption, SABR α-default, HullWhite latent items, BK tree-pricing 649/0/0/22 2026-04-25
2d jquantlib-phase2d-complete CapHelper via BlackCalibrationHelper, Heston NCCS scheme, SABR Halton via XABR 649/0/0/22 2026-04-26
2e jquantlib-phase2e-complete G2 model body (scanner WIP: 1 → 0), BlackCapFloorEngine, full Swaption infra (Black/Tree/Discretized), SwaptionHelper 656/0/0/22 2026-04-26
2f jquantlib-phase2f-complete Cap engines (Bachelier branch), G2.swaption integral, Heston BroadieKaya + NCCS tightening 675/0/0/22 2026-04-26
2g jquantlib-phase2g-complete Brent.solveImpl pre-loop alignment → +19 LOOSE→TIGHT promotions; FdHullWhite/FdG2 deferred to 2h on framework gap 675/0/0/22 2026-04-26
2h jquantlib-phase2h-complete Full Fdm* finite-difference framework (~3826 LOC, 30 classes); FdHullWhiteSwaptionEngine + FdG2 TIGHT 8.4e-15 (bit-exact) + bonus BicubicSpline Address-mapping fix 677/0/0/22 2026-04-27
2i jquantlib-phase2i-complete CORE-MATH correctly-rounded JQuantMath.exp; FdHullWhite tier LOOSE → within(3e-12); A3 finding (Apple libm not always correctly-rounded) 684/0/0/22 2026-04-28
2i.5 jquantlib-phase2i.5-complete JQuantMath.cos + .sin via Dint64 (u128 emulation); NCCS A19 partial — Math.log floor identified 687/0/0/22 2026-04-28
2i.6 jquantlib-phase2i.6-complete JQuantMath.log (CORE-MATH, 1203-case bit-exact first-shot); NCCS A19 re-fire pinned gammaFunction_.logValue Lanczos as actual residual 688/0/0/22 2026-04-30
2j jquantlib-phase2j-complete Gaussian1D family partial (P2J-10 trim): full model layer + 3 of 5 engines (Standard SwaptionEngine LOOSE, CapFloorEngine LOOSE, Jamshidian TIGHT) + 3 MF prereqs; Nonstandard + FloatFloat + MarkovFunctional deferred (4× A16 fires) 792/0/0/22 2026-05-02
2j.5 jquantlib-phase2j.5-complete Full Gaussian1D family completion: 5/5 engines + MarkovFunctional (split tier) + 4 niche-engine instruments + GaussHermiteIntegration family + AtmSmileSection + 11 align-fix commits 801/0/0/22 2026-05-02
2k jquantlib-phase2k-complete Gaussian1D feature completion: SabrInterpolatedSmileSection + BasketGeneratingEngine + TqrEigenDecomposition lifted + MF.CustomSmileFactory; all 4 MarkovFunctional smile branches operational 809/0/0/22 2026-05-02
2l jquantlib-phase2l-complete Fdm framework completeness: BiCGStab + GMRES + 6 new schemes (9 total) + Bermudan/American/dividend step conditions + vanillaComposite wiring + new math.ode package 812/0/0/22 2026-05-02
2m jquantlib-phase2m-complete 3 Fdm-dependent vanilla engines (FdBlackScholesVanilla + FdHestonHullWhiteVanilla + FdSabrVanilla) + AndreasenHuge LocalVol family (3 classes). 8 commits across 4 parallel worktrees including 2 align prereqs. 816/0/0/22 2026-05-08
2n jquantlib-phase2n-complete JQuantMath.pow correctly-rounded via CORE-MATH cr_pow — 100% bit-exact (2,763/2,763 oracle cases). Qint64 (256-bit u128-pair) infra. 8 commits including 29-file/57-site Math.pow → JQuantMath.pow swap. JQuantMath now covers all 5 transcendentals: exp/log/sin/cos/pow. 818/0/0/22 2026-05-08
2o jquantlib-phase2o-complete HestonModel rho constraint aligned to C++ v1.42.1 (BoundaryConstraint(-1,1)); BlackFormula stdDevDerivative shifted-strike guards relaxed; SABRInterpolation.op + XABRInterpolationImpl pre-apply shift; SabrInterpolatedSmileSection Scenario C activated (21 cases LOOSE). 818/0/0/22 2026-05-08
2p jquantlib-phase2p-complete First subsystem-port phase — Inflation zero family. New package org.jquantlib.termstructures.inflation (InflationTraits + Interpolated/PiecewiseZeroInflationCurve + ZeroCouponInflationSwapHelper). New cashflow classes + ZeroCouponInflationSwap. Plus 2 align prereqs. Java inflation coverage 30% → 60%. 822/0/0/22 2026-05-08
2q jquantlib-phase2q-complete Inflation YoY + CPI + Seasonality + CapFlooredYoY closeout. 10 commits across 3 worktrees. Java inflation surface coverage 60% → 85%. 832/0/0/22 2026-05-08
2r jquantlib-phase2r-complete Inflation 100% core surface coverage. YoYOptionletVolatilitySurface family + 4 inflation cap/floor instruments + InflationCapFloorEngines (Black/UnitDisplaced/Bachelier) + 3 YoY optionlet pricers + FDNewtonSafe solver + YoYInflationIndex.fixing past-path align. 8 commits across 3 worktrees. Java inflation core surface 85% → 100%. 853/0/0/22 2026-05-08
2s jquantlib-phase2s-complete Experimental inflation closeout — Polynomial2DSpline + GenericIndexes + KInterpolated/Piecewise YoYOptionletVol + YoY Optionlet Stripper family + CPI/YoY CapFloorTermPriceSurface + InterpolatingCPICapFloorEngine. Inflation subsystem fully complete. 888/0/0/22 2026-05-08
2t jquantlib-phase2t-complete First test-suite phase under rigor directive — inflation.cpp ported (2,323 LOC → 31 @Test methods). InflationCommonVars test fixture + inflationPeriod sub-annual bug fix. 919/0/0/40 2026-05-08
2u jquantlib-phase2u-complete Inflation test-suite expansion (44%→86%): 4 cpp files ported + 5 L0 Phase 2x aligns + Track F body fills with 4 infrastructure aligns. 11 commits across 6 worktrees. 933/0/0/37 2026-05-08
2v jquantlib-phase2v-complete Inflation 100% (production + test-suite). CPIBond + 12 missing CPI index classes + GlobalBootstrap + lazy-baseDate ctor + YYIIS discount-curve overload + 2 remaining test-suite ports. 7 commits + 1 manual recovery. 950/0/0/39 2026-05-08
2x jquantlib-phase2x-complete Small infrastructure aligns + WeakReferenceObservable batched notification. mvn test wall-clock 30+ min → 59.5s (32x speedup). 951/0/0/38 2026-05-08
3a jquantlib-phase3a-complete First Phase-3 subsystem (greenfield credit termstructures): 3 abstract bases + FlatHazardRate + 3 interpolated curves + PiecewiseDefaultCurve + ProbabilityTraits + DefaultProbabilityHelper non-CDS + defaultprobabilitycurves.cpp test port. New package org.jquantlib.termstructures.credit. 973/0/0/45 2026-05-08
3b jquantlib-phase3b-complete CreditDefaultSwap instrument + Protection/Claim/FaceValueClaim + MidPointCdsEngine + 3 CDS helpers + creditdefaultswap.cpp test skeleton + 4 of 7 Phase 3a CDS-deferred tests un-ignored. 1004/0/0/51 2026-05-08
3c jquantlib-phase3c-complete IntegralCdsEngine + MakeCreditDefaultSwap + DateGeneration.CDS + Schedule rule + WeekendsOnly + IterativeBootstrap refinement. 7 of 8 deferred tests un-ignored. Drive-by fixes: Settings.TODAYS_PAYMENTS, InterpolatedDiscountCurve 2 bugs. 1018/0/0/44 2026-05-09
3d jquantlib-phase3d-complete IsdaCdsEngine (480 LOC sophisticated) + IterativeBootstrap config + Actual360(true) + 3 of 6 deferred un-ignores. Credit production 100% v1.42.1. 1024/0/0/41 2026-05-09
3e jquantlib-phase3e-complete DONE_WITH_CONCERNS — 4 pre-existing PiecewiseYieldCurve bugs fixed + 3 Markit test bodies fully ported (461 LOC). Tests stay @Ignore'd pending Phase 3f. 1024/0/0/41 2026-05-09
3f jquantlib-phase3f-complete Array(double[]) copy-vs-reference fix (Path A, 73 LOC). testIsdaEngine bootstrap drift improved 100× (~1% → 1.4e-4). 1024/0/0/41 2026-05-09
3g jquantlib-phase3g-complete Discount.maxValueAfter ungated negative-rates fix (key finding: bug was Discount traits, NOT IsdaCdsEngine). 2 EUR Markit tests un-ignored + passing. 1062/0/0/38 2026-05-09
3h jquantlib-phase3h-complete First marketmodels (LMM) slice — Track A (Utilities + EvolutionDescription + CurveState + 3 curvestates + 4 drift calculators) + Track B (3 correlations + MTBrownianGenerator + AccountingEngine + MarketModelDiscounter + MultiProduct + Evolver align). MersenneTwisterUniformRng latent unsigned-long bug fixed. New packages: org.jquantlib.model.marketmodels.*. ~3,600 LOC C++ ported. 7 commits across 2 parallel worktrees. 1087/0/0/38 2026-05-09
3i–5e.5b jquantlib-phase5e5b-CFC-c-checkpoint Rolled-up retro for the 545-commit gap — see docs/migration/phase3i-through-5e5b-rolledup-completion.md. Covers Phase 3i+ marketmodels evolvers/products/callability, Phase 4a-4o.5 ql/experimental/ ports (~63K LOC C++), Phase 5a-5e.5b test-suite/ ports (~79K LOC C++ scope). Per-sub-phase completion docs slipped Phase 3i+; resumes from 5e.5b-CFC-c onward. 2959/0/0/598 2026-05-14
5e.5b-CFC-c jquantlib-phase5e5b-CFC-c-checkpoint align(time.Schedule) post-BDC dedup fix in Backward/Forward loops (mirrors C++ schedule.cpp:229-233 / :326-330). Root-caused via probe-instrumentation diff after BlackON cap/floor body-fills surfaced 6.7e-7 drift. 20-LOC fix unblocked 2 tests; no regression across 2957 other tests. New BlackON diagnostic probe added. 2959/0/0/598 2026-05-14
5e.5b-CFC-d jquantlib-phase5e5b-CFC-d-checkpoint OvernightLeg structural body-fills + Schedule characterization tests + align(time.calendars) Juneteenth port to GovernmentBondImpl + new Market.SOFR + SofrImpl. Surfaced latent Juneteenth bug — helper existed but never wired into GovernmentBond. Plus overnight_leg_caps_floors probe with cross-validated NPV. testOvernightLegWithCapsAndFloors @Ignore'd pending Cubic-extrapolation root cause. 2961/0/0/594 2026-05-14
5e.5b-CFC-d-final jquantlib-phase5e5b-CFC-d-final Continuation of CFC-d: Juneteenth wired into all 3 main US calendars (Settlement/NYSE/GovernmentBond). BlackFormula forward-derivative + RS/Chambers ports (5 new tests). AmortizingFixedRateBond body-fill (1). FixedRateBond/FixedRateLeg arbitrary-schedule support (1). InterpolatedZeroCurve flat-forward extrapolation fix closed the residual 2.7e-7 drift; testOvernightLegWithCapsAndFloors now PASSES (1). Surefire JVM heap 2g eliminated NoClassDefFoundError flakiness. Plus body-fills: MultipleResetsCouponsTest (2), MultipleResetsSwapTest (3), ZeroCouponSwapTest (6). 2961/0/0/575 2026-05-14
CFC-d-181 → 321 sweep (untagged — on main) **Massive @Ignore-clearing sweep across ~180 commits via ~50 parallel background agents. Foundational align fixes: Period.eq/le/ge/neq strict-unit comparison (CFC-d-318); Distribution constant-dx invariant (CFC-d-319); SinCosKernel sin(±Inf) → NaN parity (CFC-d-295); InflationCapFloor cached values refreshed under A3 carve-out (CFC-d-321). Production landings: MCLookback, MCEuropeanGjrGarch, GjrGarchModel/Process/AnalyticEngine, VarianceSwap/MC/Replicating, DiscountingPerpetualFutures, FlatHazardRate, Brlcdi/Business252, StochasticCollocationInvCDF, AdaptiveRungeKutta 1D/Complex, Concentrating1dMesher, TridiagonalOperator SOR, SVD wide-matrix, IncrementalStatistics Welford, FdBlackScholesVanillaEngine localVol, LocalVolSurface Dupire, ProjectedConstraint, HullWhite.FixedReversion, NoArbSabrModel + D0Interpolator + absorption tables, VannaVolgaBarrier + DoubleBarrier engines, FdExtOUJumpVanilla + FdSimpleExtOUStorage, VanillaStorageOption, LFM Sobol LDS, FFTVarianceGamma, TreeVanillaSwap, Swaption(OIS), BlackSwaptionEngine OIS, CappedFlooredCmsCoupon, CEVRNDCalculator delta>=2, MCEuropeanHeston SLV, SabrSwaptionVolatilityCube (919 LOC), HestonStochasticLocalVolProcess.evolve, FdmHestonExpressCondition, DigitalOption Greeks bumping, CatBondAdditional, Asian Average-Strike engines, Heston calibration, SABR FlochKennedy, XABR ParameterTransformation, GemanRoncoroniProcess MC, HHHW testCallableEquityPricing, HHW testHestonHullWhiteCalibration, CmsNormal.testFairRate, AssetSwap.specializedBond, CallableFixedRateBond ex-coupon ctor, FdHestonVanilla leverageFct, HestonSLV LocalVol. End state: all 138 initial @Ignore annotations cleared. 3010/0/0/1 2026-05-20
Path A — Phase 1 closure (D5) (untagged — on d5-D-marketmodel worktree) **Post-certification-audit D5-RED → essentially GREEN remediation. 16 of 17 prereq TODOs closed across rounds A1–A6 (~135 commits, ~15,000 LOC of production code, ~200 net @Test methods added). Production-port landings: QdPlus + QdFp American engines (12 schemes), AbcdCalibration + MarketModelTestSetup, CotSwapFromFwdCorrelation, MultiCompositeQuote + CompositeInstrument, calendar greenfield (Russia/Israel/Mexico/NZ/SouthKorea/Denmark/China.SSE+IB), daycounter ports (Thirty365/Actual366/Actual36525/Actual364, ECB+ASX helpers, ActualActual ISMA_Impl, DateParser strftime), Array(size,start,step)+resize, FFTVanillaEngine, FdBlackScholesShoutEngine, FdBlackScholesBarrierEngine + escrowed dividend model, NelsonSiegel (weights,opt,l2) ctor, InterpolatedPiecewiseForwardSpreadedTermStructure, BondHelper bond-helper fitting, ExpSinhIntegral + FilonIntegral + TwoDimensionalIntegral + TanhSinhIntegral, GenericLongstaffSchwartzRegression + ProxyGreekEngine, ConstantLossModel, GlobalBootstrap, BjerksundStenslandApproximationEngine v1.42.1 rewrite, AnalyticEuropeanEngine (process,discountCurve) ctor + dispatch. 6 latent production bugs found & fixed via faithful porting: (a) AndreasenHugeVolatilityInterpl put/call payoff swap — latent since 2007 port (commit 958afc29); (b) TanhSinhIntegral missing level-0 integer-multiple nodes (commit 844d75ed); (c) MethodOfLinesScheme missing bcSet.setTime() call (commit 214f7b8a); (d) PathwiseVegasOuterAccountingEngine Jacobian transpose (commit 462b8456); (e) QdPlusAmericanEngine xMax NaN-at-spot-0 (commit b8f4d88a); (f) Money.greater/greaterEqual infinite-recursion (commit 35510f03). Residual ~75–80 still-genuinely-missing-by-name tests catalogued in phase1-closure-remaining.md. 3213 methods / 0 fail (in-progress) 2026-05-20
Phase 1 genuine closure (JDK 25) jquantlib-phase1-complete-jdk25 (0e72b77a) Closed P1.1/P1.2/P1.3/P1.4 carve-outs on JDK 25 LTS base. MultiCurve + LocalBootstrap + GlobalBootstrap + SpreadBootstrapTraits + InterpolatedSpreadDiscountCurve + PiecewiseSpreadYieldCurve + ConvexMonotone helper hierarchy + AverageBMALeg + multiple marketmodel test ports. Missing-by-name vs C++ v1.42.1 test-suite: 0. 20+ latent production bugs surfaced and fixed. Memory leak hypothesis (#565) resolved as external corrupted node_modules. 3270/0/0/24 2026-05-22
JDK 25 modernization W1-W4 jquantlib-jdk25-modernized-w1-w4 (683bf14e) JDK 25 LTS upgrade (source/target/release 25, surefire 3.5.2, junit 4.13.2, slf4j 2.0.16) + 4-wave syntax modernization. W1 cosmetic (312 var + 1327 diamond / 367 files); W2 pattern matching + switch expressions (74 instanceof + 52 switch + 5 switch-with-patterns / 105 files, -361 LOC); W3 records for DTOs (15 records, -385 LOC); W4 sealed type hierarchies (Exercise/Payoff/Dividend + nits). Each wave: implementer → spec-compliance reviewer → code-quality reviewer → fix-up → FF. W5 virtual threads + W6 Vector API deferred (no existing Executor / Vector API still incubator on JDK 25). 3270/0/0/24 2026-05-22
Phase 2 forward closure — L1 jquantlib-phase2-l1-complete (899f60e7) math/utilities/time/patterns layer. 5 clusters L1-A..E: time + simple math pilot (6 calendars + OneDayCounter + BernsteinPolynomial + PascalTriangle), 13 copulas + Copula SAM (probe-validated), 12 optimization + RNGs (bit-exact MT(42) probes), 25 distributions/integrals/stats/matrixutils/ode, math root + interpolation factories. Bonus production fix: CubicInterpolation Akima derivative (was throwing "not implemented yet"). ~3370+/0/0 2026-05-22
Phase 2 forward closure — L2 jquantlib-phase2-l2-complete (6f6ecf22) termstructures + indexes layer. 4 clusters L2-A..D: 11 indexes (BBSW + Aonia + root), 7 termstructures/yield (CPIBondHelper, FxSwapRateHelper, 4 fitting methods), 6 ZABR family via sealed interface + AtmAdjustedSmileSection, 26 indexes/ibor remainder (multi-currency). RUBCurrency added. ~3420+/0/0 2026-05-22
Phase 2 forward closure — L3 jquantlib-phase2-l3-complete (3c5c3862) instruments + pricingengines layer. 4 clusters L3-A..D: 14 instruments + 9 SKIP (StickyRatchet/YoY/FixedVsFloatingSwap), 7 Italian bonds (BTP/CCTEU/Rendistato), 5 swaption family (G2SwaptionEngine, BlackStyleSwaptionSpec sealed), 34 + 1 SKELETON pricingengines Make-factories + MC engines. Bonus fixes: FellerConstraint replaces broken VolatilityConstraint stub (L4-A); Vasicek.r0() public accessor. ~3500+/0/0 2026-05-22
JQuantLib migration complete jquantlib-migration-complete (4549eb7f) Phase 2 L4 + L5 closure. L4 11 classes (FellerConstraint + Brownian generators + Gaussian1d CachedSwapKey record + historical analysis). L5 mostly triage with aggressive SKIP-with-rationale: RecursiveLossModel + FdOrnsteinUhlenbeckVanillaEngine ported, all others either already-present, v1.42.1-deprecated, or no-Java/no-C++-caller (see phase2-skips-audit.md). 5 latent production bugs surfaced and fixed during Phase 2. C++ v1.42.1 → Java JDK 25 LTS migration certified. 3531/0/0/24 2026-05-22
Phase 2 SKIPs resolved jquantlib-phase2-skips-resolved (205f8b4b) Per user decision, ported all 13 Category D + E items from the SKIPs audit. D1: CubicInterpolation Harmonic/SplineOM1/SplineOM2 + 4 factories. D2: AbcdInterpolation wrapper. D3: 5 vol-cube classes + SabrSwaptionVolatilityCube hook refactor. D4: HybridSimulatedAnnealing + 16 functors. E1: FdBlackScholesAsianEngine SKELETON → functional. 5 sub-clusters across 5 worktrees. Known deferred SKIP-E1-FOLLOWUP: FdBlackScholesAsianEngine multi-fixing accuracy (~50% drift vs Levy 1997, single-fixing-vs-vanilla agreement proves rollback+mesher correct). 3569/0/0/24 2026-05-23
Phase 2 L6 (test-suite parity) jquantlib-phase2-l6-test-suite-parity-complete (1ffd209f) Test-suite parity round. L6-A: stats + riskstats ports (5 @Test). L6-B: InflationCapFlooredCouponTest (2 tests, 840 sub-cases). L6-C: 4 marketmodel SMM tests confirmed already-ported. L6-D: commodityunitofmeasure + cdsoption (2 tests). align(math.statistics) bonus: 3 production-side bugs in GenericRiskStatistics killed (regret Expression→ComposedFunction, averageShortfall predicate Bind1st→Bind2nd, shortfall Clipped→lambda) + GaussianStatsHolder for GenericGaussianStatistics typedef parity. 3 latent production-bug fixes from L6 alone, 8 in total this Phase 2 session. Plus aggregator distributionManagement fix (mirrors jquantlib-parent for mvn deploy from repo root). 3574/0/0/24 2026-05-23
Phase 2 complete jquantlib-phase2-complete (3d005e9c) SKIP-E1-FOLLOWUP closed. Root cause was a test-fixture transcription error (q↔r swap) in the original SKIP-E1 smoke test — engine was correct all along, proven by standalone C++ probe at same swapped setup yielding bit-identical NPVs to Java. All 5 Levy 1997 reference cases pass at 3-4e-3 (well inside 2.0e-2 ceiling). Test-only fix; no production code touched. Phase 2 forward closure declared genuinely complete with zero deferred items. 3574/0/0/24 2026-05-23
JQuantLib truly complete jquantlib-truly-complete (54ca6d72) Phase 3 closure addressing ~115 pre-existing pending items from the 545-commit Phase 3i-5e.5b rolled-up period. 5 sub-clusters: P3-A Fdm toMatrix() (5 PORT sum-of-decomp + 1 DESIGN-INTENT FdmBatesOp QL_FAIL parity); P3-B mcbasket MultiPath Phase 4i.5 closure (all 5 UOE throws closed + 2 cross-val tests); P3-C 19 Coupon cap/floor stubs DESIGN-INTENT per C++ aggregate-rate base + relocated base→subclass + 25 tests; P3-D 47 PORT + 13 DESIGN-INTENT + 1 BLOCKED (PseudoSqrt Hypersphere ConjugateGradient hang — routes to Higham/Principal) + 4 latent bug fixes (TimeGrid(Array) 3 + 21-LIBOR/DiscountingBondEngine dummy-handle pattern); P3-E true @Ignore count = 2 (not 42; 40 were JavaDoc/import noise), 3 stale-calendar tests deleted (-1075 LOC), 29 import cleanups, 2 KEPT-with-rationale (AndreasenHuge A3 precision + BermudanTreeDiagJavaProbe diagnostic). 4 more latent production-bug fixes (12 total this whole session). 3613/0/0/24 2026-05-23
Phase 3-F TODO/FIXME triage (4 commits, last bf80e089 and the inline 2f58a064) Audit + aggressive cleanup of the 835 TODO/FIXME/XXX marker occurrences across production code. P3F-A: 378 stale '// TODO: message' tags after QL.require msgs (mechanical sweep, 131 files). P3F-B: 73+ XXX::OBS / XXX:registerWith observer-cleanup leftovers (-304 LOC, 43 files). P3F-C: ~91 vague FIXME author opinions + concrete fixes (DynamicProxyInvocationHandler reflection-chain deletion fulfilling 18-year @Richard-Gomes FIXME; SobolRsg 1L = 1L; <<= shift collapsed to single C++-idiom expression). P3F-D: 217+ TODO Auto-generated method stub + 'Check with Richard' (Richard left ~2021) + dead bug-tracker URLs. P3F-final: 13 trailing markers inline. Final state: 835 → 13 (98.4% cleanup); the 13 KEPT are legitimate Phase-deferral references (Phase 4o.5 EnergySwap, Phase 4i.5 IrregularSwaption, Phase 5d.5 IborLeg JavaDoc), CORE-MATH provenance notes (LogKernel + PowKernel UB documentation), explicit upstream-C++ FIXME documentation (OneFactorStudentCopula + ExponentialForwardCorrelation), JavaDoc placeholder patterns, and journal page-range citations. 3613/0/0/24 2026-05-23
Console-noise cleanup (5 commits: de95bb17, 3282157f, 1a97b04f, 642fdeca, 14086930) Eliminated all stderr-flood + compile-warning noise during test runs. LibraryException constructors no longer call QL.error(this) (was unconditionally dumping ERROR + stack trace for every constructed instance — including ones caught for fast-path/slow-path control flow like LfmCovarianceProxy.integratedCovariance → numerical fallback, IterativeBootstrap retries, observer-failure chains). DefaultObservable.notifyObservers observer-failure log now routes via SLF4J WARN (configurable) instead of QL.error → stderr. 78 @SuppressWarnings({"deprecation","unchecked"}) annotations on legitimate-internal-use sites (Array/Matrix subclasses accessing Cells.$ raw backing, generic-erasure casts after Class.newInstance(), raw-type bridge code). 3610/0/0/21 2026-05-23
JQuantLib FINAL jquantlib-final (4c93962a) Final state pointer — re-pointed 2026-06-03 to the current tip. Now subsumes the full C++ v1.42.1 ql/ surface functional-coverage milestone (0646ee75), the parity-safe observer-registry perf optimization (5baabea2, suite wall 21→12 min), and the BlackScholesDividendLattice escrowed-spot fix (f4bad451/4c93962a, converges to QuantLib AnalyticDividendEuropeanEngine). Re-verified green: mvn -pl jquantlib test = Tests run 3719, Failures 0, Errors 0, Skipped 21, BUILD SUCCESS on JDK 25 LTS. Only main remains (all worktrees + transient branches removed local+remote). 3719/0/0/21 2026-06-03

Current state. Anchored on the full-surface functional-coverage milestone 0646ee75 (tag jquantlib-cpp-surface-functional-coverage; tag jquantlib-final @ 4c93962a). Since then:

  • Parity-safe perf — observer-registry optimization 5baabea2 (Date.clone candidate profiled and declined; see docs/migration/perf-observer-optimization.md).
  • BlackScholesDividendLattice escrowed-spot fix (f4bad451/4c93962a).
  • FD American discrete-dividend engine fixFDDividendAmericanEngine had silently ignored discrete dividends (a phantom-generic porting bug); now correct and cross-validated. See docs/migration/fd-dividend-american-fix.md.
  • jquantlib-showcase — a new interactive Spring Boot demo app (see Showcase).

Suite: mvn -pl jquantlib test = 3721 tests / 0 failures / 0 errors / 21 skipped, BUILD SUCCESS on JDK 25 LTS. Scanner WIP-stub count: 0 genuinely-pending. JDK: 25 LTS. Repo hygiene: only main remains (no worktrees or transient branches).

3 documented carve-outs (explicit; NOT silent deferrals):

  1. PseudoSqrt Hypersphere/LowerDiagonalhypersphereOptimize is ported (from C++ pseudosqrt.cpp:141-263); Java ConjugateGradient doesn't converge on the ill-conditioned target. UOE replaced with descriptive deferred-port message routing users to Higham / Principal alternatives. Closure requires Java optimizer hardening pass.
  2. AndreasenHugeVolatilityInterplTest#testFlatVolCalibration — A3 precision finding: observed residual range 2e-9..3e-8 vs spec 1e-10. Per CLAUDE.md, not loosening tolerance. Closure requires production-side LM/TridiagonalOperator precision work.
  3. BermudanTreeDiagJavaProbe — class-level @Ignore as legitimate diagnostic probe (not a regression test).

13 latent production-bug fixes surfaced and fixed this session: see docs/migration/phase2-skips-audit.md and docs/migration/phase2-L6-completion.md for full details.

Phase 1 certification audit — 2026-05-20: D1 YELLOW (suite green 3010/0/0/1 in 17m23s; ~45 slow-test gates pending discussion), D2 / D4 GREEN, D3 / D6 AMBER (now remediated), D5 RED (280 missing C++ tests across 49 files — under active remediation). Pre-Phase-2 NO-GO until D5 closes.

Each phase has a binding design doc, an executable plan doc, a progress log, and a completion doc — all under docs/migration/.

Architecture of a phase

Every phase follows a uniform shape, refined since Phase 2a:

brainstorm → design → plan → execute (subagent-driven) → review → tag → memory

1. Brainstorm & design

A binding spec (docs/migration/phase<N>-design.md) is approved before any code is written. Sections include scope (in/out), approach comparison, worktree topology, tolerance & probe discipline, pause triggers (A1–A19), decision log.

2. Plan

A bite-sized, checkbox-tracked task list (docs/migration/phase<N>-plan.md) with exact file paths, code snippets, and expected test-count deltas per task. No "TODO" or "TBD" — every step is concrete.

3. Execute

Each phase runs across 2–4 git worktrees (named jquantlib-<phase>-A, -B, -C, ...). A controller dispatches one fresh subagent per task with two-stage review:

  1. Spec compliance review — does the code match the spec exactly?
  2. Code quality review — strengths, blockers, and improvements.

Independent worktrees run in parallel; dependent ones serialize.

4. Pause triggers

Eighteen-and-counting documented conditions where the controller stops and asks the human. The most consequential have been:

  • A3 (reference is itself wrong) — fired in Phase 2i; Apple libm std::exp shown not always correctly-rounded; resolution = use CORE-MATH cr_exp directly as oracle.
  • A4 (needs new class outside scoped packages) — fired in Phase 2e (Swaption was a near-empty stub) and 2g (Fdm framework absent), each cleanly redirected.
  • A13 (transcendental ULP slack) — fired in Phase 2f; led to Phase 2i's CORE-MATH transcendental track.
  • A19 (post-swap tier promotion fails) — fired in Phase 2i (FdHullWhite — non-transcendental floor) and Phase 2i.5 (NCCS — Math.log floor); each pinpoints the next residual to address.

5. Tag + memory

Phase ends with git tag -a jquantlib-phase<N>-complete, a completion doc, and a refresh of long-lived project memory.

Precision track — the JQuantMath story

A recurring discovery from Phase 2f onwards: the JVM's java.lang.Math transcendentals carry up to ~1 ULP of slack relative to a correctly-rounded reference. That slack compounds through Fourier inversions, ADI schemes, and root-finders, and limits how tight an EXACT-tier comparison can ever be.

Phase 2i and 2i.5 attack the floor head-on by porting CORE-MATH — an academic correctly-rounded transcendental library (BSD/MIT, Sibidanov et al., Inria) — into a new package org.jquantlib.math.transcendental.JQuantMath.

Primitive Status Source Note
JQuantMath.exp ✅ Phase 2i CORE-MATH src/binary64/exp/exp.c Bit-exact across 508 probe cases including all 51 hard-cases DB entries
JQuantMath.cos ✅ Phase 2i.5 CORE-MATH src/binary64/cos/cos.c Bit-exact across 1,381 probe cases incl. Payne-Hanek stress through 2^50·π
JQuantMath.sin ✅ Phase 2i.5 CORE-MATH src/binary64/sin/sin.c Bit-exact across 1,376 probe cases
JQuantMath.log ✅ Phase 2i.6 CORE-MATH src/binary64/log/log.c Bit-exact across 1,203 probe cases first-shot. Sister long[4] dint64-style helpers (log_dint.h is bit-incompatible with sin/cos's dint.h)
JQuantMath.pow ✅ Phase 2n CORE-MATH src/binary64/pow/pow.c Bit-exact across 2,763 probe cases. Stage-1 doubles + Stage-2 Dint64 Ziv chain (Stage-3 Qint64 deferred — no oracle case demands it). Production-wired at 29 files / 57 sites.
JQuantMath.lgamma ❌ Blocked No correctly-rounded source available CORE-MATH does not have lgamma; msun/glibc options either non-correctly-rounded or license-incompatible. NCCS EXACT remains blocked.

Two supporting types in org.jquantlib.math.transcendental emulate the C source's extended-precision integers:

  • Dint64 — emulates unsigned __int128 (dint64_t in CORE-MATH source). Package-private; validated across 100 probe cases. Used by LogKernel (log), SinCosKernel (sin+cos), and PowKernel (pow stage-2 Ziv chain).
  • Qint64 — emulates 256-bit u128-pair arithmetic (qint64_t). Package-private; validated across 322 probe cases / 16 ops. Foundation for pow's stage-3 Ziv (deferred — not exercised by current oracle) and any future lgamma port.

Why CORE-MATH and not msun, glibc, or Apple libm?

This was a hard-won lesson:

  • JVM Math.exp (HotSpot) ≈ 1-ULP slack
  • FreeBSD msun e_exp.c ≈ same 1-ULP slack as JVM (Phase 2i pre-pivot BLOCKED finding)
  • Apple libm std::exp (macOS arm64) — almost correctly-rounded but not provably so; ~50/2^64 hard cases are still 1 ULP off (Phase 2i A3 finding, verified via 300-bit mpmath)
  • CORE-MATH cr_exp — correctly-rounded by design across all IEEE-754 rounding modes

Probe oracles for transcendentals therefore #include "coremath/exp.c" directly and call cr_exp(x) — not the platform <cmath>.

Ground truth

Resource Detail
Pinned C++ submodule QuantLib v1.42.1 @ 099987f0ca2c11c505dc4348cdb9ce01a598e1e5
Migration harness migration-harness/ — CMake-built C++17 probes linked against the submodule
Probe references migration-harness/references/ — JSON files keyed by test_group, consumed via ReferenceReader
Java module under port jquantlib/ (Maven; Java 11; JUnit 4)
Stub scanner tools/stub-scanner/scan_stubs.py — emits docs/migration/stub-inventory.json and worklist.md
Phase docs docs/migration/ — design, plan, progress, completion per phase

Repository structure

jquantlib/                              ← this repo root
├── jquantlib/                          ← Maven module under active port
│   ├── src/main/java/org/jquantlib/   ← production code
│   │   └── math/transcendental/       ← Phase 2i-2n (JQuantMath, ExpKernel, LogKernel, SinCosKernel, PowKernel, Dint64, Qint64)
│   └── src/test/java/                 ← JUnit 4 tests cross-validated against probes
├── jquantlib-helpers/                  ← helper classes
├── jquantlib-contrib/                  ← third-party contributions
├── jquantlib-samples/                  ← sample applications
│
├── migration-harness/                  ← C++ ground-truth scaffolding
│   ├── cpp/
│   │   ├── CMakeLists.txt
│   │   ├── quantlib/                  ← pinned QuantLib v1.42.1 submodule
│   │   └── probes/                    ← per-feature C++ probes emitting JSON
│   │       └── transcendental/
│   │           └── coremath/          ← vendored CORE-MATH algorithm sources
│   ├── references/                     ← generated reference JSONs
│   ├── setup.sh / generate-references.sh / verify-harness.sh
│   └── README.md
│
├── docs/migration/                     ← phase design, plan, progress, completion docs
├── tools/stub-scanner/                 ← Python scanner for in-progress stubs
└── README.md                           ← (this file)

Quick start

Build & test

# Test the Java module (run from the inner module — not the root)
cd jquantlib && mvn test
# Expected: Tests run: 3721, Failures: 0, Errors: 0, Skipped: 21

# Snapshot the stub scanner
python3 tools/stub-scanner/scan_stubs.py
# Expected: 0 stubs

# Verify the C++ harness is functional
./migration-harness/verify-harness.sh

Regenerate probe references

# (re-)build the C++ harness and emit all references/*.json
bash migration-harness/setup.sh
bash migration-harness/generate-references.sh

Run a sample

mvn clean verify install
# Sample apps live under jquantlib-samples/

Showcase — JQuantLib in action

The repo includes jquantlib-showcase/, an interactive Spring Boot web application that demonstrates the library in the browser: option pricing with live Greeks, a cross-engine comparison (closed-form, lattice, finite differences, Monte Carlo), Monte Carlo convergence (pseudo-random vs Sobol), implied volatility, barrier / Asian / discrete-dividend exotics, fixed-rate bonds, interpolated yield curves, market calendars, and a live runner for the bundled jquantlib-samples programs.

# 1. One-time: install the library artifacts into your local Maven repo (from the repo root)
mvn -pl jquantlib,jquantlib-helpers,jquantlib-samples -am install -DskipTests

# 2. Run the showcase
cd jquantlib-showcase
mvn spring-boot:run

Then open http://localhost:8080. Alternatively, build a self-contained jar and run it:

cd jquantlib-showcase
mvn -DskipTests package
java -jar target/jquantlib-showcase-1.0.0.jar

Requires JDK 25; uses the latest Spring Boot 4.0.x. Front-end libraries are vendored, so it runs fully offline. Full demo list and architecture: jquantlib-showcase/README.md.

What the next phase looks like

Phase 2n ✅ complete — JQuantMath.pow correctly-rounded (100% bit-exact 2,763/2,763 vs CORE-MATH cr_pow); Qint64 256-bit infra; 57-site production swap. JQuantMath now covers all 5 transcendentals: exp/log/sin/cos/pow. The next priorities, in autonomous-mode dispatch order:

  1. HestonModel rho constraint alignPositiveConstraintBoundaryConstraint(-1,1) to match C++ v1.42.1 (Phase 2m Track B carry-forward)
  2. AndreasenHuge calibration — Phase 2m Track D ported the surfaces but not the calibration loop
  3. SABRInterpolation shifted-strike support — Phase 2k Track A Scenario C unblocker
  4. U128.java shared util — consolidate u128 helpers across Dint64, Qint64, LogKernel, PowKernel, GaussianQuadrature.TqrEigen
  5. Douglas ADI / FdmAffineModelTermStructure — FdHullWhite real floor (Phase 2i WI-2 B-1 A19)
  6. PowKernel stage-3 (Qint64 chain + exact_pow) — only if a future test surfaces a hard-rounding case stage-2 fails
  7. JQuantMath.lgamma — still blocked; CORE-MATH has no lgamma. NCCS EXACT path still gated on this.
  8. C++ test-suite Java equivalents — every C++ engine test deserves a Java equivalent (~150-200K LOC of tests)
  9. Phase 3+ subsystemsexperimental/, models/marketmodels/, termstructures/credit/, inflation/

Binding exit criterion: every C++ class, function, header, and test from QuantLib v1.42.1 has a faithful Java equivalent. Realistic path to "done" is ~50-100+ phases.

Documentation links

Modules

Module Role
jquantlib-parent Root parent POM + aggregator (lives at the repo root)
jquantlib Main module — actively being ported (mirrors QuantLib/C++)
jquantlib-helpers Helper classes
jquantlib-contrib Third-party contributions
jquantlib-samples Sample code
jquantlib-showcase Interactive Spring Boot demo web app (see Showcase)

Contributing

This repository is currently a single-owner, direct-to-main migration project. Outside contributions are welcomed via issues, but the operational model assumes one engineer driving the port through subagent-assisted pipelines. If you'd like to help with a specific package or audit a phase, open an issue first to coordinate.

License

JQuantLib is released under the BSD License — see LICENSE.TXT. Vendored CORE-MATH source files retain their original MIT license headers under migration-harness/cpp/probes/transcendental/coremath/.

Acknowledgements

  • The QuantLib team — foundational C++ codebase and ongoing reference.
  • The CORE-MATH project (Sibidanov et al., Inria) — provably correctly-rounded transcendental algorithms.
  • The original JQuantLib contributors (~2007–2021) whose work forms the starting baseline.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors