A 100%-Python port of QuantLib — the de-facto open-source library for quantitative finance — being systematically rebuilt from C++ v1.42.1 with bit-exact precision guarantees.
Tip
📦 Released — PQuantLib v1.42.1 is on PyPI.
Install it in any Python ≥ 3.14 project — uv add pquantlib (or pip install pquantlib) — and price an option in a few lines; see the package README. The publish process is documented in RELEASING.md.
PQuantLib provides Python 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 faithfully as Python idioms allow, offering a precise, type-checked Python alternative to:
- The official QuantLib-Python SWIG bindings (which wrap the C++ library) — PQuantLib is a pure-Python reimplementation, not a binding.
- Building your own QuantLib bridge over JPype/Py4J to JQuantLib (slower, JVM-coupled).
- Re-implementing risk math piecewise on top of NumPy/SciPy (no QuantLib parity).
PQuantLib is being built as a systematic, full-fidelity port from C++ QuantLib v1.42.1, using the same migration discipline that delivered the sister project JQuantLib (Java port). Every functional change is cross-validated against C++ reference values via probe programs that link against the pinned QuantLib commit.
This port is the Python sibling of JQuantLib (tag jquantlib-final). Both projects:
- Pin the same C++ ground truth (
v1.42.1@099987f0) - Use the same migration patterns (subagent-driven, worktree-parallel, tier-stratified tolerances, probe-based cross-validation, direct-to-main per cluster)
- Share the same
migration-harness/design (C++ submodule + probe directory + JSON reference values) - Pass the same test-suite scope (faithful ports of C++
test-suite/*.cppfiles)
The two projects are independent but borrow heavily from each other's plans. Bugs surfaced in one port are checked in the other.
| Principle | What it means in practice |
|---|---|
| C++ is source of truth | Where Python diverges from QuantLib v1.42.1 — signatures, implementations, constants, behavior — the Python code is adapted to match C++ behavior. Python idioms (dataclasses, type hints, match/case, async) are used where natural. |
| 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. Python tests load those JSONs and assert against them via tolerance helpers. No expected value is invented inline. |
| Tier-stratified tolerances | Comparisons land in one of three tiers — EXACT (bit-identical via struct.pack('!d', x)), TIGHT (math.isclose(abs_tol=1e-14, rel_tol=1e-12)), LOOSE (math.isclose(abs_tol=1e-8, rel_tol=1e-8)). Per-test exceptions require an inline written justification. |
| Bulletproof, not fast | Every commit passes uv run pytest + uv run pyright + uv run ruff check. 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 (pquantlib-phase<N>-complete) and a completion document under docs/migration/. |
Per-phase scoping follows JQuantLib's L1–L5 layer sequencing, then adds opt-in extensions and a full-closure mega-phase:
- Phase 0: bootstrap — uv workspace, packages, migration-harness scaffold
- Phase 1: L1 — math primitives, time, foundations
- Phase 2: L2 — termstructures + indexes + cashflows + quotes
- Phase 3: L3 — instruments + pricingengines
- Phase 4: L4 — models (short-rate + equity stochastic-vol + calibration + swaption/capfloor engines)
- Phase 5: L5 — tree/lattice + Monte Carlo + finite-difference + exotic instruments
- Phase 6: high-impact Phase 4+5 carve-outs (American MC, Bates, DoubleBarrier) — end of the planned migration
- Phases 7–10: opt-in extensions — inflation, credit (CDS/CDO), cap/floor + SABR/ZABR vol surfaces, Gaussian1d short-rate
- Phase 11: full C++ v1.42.1 closure — the 12-wave MarketModels/LMM mega-phase →
pquantlib-final/pquantlib-100-complete - Phase 12: sibling packages —
pquantlib-contrib/-helpers/-samples
| Phase | Tag | What landed | Tests | Date |
|---|---|---|---|---|
| 0 | pquantlib-phase0-bootstrap |
Project skeleton (uv workspace, 4 packages, pyright strict, ruff lint+format, pytest), CLAUDE.md, migration-harness/ scaffold, BSD LICENSE | 2/0/0 (smoke) | 2026-05-23 |
| 1 L1-A (pilot) | pquantlib-phase1-l1-A-complete |
Foundations + time core (41 sovereign/exchange calendars via 5-agent fan-out) + 11 day counters + 8 first-math modules | 415/0/0 | 2026-05-23..2026-05-24 |
| 1 L1-B/C/D/E (parallel) | (merged into Phase 1 tag) | L1-B (12 copulas + 3 normal distributions + 2 statistics + 5 currencies), L1-C (9 Solver1D + 5 simple integrals), L1-D (5 RNGs all EXACT-tier + BoxMuller + 7 optimization scaffolding), L1-E (4 interpolations + bilinear + scipy-backed Cholesky). 4 isolated-worktree subagents in parallel, ~25 min wall-clock. | +166 → 581/0/0 | 2026-05-24 |
| 1 complete | pquantlib-phase1-complete |
Full L1 layer — math primitives, time, foundations. 581 tests across 16 C++ probes / ~10,000 reference values. | 581/0/0 | 2026-05-24 |
| 2 L2-A (pilot) | pquantlib-phase2-l2-A-complete |
Foundations: quotes + TermStructure + Extrapolator + BootstrapHelper + Index/IndexManager + 4 cross-cluster Protocols (Yield/Ibor/Overnight/Swap) | 649/0/0 | 2026-05-26 |
| 2 L2-B/C/D/E (parallel) | (merged into Phase 2 tag) | L2-B (yield curves + Compounding + InterestRate), L2-C (8 ibors + 2 swap + 7 rate helpers), L2-D (cashflows + Coupon hierarchy + leg generators + CashFlows aggregator + Duration), L2-E (vol termstructures: SmileSection + BlackVol/LocalVol family). 4 isolated-worktree subagents in parallel, ~35 min wall-clock. | +273 → 922/0/0 | 2026-05-26 |
| 2 complete | pquantlib-phase2-complete |
Full L2 layer — termstructures + indexes + cashflows + quotes. 922 tests; cross-cluster Protocols proven as fan-out glue. | 922/0/0 | 2026-05-26 |
| 3 L3-A (pilot) | pquantlib-phase3-l3-A-complete |
Foundations: Settings.evaluation_date observable + 4 retroactive L1/L2 cleanups; Payoff + Exercise + Instrument + PricingEngine + GenericEngine + BlackFormula + Option + 3 cross-cluster Protocols (Instrument / PricingEngine / StochasticProcess) | 1037/0/0 | 2026-05-27 |
| 3 L3-B/C/D/E (parallel) | (merged into Phase 3 tag) | L3-B (bonds: Bond + 4 concretes + Callability + DiscountingBondEngine + BondForward), L3-C (swaps: Swap + VanillaSwap + OIS + ZeroCoupon + Make-factories + DiscountingSwapEngine + 3 L2-C carry-over closures), L3-D (equity options + processes: StochasticProcess hierarchy + GBSM family + VanillaOption + EuropeanOption + AnalyticEuropeanEngine + BinomialVanillaEngine), L3-E (forwards: Forward + Position + FxForward + FRA + DiscountingFwdEngine + L2-C FraRateHelper carry-over). 4 isolated-worktree subagents in parallel, ~50 min wall-clock. | +247 → 1284/0/0 | 2026-05-27 |
| 3 complete | pquantlib-phase3-complete |
Full L3 layer — instruments + pricingengines. 1284 tests across ~50 classes; vanilla pricing path (bonds + swaps + European options + FX forwards) end-to-end. | 1284/0/0 | 2026-05-27 |
| 4 L4-A (pilot) | pquantlib-phase4-l4-A-complete |
Foundations: Phase 1 LM + Simplex carry-overs closed (scipy-backed); Parameter hierarchy + Model + CalibratedModel + CalibrationHelper bases + 3 cross-cluster Protocols (Model / CalibrationHelper / ShortRateModel) | 1351/0/0 | 2026-05-27 |
| 4 L4-B/C/D/E (parallel) | (merged into Phase 4 tag) | L4-B (short-rate: Vasicek + HW + CIR + ExtendedCIR + OU/CIR processes), L4-C (Heston + Bates + AnalyticHestonEngine), L4-D (G2++ + TwoFactorModel + multi-process suite), L4-E (Swaption + CapFloor instruments closing Phase 3 carve-out + Black/Bachelier/Jamshidian/G2 swaption engines + Black/Bachelier/AnalyticCapFloor engines + SwaptionHelper + CapHelper). 4 parallel cluster subagents, ~50 min wall-clock. | +193 → 1544/0/0 | 2026-05-27 |
| 4 complete | pquantlib-phase4-complete |
Full L4 layer — models (short-rate + equity stochastic-vol + calibration helpers + analytic swaption/capfloor engines). 1544 tests across ~40 classes. Phase 1 optimizer carry-overs + Phase 3 Swaption/CapFloor carve-outs closed. | 1544/0/0 | 2026-05-27 |
| 5 L5-A (pilot) | pquantlib-phase5-l5-A-complete |
Foundations: Phase 1 Sobol + Burley2020 + GammaFunction Lanczos + AkimaCubic carry-overs closed; Tree[T] + Lattice + DiscretizedAsset hierarchy + 3 cross-cluster Protocols | 1614/0/0 | 2026-05-28 |
| 5 L5-B/C/D/E (parallel) | (merged into Phase 5 tag) | L5-B (TrinomialTree + BlackScholesLattice + TreeSwaption/CapFloorEngine + BlackKarasinski — closes Phase 4 carve-outs), L5-C (MC framework + MCEuropeanEngine + MCAsianEngine), L5-D (FD framework + FdBlackScholesVanillaEngine + VanillaOption.implied_volatility — closes Phase 3 carve-out), L5-E (6 exotic instrument families + 6 analytic engines + BivariateCumulativeNormalDistribution — closes Phase 1 carve-out). 4 parallel cluster subagents, ~50 min wall-clock. | +269 → 1883/0/0 | 2026-05-28 |
| 5 complete | pquantlib-phase5-complete |
Full L5 layer — tree/lattice + MC + FD + exotic instruments. 1883 tests across ~50 classes. Closed 5 distinct phases of carry-overs (Phase 1 Sobol/GammaFunction/Akima/Bivariate; Phase 3 VanillaOption.implied_volatility; Phase 4 BlackKarasinski/TreeSwaption/TreeCapFloor). | 1883/0/0 | 2026-05-28 |
| 6 L6-A/B/C (parallel) | (merged into Phase 6 + final tags) | L6-A (LongstaffSchwartz American MC — closes Phase 5 carve-out), L6-B (BatesEngine — closes Phase 4 carve-out via add_on_term hook), L6-C (DoubleBarrierOption + AnalyticDoubleBarrierEngine Ikeda-Kunitomo 1992 — closes Phase 5 carve-out). Modernization sweep deleted after audit (codebase already modern from day 1). 3 parallel cluster subagents, ~30 min wall-clock. | +75 → 1958/0/0 | 2026-05-28 |
| 6 complete | pquantlib-phase6-complete |
High-impact Phase 4+5 carve-outs closed + final closure tooling (docs/carve-outs.md + 4 sample programs). 1958 tests; closes Phase 4 BatesEngine + Phase 5 American MC + DoubleBarrier. |
1958/0/0 | 2026-05-28 |
| Planned migration complete | pquantlib-phase6-complete (orig. pquantlib-final; re-pointed → Phase 11 on 2026-05-31) |
End of planned migration. ~340 classes ported across ~1958 tests (54.2% of jquantlib-final). Vanilla pricing + calibration end-to-end + American MC + analytic exotics covered. See docs/carve-outs.md for comprehensive carve-out documentation. |
1958/0/0 | 2026-05-28 |
| 7 inflation (opt-in extension) | pquantlib-phase7-complete |
Inflation Tier-1 carve-out closed: 5 region indexes + termstructure abstracts + Seasonality + Interpolated curves + inflation cashflows + pricers + ZeroCouponInflationSwap + YearOnYearInflationSwap + CPISwap + YoYInflationCapFloor + vol surfaces + 3 YoY analytic engines (Bachelier/Black/UnitDisplaced). L7-B Piecewise + helpers deferred to L7-Bb follow-up. 4 clusters; ~32 classes; +151 tests. | 2109/0/0 | 2026-05-28 |
| 8 piecewise inflation + credit + capfloor-vol (opt-in extension) | pquantlib-phase8-complete |
L8-A Piecewise{Zero,YoY}InflationCurve + IterativeBootstrap (closes L7-Bb + L2-B); L8-B Tier-1 credit (DefaultProbabilityTermStructure family + FlatHazardRate + 3 interpolated curves + probability traits + PiecewiseDefaultCurve scaffold + Spread/UpfrontCdsHelper + CreditDefaultSwap + Claim + MidPoint/Integral CDS engines); L8-C capfloor/optionlet/swaption vol surfaces (CapFloorTermVolatilityStructure family + OptionletVolatilityStructure family + OptionletStripper1 + SwaptionVolatilityStructure family + SwaptionVolatilityMatrix; closes Phase 2 capfloor-vol). 3 parallel-no-pilot clusters, ~60 min wall-clock. ~40 classes; +194 tests. | 2303/0/0 | 2026-05-28 |
| 9 cubic/bicubic + post-L8 ergonomics + SABR cube (opt-in extension) | pquantlib-phase9-complete |
L9-A pilot Cubic + Bicubic spline interpolators (CubicNaturalSpline + MonotonicCubicNaturalSpline + BicubicSpline via scipy delegation; opt-in interpolator= kwarg on L8-C surfaces; closes L1-E cubic-family); L9-B post-L8 ergonomics (PiecewiseYieldCurve + Discount/ZeroYield/ForwardRate traits + PiecewiseDefaultCurve bootstrap wiring + IsdaCdsEngine + implied_hazard_rate + conventional_spread + MakeCDS); L9-C SABR swaption smile cube (sabr_volatility + sabr_normal_volatility (Hagan 2002) + SabrInterpolation + SmileSection abstract + Flat/Interpolated/Sabr/Spreaded SmileSection + SwaptionVolatilityCube + SabrSwaptionVolatilityCube + InterpolatedSwaptionVolatilityCube; closes Phase-8 SABR). Pilot + 2-parallel, ~90 min wall-clock. ~22 classes; +161 tests. |
2464/0/0 | 2026-05-28 |
| 10 vol surface tail + Gaussian1d short-rate + interpolator tail / ZABR (opt-in extension) | pquantlib-phase10-complete |
L10-A vol surface tail (Kahale + Atm + AtmAdjusted + SabrInterpolated SmileSection + OptionletStripper2 + SabrInterpolation Halton multi-start + HaltonRsg; closes Phase 9 vol-tail residuals + L1-D HaltonRsg); L10-B Gaussian1d short-rate (Gaussian1dModel + Gsr + GsrProcess + Gaussian1dSwaptionVolatility; closes Tier-1 specialty short-rate, MarkovFunctional deferred); L10-C interpolator tail + ZABR (HymanFilteredCubic + ChebyshevInterpolation + MultiCubicSpline + AbcdInterpolation + zabr_volatility + ZabrSmileSection; closes L1-E interpolator tail + ZABR family). 3 parallel-no-pilot clusters, ~75 min wall-clock. ~17 classes; +188 tests. | 2652/0/0 | 2026-05-29 |
| 11 full C++ v1.42.1 closure (12-wave mega-phase) | pquantlib-phase11-complete + pquantlib-100-complete + pquantlib-final |
The complete-closure phase. W1 specialty models (MarkovFunctional + Gaussian1d engines + Bates variants + Heston SLV/GjrGarch); W2 ZABR/smile/bootstrap tail; W3 experimental/credit/* (copulas + 5 loss models + CDO + NthToDefault); W4 exotic/barrier/variance options; W5 experimental/finitedifferences/*; W6 NoArbSABR + SVI + vol surfaces + copulas + heuristic optimizers; W7 processes + full commodity/energy stack + experimental inflation + variance-gamma + FFT; W8 long-tail experimental (CMS-spread, callable/cat bonds, VannaVolga, CLV, xccy); W9–W11 the entire MarketModels/BGM/LMM domain (core + models + evolvers + calibration + products + callability + pathwise greeks — 2 canonical end-to-end tests pass); W12 coverage-audit + core cashflows CMS/CappedFloored/Digital gap-fill. ~520 classes; +1396 tests. Functional 1:1 with C++ v1.42.1. |
4048/0/0 | 2026-05-31 |
| 12 sibling-packages migration | pquantlib-siblings-complete |
The three JQuantLib sibling Maven modules ported into the workspace members. W-S1 XorShiftRandom → pquantlib-contrib (JQuantLib-original, no C++ equiv); W-S2 dividend-option compat primitives (DividendVanillaOption + BinomialDividendVanillaEngine + BlackScholesDividendLattice) + W-S3 6 helper builders + the retired pre-1.0 FD framework (~35 classes) → pquantlib-helpers (retired-API classes hosted in the helpers package, on v1.42.1 primitives, TIGHT vs Java); W-S4 ConvertibleBond subsystem (Convertible{FixedCoupon,ZeroCoupon}Bond + SoftCallability + DiscretizedConvertible + TsiveriotisFernandesLattice + BinomialConvertibleEngine) → pquantlib core, closing the carve-out (TIGHT vs C++ N=801); W-S5 sample programs + AllSamples runner + smoke suite → pquantlib-samples (12 COMPLETE + 1 INCOMPLETE + 3 PENDING). API-era reconciliation: siblings targeted ~QL-1.0; core stays pure v1.42.1. ~45 classes; +189 tests / +3 skips. |
4237 passed, 3 skipped | 2026-06-03 |
Current tip on main: Phase 12 complete — pquantlib-siblings-complete. The three JQuantLib sibling packages (pquantlib-contrib, pquantlib-helpers, pquantlib-samples) are now populated; core remains functional 1:1 with C++ QuantLib v1.42.1 (Phase 11, pquantlib-100-complete / pquantlib-final). The ConvertibleBond carve-out is closed in core; period-specific retired-API dividend/FD classes are hosted in pquantlib-helpers per the API-era reconciliation. 4237 passed + 3 skipped (the 3 PENDING samples). See docs/migration/phase12-completion.md for the sibling-migration closure summary + docs/migration/phase11-completion.md for the 12-wave core closure + docs/carve-outs.md Statistics.
Sample programs: Run uv run python -m pquantlib_samples.{vanilla_swap_pricing,heston_calibration,american_option_mc,double_barrier_analytic} for end-to-end demos.
What's available today (detailed catalog of the L1–L5 foundation — Phases 1–5; later phases are summarized in the migration table above)
Phase 1 ships the foundation: math primitives, time machinery, day counters, currencies, distributions, random number generators, simple optimization scaffolding, and a starter set of 1-D/2-D interpolations. Importable as pquantlib.<module>.
pquantlib.exceptions—LibraryException(C++QL::Erroranalogue),RootNotBracketed, etc.pquantlib.qassert—require(cond, msg)/ensure(...)(C++QL_REQUIRE/QL_ENSURE).pquantlib.testing.tolerance—exact(a, e)/tight(a, e)/loose(a, e)/custom(a, e, abs_tol, rel_tol).pquantlib.testing.reference_reader—load("<topic>/<class>")returns probe-emitted JSON.pquantlib.patterns—Observer/Observable(weakref-backed),Singleton(metaclass),Visitor/Visitable(Protocols),LazyObject,CuriouslyRecurringTemplate.
pquantlib.time.Date— frozen@dataclass, Excel-1900 epoch,+/-/</etc. with@overload-narrowed return types.pquantlib.time.Period—frozen+slots, normalized arithmetic.pquantlib.time.DateParser/PeriodParser— string ↔ value-type.pquantlib.time.Calendar— abstract base + 4 trivial concretes (NullCalendar,WeekendsOnly,JointCalendar,BespokeCalendar) + 41 sovereign/exchange calendars (US/UK/Germany/France/Italy/Japan/Switzerland/Sweden/Brazil/China/India/Canada/Australia/Russia/Israel/etc., each with default-marketConventionenum).pquantlib.time.Schedule+MakeSchedule— builder pattern for date schedules.pquantlib.time.IMM/ASX/ECB— module-of-free-functions exportingnext_date,is_imm_date,known_date, etc.pquantlib.time.TimeGrid— mandatory + close-enough times bundle.pquantlib.time.TimeSeries[T]— PEP 695 generic; sorted-by-date container.
pquantlib.daycounters — DayCounter abstract + 11 concretes (Actual360, Actual365Fixed w/ Standard/NoLeap/Actual365 convention dispatch, ActualActual w/ ISMA/Bond/ISDA/Historical/Actual365/AFB/Euro variants, Thirty360 w/ USA/BondBasis/European/Italian/German/ISMA/ISDA/NASD/EurobondBasis variants, Business252, One, Simple, Thirty365).
pquantlib.math.constants—M_PI,QL_EPSILON,QL_MIN_REAL,QL_MAX_REAL(frommath+sys.float_info).pquantlib.math.closeness.close_enough— relative-tolerance comparison.pquantlib.math.rounding— 6Typeenums (Up/Down/Closest/Floor/Ceiling/None).pquantlib.math.factorial— table to n=27 +math.lgammafallback (LOOSE-tier).pquantlib.math.error_function—math.erfdelegate (LOOSE-tier).pquantlib.math.beta+incomplete_beta+beta_continued_fraction— closed-form viamath.lgamma.pquantlib.math.bernstein_polynomial+pascal_triangle— combinatorial helpers withqassert.requireguards.
pquantlib.math.distributions—NormalDistribution,CumulativeNormalDistribution(viamath.erf),InverseCumulativeNormal(Acklam algorithm),MoroInverseCumulativeNormal.pquantlib.math.copulas— 12 closed-form 2-D copulas: AliMikhailHaq, Clayton, FarlieGumbelMorgenstern, Frank, Galambos, Gaussian, Gumbel, HuslerReiss, Independent, MaxCopula, MinCopula, Plackett. (MarshallOlkin deferred.) All@dataclass(frozen=True, slots=True)with__call__.pquantlib.math.statistics—GeneralStatistics(running mean/variance/kurtosis/skew),IncrementalStatistics(Welford-style aggregator).
pquantlib.math.randomnumbers — MersenneTwisterUniformRng (MT19937), KnuthUniformRng, LecuyerUniformRng, Ranlux3UniformRng, Xoshiro256StarStarUniformRng, BoxMullerGaussianRng. Every PRNG reproduces C++ outputs bit-for-bit via struct.pack('!d', x) comparison.
pquantlib.math.solvers1d—Solver1Dabstract + 9 concretes (Bisection,Brent,FalsePosition,FiniteDifferenceNewtonSafe,Halley,Newton,NewtonSafe,Ridder,Secant).pquantlib.math.integrals—Integratorabstract + 5 simple concretes (SimpsonIntegral,TrapezoidIntegral,SegmentIntegral,GaussKronrodAdaptive,GaussLobattoIntegral).
pquantlib.math.optimization — Constraint family (NoConstraint, PositiveConstraint, BoundaryConstraint), CostFunction, EndCriteria, OptimizationMethod abstract, Problem. (Concrete LM/BFGS/Simplex/CG/SA optimizers deferred to a follow-up cluster.)
pquantlib.math.interpolations—Interpolationabstract + 4 1-D concretes (LinearInterpolation,LogLinearInterpolation,BackwardFlatInterpolation,ForwardFlatInterpolation) +BilinearInterpolation2-D.pquantlib.math.matrixutilities—Array/Matrixtyping aliases overnpt.NDArray[np.float64], plusCholeskyDecomposition(scipy delegate).
pquantlib.currencies — 5 ISO descriptors (USD, EUR, GBP, JPY, CHF) as @dataclass(frozen=True, slots=True). (More currencies follow in L2 termstructures work.)
Full GaussianOrthogonalPolynomial hierarchy (12+ subclass tree), SobolRsg + Burley2020SobolRsg low-discrepancy, LevenbergMarquardt/Bfgs/Simplex/ConjugateGradient/SimulatedAnnealing optimizers, 8+ cubic-spline variants (AkimaCubicInterpolation, KrugerCubic, FritschButland, etc.), QRDecomposition/EigenvalueDecomposition/SVD/SparseMatrix utilities, full GammaFunction (currently delegated to math.lgamma). See docs/migration/phase1-completion.md.
pquantlib.quotes—Quoteabstract +SimpleQuote(mutable, observer-aware) +DerivedQuote(quote, f)+CompositeQuote(quote1, quote2, f)— market-observable handles used by every termstructure and rate-helper input.
pquantlib.termstructures.term_structure.TermStructure— abstract base; reference_date / max_date / day_counter / calendar / extrapolation support.pquantlib.termstructures.extrapolator.Extrapolator— enable/disable extrapolation flag mixin.pquantlib.termstructures.bootstrap_helper.BootstrapHelper[TS]— abstract; PEP 695 generic;PillarChoiceenum.pquantlib.termstructures.protocols—YieldTermStructureProtocol,IborIndexProtocol,OvernightIndexProtocol,SwapIndexProtocol—@runtime_checkablecross-cluster glue.
pquantlib.termstructures.yield_term_structure.YieldTermStructure (abstract); concretes under pquantlib.termstructures.yield_.*:
FlatForward(+FlatForward.from_rate(...)classmethod) — constant-rate curve.InterpolatedZeroCurve/InterpolatedForwardCurve/InterpolatedDiscountCurve— parameterized by anInterpolationFactory(PEP 695 generics; default Linear).ZeroCurve/ForwardCurve/DiscountCurve— PEP 695typealiases over the linear-interp variants.ForwardSpreadedTermStructure/ZeroSpreadedTermStructure/DiscountSpreadedTermStructure— Quote-driven spread overlays.ImpliedTermStructure— forward-shifted view of an existing curve.
DepositRateHelper/FraRateHelper/FuturesRateHelper/SwapRateHelper/OISRateHelper/BondHelper/FxSwapRateHelper— all subclassBootstrapHelper. SwapRateHelper / OISRateHelper / BondHelperimplied_quote()deferred to L3 (need pricing engines).
pquantlib.time.compounding.Compounding— IntEnum (Simple / Compounded / Continuous / SimpleThenCompounded / CompoundedThenSimple).pquantlib.interest_rate.InterestRate— rate + day-counter + compounding + frequency;compound_factor(t)/discount_factor(t)/equivalent_rate(...)/implied_rate(...)factory; null sentinel viaInterestRate.null()+is_null().
pquantlib.indexes.index.Index (abstract base, observable) + IndexManager singleton (fixings repo, case-insensitive); under pquantlib.indexes.*:
InterestRateIndex/IborIndex/OvernightIndex/SwapIndex— abstract bases.- 8 ibor concretes:
Euribor,USDLibor,GBPLibor,Eonia,Sofr,Sonia,FedFunds,Estr. Multi-tenor viaPeriodarg + classmethod shortcuts (e.g.Euribor.three_months()). - 2 swap indexes:
EuriborSwapIsdaFixA,UsdLiborSwapIsdaFixAm.
pquantlib.cashflows.*:
CashFlow(abstract) +SimpleCashFlow(+Redemption+AmortizingPayment).Coupon(abstract) +FixedRateCoupon+FloatingRateCoupon+IborCoupon+OvernightIndexedCoupon.fixed_rate_leg(...)/ibor_leg(...)/overnight_leg(...)— free-function leg generators (Pythonic replacement for C++ Builder pattern).CouponPricer(abstract) +IborCouponPricer+BlackIborCouponPricer+CompoundingOvernightIndexedCouponPricer.CashFlows— static methods aggregator:npv/bps/irr/simple_duration/macaulay_duration/modified_duration/convexity.Duration— IntEnum (Simple / Macaulay / Modified).
pquantlib.termstructures.volatility.*:
VolatilityTermStructureabstract +SmileSectionabstract +FlatSmileSectionconcrete.BlackVolTermStructure(+BlackVolatilityTermStructure+BlackVarianceTermStructureadapters) abstracts +BlackConstantVol+BlackVarianceCurve+BlackVarianceSurface(bilinear) concretes.LocalVolTermStructureabstract +LocalConstantVol+LocalVolCurve+LocalVolSurface(Dupire, flat-curve simplification) concretes.
All inflation termstructures/indexes/cashflows; all credit termstructures; ZABR/SABR/XABR volatility models; capfloor/optionlet/swaption volatility; 35 specialty ibors beyond the 8 must-port; specialized cashflows (Digital / Cms / CapFloored / AverageBmaCoupon); advanced curve construction (FittedBondDiscountCurve / MultiCurve / GlobalBootstrap / spline-fitting variants); PiecewiseYieldCurve full bootstrap. See docs/migration/phase2-completion.md.
(Phase 3 closed the previously-deferred Settings.evaluation_date wiring, SwapRateHelper.implied_quote, OISRateHelper.implied_quote, SwapIndex.forecast_fixing, and FraRateHelper(useIndexedCoupon=True) carry-overs.)
pquantlib.payoffs—Payoffabstract +PlainVanillaPayoff(option_type, strike)+CashOrNothingPayoff+AssetOrNothingPayoff+GapPayoff+SuperFundPayoff+SuperSharePayoff.OptionTypeenum (Call=1, Put=−1).pquantlib.exercise—Exerciseabstract +EuropeanExercise(date)+AmericanExercise(earliest, latest=None, payoff_at_expiry=False)+BermudanExercise(dates, ...).pquantlib.option.Option— abstract base for option instruments.pquantlib.patterns.observable_settings.ObservableSettings— now exposesevaluation_datefield with observer notification.
Instrumentabstract +OneAssetOptionabstract.pquantlib.instruments.protocols—InstrumentProtocol,PricingEngineProtocol,StochasticProcessProtocol.- Bonds (
pquantlib.instruments.bonds.*):Bond+FixedRateBond+ZeroCouponBond+FloatingRateBond+AmortizingFixedRateBond+Callability+CallabilitySchedule+BondForward. - Swaps:
Swap+FixedVsFloatingSwap+VanillaSwap+OvernightIndexedSwap+ZeroCouponSwap+make_vanilla_swap(...)+make_ois(...)free-function factories. - Options:
VanillaOption+EuropeanOption. - Forwards:
Forwardabstract +ForwardTypePayoff+Positionenum +FxForward+ForwardRateAgreement.
PricingEngineabstract +GenericEngine[ArgsT, ResultsT]PEP 695 generic.pquantlib.pricingengines.black_formula—black_formula(...)(lognormal) /bachelier_black_formula(...)/black_formula_implied_std_dev(...)/bachelier_black_formula_implied_vol(...)+ Black-vega derivatives.pquantlib.pricingengines.bond.discounting_bond_engine.DiscountingBondEngine.pquantlib.pricingengines.swap.discounting_swap_engine.DiscountingSwapEngine.pquantlib.pricingengines.forward.discounting_fwd_engine.DiscountingFwdEngine.pquantlib.pricingengines.vanilla.analytic_european_engine.AnalyticEuropeanEngine— closed-form BSM + Greeks (delta/gamma/vega/theta/rho).pquantlib.pricingengines.vanilla.binomial_engine.BinomialVanillaEngine— parameterized byTreeBuilderenum (CRR / JarrowRudd / Tian / LeisenReimer); supports American/Bermudan via numpy backward induction.pquantlib.pricingengines.vanilla.black_calculator.BlackCalculator— Visitor-replacement helper.
StochasticProcess+StochasticProcess1Dabstracts.EulerDiscretization— drift/diffusion stepper.GeneralizedBlackScholesProcess(risk-free + dividend + Black-vol curves),BlackScholesProcess(no dividends),BlackProcess(no rates — Black 76),BlackScholesMertonProcess(full BSM).
All exotic instruments (Asian/Barrier/Basket/Cliquet/Lookback/Quanto/etc.); specialty bonds; specialty swaps; all MC + FD engines; lattice/tree hierarchy; VanillaOption.implied_volatility (needs FD engine). Full list in docs/migration/phase3-completion.md.
(Phase 4 closed the previously-deferred Swaption + CapFloor instruments, plus the Heston / Hull-White / G2 / Vasicek / CIR analytic engines.)
pquantlib.math.optimization.levenberg_marquardt.LevenbergMarquardt—scipy.optimize.least_squares(method='lm')wrapper.pquantlib.math.optimization.simplex.Simplex—scipy.optimize.minimize(method='Nelder-Mead')wrapper.
Modelabstract +TermStructureConsistentModel+CalibratedModel(withcalibrate(instruments, method, end_criteria, ...)orchestration).Parameterhierarchy:NullParameter/ConstantParameter/PiecewiseConstantParameter/TermStructureFittedParameter.CalibrationHelper+BlackCalibrationHelperabstract bases.pquantlib.models.protocols—ModelProtocol,CalibrationHelperProtocol,ShortRateModelProtocol.
ShortRateModel+OneFactorModel+OneFactorAffineModelabstracts (closed-formA(t,T),B(t,T),discount_bond_optionvia Jamshidian).Vasicek(r0, a, b, sigma, lambda_=0.0).HullWhite(termStructure, a=0.1, sigma=0.01)— extended-Vasicek withphi(t)closed-form +convexity_bias.CoxIngersollRoss(r0, theta, k, sigma).ExtendedCoxIngersollRoss(termStructure, theta, k, sigma, r0).TwoFactorModelabstract.G2(termStructure, a, sigma, b, eta, rho)— Brigo-Mercurio G2++ with closed-formdiscount_bond+discount_bond_option+swaption.
HestonModel(process)+HestonModelHelper(calibration helper).BatesModel(process)— HestonModel + Merton jumps.
pquantlib.processes.*:
OrnsteinUhlenbeckProcess,CoxIngersollRossProcess,HestonProcess(2-D: S, V),BatesProcess,G2Process,G2ForwardProcess,HullWhiteForwardProcess,ForwardMeasureProcess(1-D + multi-D).
pquantlib.instruments.swaption.Swaption+pquantlib.instruments.cap_floor.{CapFloor, Cap, Floor}.
SwaptionHelper+CapHelper(concreteBlackCalibrationHelpers).
pquantlib.pricingengines.*:
vanilla.analytic_heston_engine.AnalyticHestonEngine(model, integration_order=144)— Gatheral characteristic function +scipy.integrate.quad.swaption.black_swaption_engine.BlackSwaptionEngine(model-free Black).swaption.bachelier_swaption_engine.BachelierSwaptionEngine(model-free normal).swaption.jamshidian_swaption_engine.JamshidianSwaptionEngine(model)— analytic under anyOneFactorAffineModelvia Jamshidian decomposition.swaption.g2_swaption_engine.G2SwaptionEngine(model, range_, intervals)— analytic G2 via 1-D SegmentIntegral + nested Brent solve.capfloor.black_capfloor_engine.BlackCapFloorEngine,bachelier_capfloor_engine.BachelierCapFloorEngine.capfloor.analytic_capfloor_engine.AnalyticCapFloorEngine(model)— usesmodel.discount_bond_optionfor each caplet/floorlet (HW/Vasicek/CIR/ExtendedCIR).
MarketModels (125 files of LMM machinery); specialty short-rate (Gaussian1d / GSR / MarkovFunctional / HestonSLV / GJR-GARCH / BatesDoubleExp); volatility models (GARCH / GarmanKlass / etc.). See docs/migration/phase4-completion.md.
(Phase 5 closed: BlackKarasinski + TreeSwaptionEngine + TreeCapFloorEngine + MC framework + FD framework + exotic instruments.)
pquantlib.math.randomnumbers.sobol_rsg.SobolRsg+Burley2020SobolRsg— low-discrepancy via scipy.stats.qmc.Sobol.pquantlib.math.distributions.gamma_function.GammaFunction— Lanczos approximation; replaces math.lgamma in Factorial.pquantlib.math.distributions.bivariate_cumulative_normal.BivariateCumulativeNormalDistribution+Dr78alias — Genz-Bretz via scipy.stats.multivariate_normal.pquantlib.math.interpolations.akima_cubic_interpolation.AkimaCubicInterpolation— scipy.interpolate.Akima1DInterpolator.
Tree[T]+Latticeabstracts;BinomialTreeconcretes (CRR / JarrowRudd / Tian / LeisenReimer);TrinomialTree;TreeLattice1D;BlackScholesLattice.DiscretizedAsset+DiscretizedOption+DiscretizedDiscountBond+DiscretizedSwap+DiscretizedSwaption+DiscretizedCapFloor.
pquantlib.pricingengines.swaption.tree_swaption_engine.TreeSwaptionEngine(model, time_steps).pquantlib.pricingengines.capfloor.tree_capfloor_engine.TreeCapFloorEngine(model, time_steps).pquantlib.models.shortrate.onefactor.black_karasinski.BlackKarasinski(termStructure, a=0.1, sigma=0.1).ShortRateModel.tree(grid)across Vasicek / HW / CIR / ExtendedCIR / BlackKarasinski.
Path+MultiPath+BrownianBridge+PathGenerator+MultiPathGenerator+PathPricer+McSimulation+MonteCarloModel.MCVanillaEngineabstract +MCEuropeanEngine+MCDiscreteArithmeticAveragePriceEngine.DiscreteAveragingAsianOption+AnalyticDiscreteGeometricAveragePriceAsianEngine(Levy 1997).
- 18 modules: layout + meshers (FdmBlackScholesMesher) + operators (TripleBandLinearOp + FirstDeriv/SecondDeriv + FdmBlackScholesOp) + schemes (ExplicitEuler/ImplicitEuler/CrankNicolson) + step conditions (FdmAmericanStepCondition + Composite) + solver (FdmBackwardSolver) + config DTOs.
pquantlib.pricingengines.vanilla.fd_black_scholes_vanilla_engine.FdBlackScholesVanillaEngine(process, t_grid=100, x_grid=100, scheme=CrankNicolson)— supports European + American.pquantlib.instruments.vanilla_option.VanillaOption.implied_volatility(...)— Brent solver dispatching to AnalyticEuropean or FD as appropriate. Closes Phase 3 carve-out.
AsianOptionfamily (ContinuousAveragingAsianOption+DiscreteAveragingAsianOption).BarrierOption+BarrierTypeIntEnum (DownIn / UpIn / DownOut / UpOut).BasketOption+BasketPayoffhierarchy (Min / Max / Average / Spread).ContinuousFloatingLookbackOption+ContinuousFixedLookbackOption.CliquetOption,DigitalOption.- Analytic engines:
AnalyticContinuousGeometricAveragePriceAsianEngine(Kemna-Vorst),AnalyticBarrierEngine(Reiner-Rubinstein),AnalyticBinaryBarrierEngine,StulzEngine(2-asset basket),AnalyticContinuousFloatingLookbackEngine(Conze-Viswanathan).
FloatingTypePayoff,PercentageStrikePayoff.
Tree/lattice: TreeLattice2D + G2.tree(), Joshi4/AdditiveEQP/Trigeorgis builders. MC: LongstaffSchwartz American MC, Heston/G2/Bates/HW MC engines, low-discrepancy MC, all exotic MC engines. FD: multi-asset FD (Heston/G2/Bates), time-dependent operators, operator-splitting (HV/MS/CS), BoundaryCondition framework, Concentrating1dMesher. Exotic: DoubleBarrier, PartialTimeBarrier, SoftBarrier, HolderExtensible, ComplexChooser, Compound, 3+ asset baskets. See docs/migration/phase5-completion.md. Phase 6 addresses high-impact remainder + modernization.
pquantlib/ # repo root
├── pquantlib/ # core package
│ ├── pyproject.toml
│ ├── src/pquantlib/ # the actual sources
│ │ ├── __init__.py
│ │ ├── py.typed
│ │ └── ... # ported modules land here
│ └── tests/ # pytest tests
├── pquantlib-contrib/ # community contributions / extras
│ └── (same shape)
├── pquantlib-helpers/ # convenience builders + utilities
│ └── (same shape)
├── pquantlib-samples/ # example scripts (not packaged for distribution)
│ └── (same shape)
├── pquantlib-showcase/ # interactive Streamlit demo app (see its README)
│ └── app.py, pages/, src/, tests/
├── migration-harness/ # C++ ground-truth infrastructure
│ ├── cpp/quantlib/ # git submodule → QuantLib v1.42.1 @ 099987f0
│ ├── cpp/probes/ # one-off C++ probes emitting reference JSONs
│ ├── references/ # JSON reference value files consumed by pytest
│ ├── build-cpp.sh # builds QuantLib + all probes
│ └── generate-references.sh # runs all probes, emits JSONs
├── docs/migration/ # per-phase design / plan / progress / completion docs
├── pyproject.toml # workspace root (members = the 5 packages above)
├── .python-version # 3.14
├── CLAUDE.md # binding instructions for Claude Code sessions
├── README.md # this file
└── LICENSE # BSD
Every phase follows a uniform shape (refined from JQuantLib's discipline):
brainstorm → design → plan → execute (subagent-driven) → review → tag → memory
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–A8), decision log.
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.
Each phase runs across 2–5 git worktrees (named pquantlib-<phase>-A, -B, -C, ...). A controller dispatches one fresh subagent per cluster with two-stage review:
- Spec compliance review — does the code match the spec exactly?
- Code quality review — pyright strict, ruff clean, idiomatic Python, no dead code, no half-finished implementations.
After both reviews pass, the cluster fast-forwards to main.
Final code-quality reviewer for the entire phase. Signed annotated tag with a comprehensive commit message. Completion doc written.
git clone git@github.com:jlmoya/pquantlib.git
cd pquantlib
# Install dependencies into the workspace venv
uv sync
# Run the full suite
uv run pytest
# Type-check
uv run pyright
# Lint
uv run ruff check
# Build the C++ harness (one-time setup before probe-validated tests)
./migration-harness/build-cpp.shC++ QuantLib is pinned to v1.42.1 @ commit 099987f0ca2c11c505dc4348cdb9ce01a598e1e5 (2026-04-16 — same pin as the sister project JQuantLib). The submodule lives at migration-harness/cpp/quantlib/.
When v1.42.1 has a documented bug (caught via cross-validation), PQuantLib mirrors the buggy behavior in production code and documents the bug inline. Fixing the bug is a separate decision logged in the phase-design's decision log.
BSD (same as QuantLib).
- The QuantLib team — foundational C++ codebase and ongoing reference.
- The JQuantLib sister project — proved the migration discipline that PQuantLib reuses.
- The CORE-MATH project (Sibidanov et al., Inria) — provably correctly-rounded transcendental algorithms (used by JQuantLib's JQuantMath; PQuantLib leverages
mpmathfor the equivalent precision guarantees).