Live base-date CPI coupons and legs¶
Python and Go can derive the CPI denominator from a retained inflation index instead of requiring a fixed CPI number. These are additive named factories; existing explicit-base constructors and their numerical behavior are unchanged.
| Layer | Coupon | Leg |
|---|---|---|
| Rust | CpiCoupon::from_base_date |
CpiLeg::from_base_date |
| Python | CPICoupon.from_base_date |
CPILeg.from_base_date |
| Go | Session.NewCPICouponFromBaseDate |
Session.NewCPILegFromBaseDate |
| C | itofin_cpi_coupon_from_base_date |
itofin_cpi_leg_from_base_date |
Observation contract¶
- Base CPI is read lazily and live, not frozen when the object is built. A missing base fixing does not prevent construction, but a valuation requiring it fails. Adding a missing fixing or relinking the inflation curve is observed by existing coupons and legs.
- A coupon reads its denominator with the native convention:
laggedFixing(base_date + observation_lag, observation_lag, interpolation). - The terminal indexed principal reads its denominator with
laggedFixing(base_date, zero_lag, interpolation). This is intentionally different from the coupon route. - Month arithmetic is not invertible. January 31 plus one month clamps to February's end, and subtracting one month can return a different January day. Linear interpolation also weights by the unlagged observation period. Do not replace either native route with a hand-computed fixed denominator.
- Omitting a leg's base date uses schedule start minus observation lag. An omitted base date requires at least one coupon period; an explicit date can also construct a single terminal payment in Rust/C.
- Zero-rate leg coupons remain fixed zero coupons requiring no CPI fixings. Their terminal indexed principal is still fixing-dependent.
Coupon base_fixing() / BaseFixing() returns the effective denominator and
can fail. C uses query field 6. The old Rust base_cpi() stored-value getter
is unchanged for explicit-base objects; on new date-based coupons it returns
native f64::MAX, the no-explicit-base sentinel, not an actual CPI level.
Python and Go expose the fallible effective query rather than that sentinel.
The new Go/C factories reuse the old configuration structures and ignore
BaseCPI / base_cpi in this named path, including non-finite stored values.
Old explicit-base factories still validate and use that field. Other finite
parameters, enums, dates, lags and observation bounds remain validated. A
nonzero supplied base date must be valid; only a missing leg base date uses
its default. A zero observed CPI denominator is an error, not a finite price.
Ownership and pricing¶
Indices, their Settings and linked curves remain retained and live. Python/Go
leg facades fix payment and ex-coupon dates at construction; build() / Build()
clones that graph. Rebuild the factory to adopt later calendar holiday edits.
Generic Leg NPV uses the same Settings object as the inflation index, not
just equal evaluation dates. Go inputs must also share one Session.
Attach a plain CPICouponPricer before querying a directly constructed coupon's
rate or amount. Leg construction attaches the existing plain pricer. This
adds no convexity correction, cap/floor optionlet, new volatility model,
CPIBond base-date constructor or CPISwap fair fixed-rate formula.
Validation and examples¶
The tracked coupon matrix covers 36 native cases and three market states: Flat/Linear, 0/1/3-month lags, signed/zero rates, historical/forecast observations, ex-coupon accrual and curve relinking. A separate 32-case leg matrix covers explicit/default bases, irregular schedules, zero-rate coupons, repeating rate vectors, varying notionals, adjusted principal, growth/full principal and NPV.
Coupon fixtures are produced by scripts/generate_cpi_base_date_oracle.py
using QuantLib 1.43. The leg producer uses pinned source headers with the
independent wheel and records that mixed provenance, not a full-source build.
Its entire numerical matrix was also independently reconstructed through SWIG.
See the two provenance JSON files under sdk/go/testdata/cpi-base-date-*.