Source code for pyquantlib.builders

"""
Pythonic wrapper functions for QuantLib Make* builders.

Each function accepts the builder's constructor arguments as positional
parameters and all builder options as keyword arguments, returning the
built object directly.

See docs/design/builder-pattern.md for the design rationale.
"""

from . import _pyquantlib as _ql

# ---------------------------------------------------------------------------
# Shared helper
# ---------------------------------------------------------------------------

def _apply_kwargs(func_name, method_map, builder, kwargs):
    """Apply keyword arguments to a builder via its with* methods."""
    for name, value in kwargs.items():
        try:
            method = method_map[name]
        except KeyError:
            raise TypeError(
                f"{func_name}() got an unexpected keyword argument {name!r}"
            ) from None
        getattr(builder, method)(value)


# ---------------------------------------------------------------------------
# MakeSchedule
# ---------------------------------------------------------------------------

_MAKESCHEDULE_METHODS = {
    "tenor": "withTenor",
    "frequency": "withFrequency",
    "calendar": "withCalendar",
    "convention": "withConvention",
    "terminationDateConvention": "withTerminationDateConvention",
    "rule": "withRule",
    "endOfMonth": "endOfMonth",
    "firstDate": "withFirstDate",
    "nextToLastDate": "withNextToLastDate",
}


[docs] def MakeSchedule(effectiveDate=None, terminationDate=None, *, forwards=False, backwards=False, **kwargs): """Build a Schedule from keyword arguments. Parameters ---------- effectiveDate : Date, optional Start date of the schedule. terminationDate : Date, optional End date of the schedule. forwards : bool Use forward date generation. backwards : bool Use backward date generation. **kwargs Builder options mapped to ``with*`` methods (e.g. ``tenor``, ``frequency``, ``calendar``, ``convention``, ``rule``, ...). Returns ------- Schedule """ ms = _ql.MakeSchedule() if effectiveDate is not None: ms.from_(effectiveDate) if terminationDate is not None: ms.to(terminationDate) if forwards: ms.forwards() if backwards: ms.backwards() _apply_kwargs("MakeSchedule", _MAKESCHEDULE_METHODS, ms, kwargs) return ms.schedule()
# --------------------------------------------------------------------------- # MakeCapFloor # --------------------------------------------------------------------------- _MAKECAPFLOOR_METHODS = { "nominal": "withNominal", "effectiveDate": "withEffectiveDate", "tenor": "withTenor", "calendar": "withCalendar", "convention": "withConvention", "terminationDateConvention": "withTerminationDateConvention", "rule": "withRule", "endOfMonth": "withEndOfMonth", "firstDate": "withFirstDate", "nextToLastDate": "withNextToLastDate", "dayCount": "withDayCount", "asOptionlet": "asOptionlet", "pricingEngine": "withPricingEngine", } def MakeCapFloor(capFloorType, tenor, index, strike=None, forwardStart=None, **kwargs): """Build a CapFloor from keyword arguments. Parameters ---------- capFloorType : CapFloorType Cap, Floor, or Collar. tenor : Period Tenor of the cap/floor. index : IborIndex The floating rate index. strike : float, optional Strike rate. ``None`` for ATM. forwardStart : Period, optional Forward start period. **kwargs Builder options mapped to ``with*`` methods (e.g. ``nominal``, ``pricingEngine``, ``calendar``, ``dayCount``, ...). Returns ------- CapFloor """ if forwardStart is not None: builder = _ql.MakeCapFloor(capFloorType, tenor, index, strike, forwardStart) else: builder = _ql.MakeCapFloor(capFloorType, tenor, index, strike) _apply_kwargs("MakeCapFloor", _MAKECAPFLOOR_METHODS, builder, kwargs) return builder.capFloor() # --------------------------------------------------------------------------- # MakeOIS # --------------------------------------------------------------------------- _MAKEOIS_METHODS = { "receiveFixed": "receiveFixed", "swapType": "withType", "nominal": "withNominal", "settlementDays": "withSettlementDays", "effectiveDate": "withEffectiveDate", "terminationDate": "withTerminationDate", "rule": "withRule", "fixedLegRule": "withFixedLegRule", "overnightLegRule": "withOvernightLegRule", "paymentFrequency": "withPaymentFrequency", "fixedLegPaymentFrequency": "withFixedLegPaymentFrequency", "overnightLegPaymentFrequency": "withOvernightLegPaymentFrequency", "paymentAdjustment": "withPaymentAdjustment", "paymentLag": "withPaymentLag", "paymentCalendar": "withPaymentCalendar", "calendar": "withCalendar", "fixedLegCalendar": "withFixedLegCalendar", "overnightLegCalendar": "withOvernightLegCalendar", "convention": "withConvention", "fixedLegConvention": "withFixedLegConvention", "overnightLegConvention": "withOvernightLegConvention", "terminationDateConvention": "withTerminationDateConvention", "fixedLegTerminationDateConvention": "withFixedLegTerminationDateConvention", "overnightLegTerminationDateConvention": "withOvernightLegTerminationDateConvention", "endOfMonth": "withEndOfMonth", "fixedLegEndOfMonth": "withFixedLegEndOfMonth", "overnightLegEndOfMonth": "withOvernightLegEndOfMonth", "fixedLegDayCount": "withFixedLegDayCount", "overnightLegSpread": "withOvernightLegSpread", "discountingTermStructure": "withDiscountingTermStructure", "telescopicValueDates": "withTelescopicValueDates", "averagingMethod": "withAveragingMethod", "lookbackDays": "withLookbackDays", "lockoutDays": "withLockoutDays", "observationShift": "withObservationShift", "pricingEngine": "withPricingEngine", } def MakeOIS(swapTenor, overnightIndex, fixedRate=None, fwdStart=None, **kwargs): """Build an OvernightIndexedSwap from keyword arguments. Parameters ---------- swapTenor : Period Tenor of the swap. overnightIndex : OvernightIndex The overnight rate index. fixedRate : float, optional Fixed rate. ``None`` for ATM. fwdStart : Period, optional Forward start period. **kwargs Builder options mapped to ``with*`` methods (e.g. ``nominal``, ``pricingEngine``, ``fixedLegDayCount``, ...). Returns ------- OvernightIndexedSwap """ if fwdStart is not None: builder = _ql.MakeOIS(swapTenor, overnightIndex, fixedRate, fwdStart) else: builder = _ql.MakeOIS(swapTenor, overnightIndex, fixedRate) _apply_kwargs("MakeOIS", _MAKEOIS_METHODS, builder, kwargs) return builder.ois() # --------------------------------------------------------------------------- # MakeVanillaSwap # --------------------------------------------------------------------------- _MAKEVANILLASWAP_METHODS = { "receiveFixed": "receiveFixed", "swapType": "withType", "nominal": "withNominal", "settlementDays": "withSettlementDays", "effectiveDate": "withEffectiveDate", "terminationDate": "withTerminationDate", "rule": "withRule", "paymentConvention": "withPaymentConvention", "fixedLegTenor": "withFixedLegTenor", "fixedLegCalendar": "withFixedLegCalendar", "fixedLegConvention": "withFixedLegConvention", "fixedLegTerminationDateConvention": "withFixedLegTerminationDateConvention", "fixedLegRule": "withFixedLegRule", "fixedLegEndOfMonth": "withFixedLegEndOfMonth", "fixedLegFirstDate": "withFixedLegFirstDate", "fixedLegNextToLastDate": "withFixedLegNextToLastDate", "fixedLegDayCount": "withFixedLegDayCount", "floatingLegTenor": "withFloatingLegTenor", "floatingLegCalendar": "withFloatingLegCalendar", "floatingLegConvention": "withFloatingLegConvention", "floatingLegTerminationDateConvention": "withFloatingLegTerminationDateConvention", "floatingLegRule": "withFloatingLegRule", "floatingLegEndOfMonth": "withFloatingLegEndOfMonth", "floatingLegFirstDate": "withFloatingLegFirstDate", "floatingLegNextToLastDate": "withFloatingLegNextToLastDate", "floatingLegDayCount": "withFloatingLegDayCount", "floatingLegSpread": "withFloatingLegSpread", "discountingTermStructure": "withDiscountingTermStructure", "indexedCoupons": "withIndexedCoupons", "atParCoupons": "withAtParCoupons", "pricingEngine": "withPricingEngine", }
[docs] def MakeVanillaSwap(swapTenor, iborIndex, fixedRate=None, forwardStart=None, **kwargs): """Build a VanillaSwap from keyword arguments. Parameters ---------- swapTenor : Period Tenor of the swap. iborIndex : IborIndex The floating rate index. fixedRate : float, optional Fixed rate. ``None`` for par rate. forwardStart : Period, optional Forward start period. **kwargs Builder options mapped to ``with*`` methods (e.g. ``nominal``, ``pricingEngine``, ``fixedLegDayCount``, ``floatingLegSpread``, ...). Returns ------- VanillaSwap """ if forwardStart is not None: builder = _ql.MakeVanillaSwap(swapTenor, iborIndex, fixedRate, forwardStart) else: builder = _ql.MakeVanillaSwap(swapTenor, iborIndex, fixedRate) _apply_kwargs("MakeVanillaSwap", _MAKEVANILLASWAP_METHODS, builder, kwargs) return builder.swap()
# --------------------------------------------------------------------------- # MakeSwaption # --------------------------------------------------------------------------- _MAKESWAPTION_METHODS = { "nominal": "withNominal", "settlementType": "withSettlementType", "settlementMethod": "withSettlementMethod", "optionConvention": "withOptionConvention", "exerciseDate": "withExerciseDate", "underlyingType": "withUnderlyingType", "indexedCoupons": "withIndexedCoupons", "atParCoupons": "withAtParCoupons", "pricingEngine": "withPricingEngine", }
[docs] def MakeSwaption(swapIndex, optionTenor, strike=None, **kwargs): """Build a Swaption from keyword arguments. Parameters ---------- swapIndex : SwapIndex The swap index. optionTenor : Period or Date Option tenor (Period) or fixing date (Date). strike : float, optional Strike rate. ``None`` for ATM. **kwargs Builder options mapped to ``with*`` methods (e.g. ``nominal``, ``pricingEngine``, ``settlementType``, ...). Returns ------- Swaption """ builder = _ql.MakeSwaption(swapIndex, optionTenor, strike) _apply_kwargs("MakeSwaption", _MAKESWAPTION_METHODS, builder, kwargs) return builder.swaption()
# --------------------------------------------------------------------------- # MakeYoYInflationCapFloor # --------------------------------------------------------------------------- _MAKEYOYINFLATIONCAPFLOOR_METHODS = { "nominal": "withNominal", "effectiveDate": "withEffectiveDate", "paymentDayCounter": "withPaymentDayCounter", "paymentAdjustment": "withPaymentAdjustment", "fixingDays": "withFixingDays", "pricingEngine": "withPricingEngine", "asOptionlet": "asOptionlet", "strike": "withStrike", "atmStrike": "withAtmStrike", "forwardStart": "withForwardStart", }
[docs] def MakeYoYInflationCapFloor(capFloorType, index, length, calendar, observationLag, interpolation, **kwargs): """Build a YoYInflationCapFloor from keyword arguments. Parameters ---------- capFloorType : YoYInflationCapFloorType Cap, Floor, or Collar. index : YoYInflationIndex The YoY inflation index. length : int Length in years. calendar : Calendar Payment calendar. observationLag : Period Observation lag. interpolation : CPI.InterpolationType Interpolation type. **kwargs Builder options mapped to ``with*`` methods (e.g. ``nominal``, ``pricingEngine``, ``strike``, ``paymentDayCounter``, ...). Returns ------- YoYInflationCapFloor """ builder = _ql.MakeYoYInflationCapFloor( capFloorType, index, length, calendar, observationLag, interpolation) _apply_kwargs("MakeYoYInflationCapFloor", _MAKEYOYINFLATIONCAPFLOOR_METHODS, builder, kwargs) return builder.capFloor()
# --------------------------------------------------------------------------- # MakeFdHestonVanillaEngine # --------------------------------------------------------------------------- _MAKEFDHESTONVANILLAENGINE_METHODS = { "tGrid": "withTGrid", "xGrid": "withXGrid", "vGrid": "withVGrid", "dampingSteps": "withDampingSteps", "fdmSchemeDesc": "withFdmSchemeDesc", } def MakeFdHestonVanillaEngine(hestonModel, **kwargs): """Build an FdHestonVanillaEngine from keyword arguments. Parameters ---------- hestonModel The Heston model. **kwargs Builder options: ``tGrid``, ``xGrid``, ``vGrid``, ``dampingSteps``, ``fdmSchemeDesc``. ``cashDividends`` expects a tuple of (dates, amounts). Returns ------- PricingEngine """ cash_divs = kwargs.pop("cashDividends", None) builder = _ql.MakeFdHestonVanillaEngine(hestonModel) _apply_kwargs("MakeFdHestonVanillaEngine", _MAKEFDHESTONVANILLAENGINE_METHODS, builder, kwargs) if cash_divs is not None: dates, amounts = cash_divs builder.withCashDividends(dates, amounts) return builder.engine()