From 619e0312e4d8f4e0954374a4526cbb65bc55fc58 Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Mon, 30 Oct 2023 16:12:51 -0400 Subject: [PATCH 1/6] couple extra nogil annotations --- quantlib/_index.pxd | 2 +- quantlib/_interest_rate.pxd | 2 +- quantlib/_observable.pxd | 2 +- quantlib/indexes/_ibor_index.pxd | 2 +- quantlib/indexes/_interest_rate_index.pxd | 3 +-- quantlib/termstructures/_helpers.pxd | 2 +- quantlib/termstructures/yields/_bond_helpers.pxd | 4 +--- quantlib/termstructures/yields/_rate_helpers.pxd | 2 +- quantlib/types.pxd | 2 +- 9 files changed, 9 insertions(+), 12 deletions(-) diff --git a/quantlib/_index.pxd b/quantlib/_index.pxd index 0c4f6a76e..e4e1b161a 100644 --- a/quantlib/_index.pxd +++ b/quantlib/_index.pxd @@ -19,7 +19,7 @@ from quantlib.time._calendar cimport Calendar from quantlib.time._date cimport Date -cdef extern from 'ql/index.hpp' namespace 'QuantLib': +cdef extern from 'ql/index.hpp' namespace 'QuantLib' nogil: cdef cppclass Index(Observable): string name() diff --git a/quantlib/_interest_rate.pxd b/quantlib/_interest_rate.pxd index 95e6e278c..aff1c187e 100644 --- a/quantlib/_interest_rate.pxd +++ b/quantlib/_interest_rate.pxd @@ -14,7 +14,7 @@ from quantlib.time._daycounter cimport DayCounter from quantlib.time._period cimport Frequency from quantlib.compounding cimport Compounding -cdef extern from 'ql/interestrate.hpp' namespace 'QuantLib': +cdef extern from 'ql/interestrate.hpp' namespace 'QuantLib' nogil: cppclass InterestRate: InterestRate() diff --git a/quantlib/_observable.pxd b/quantlib/_observable.pxd index f516ac3da..b1481fb18 100644 --- a/quantlib/_observable.pxd +++ b/quantlib/_observable.pxd @@ -1,5 +1,5 @@ -include 'types.pxi' from .handle cimport shared_ptr +from .types cimport Size cdef extern from 'ql/patterns/observable.hpp' namespace 'QuantLib' nogil: cdef cppclass Observable: diff --git a/quantlib/indexes/_ibor_index.pxd b/quantlib/indexes/_ibor_index.pxd index a88e84935..805ce511b 100644 --- a/quantlib/indexes/_ibor_index.pxd +++ b/quantlib/indexes/_ibor_index.pxd @@ -22,7 +22,7 @@ cimport quantlib.termstructures.yields._flat_forward as _ff from quantlib.indexes._interest_rate_index cimport InterestRateIndex -cdef extern from 'ql/indexes/iborindex.hpp' namespace 'QuantLib': +cdef extern from 'ql/indexes/iborindex.hpp' namespace 'QuantLib' nogil: # base class for Inter-Bank-Offered-Rate indexes (e.g. %Libor, etc.) cdef cppclass IborIndex(InterestRateIndex): diff --git a/quantlib/indexes/_interest_rate_index.pxd b/quantlib/indexes/_interest_rate_index.pxd index 9d62b68e4..40b77b6b5 100644 --- a/quantlib/indexes/_interest_rate_index.pxd +++ b/quantlib/indexes/_interest_rate_index.pxd @@ -19,10 +19,9 @@ from quantlib.time._daycounter cimport DayCounter from quantlib.currency._currency cimport Currency -cdef extern from 'ql/indexes/interestrateindex.hpp' namespace 'QuantLib': +cdef extern from 'ql/indexes/interestrateindex.hpp' namespace 'QuantLib' nogil: cdef cppclass InterestRateIndex(Index): - InterestRateIndex() InterestRateIndex(string& familyName, Period& tenor, Natural settlementDays, diff --git a/quantlib/termstructures/_helpers.pxd b/quantlib/termstructures/_helpers.pxd index 9b498f632..0acbed1b9 100644 --- a/quantlib/termstructures/_helpers.pxd +++ b/quantlib/termstructures/_helpers.pxd @@ -13,7 +13,7 @@ from quantlib.handle cimport Handle from quantlib._quote cimport Quote from quantlib.time._date cimport Date -cdef extern from 'ql/termstructures/bootstraphelper.hpp' namespace 'QuantLib': +cdef extern from 'ql/termstructures/bootstraphelper.hpp' namespace 'QuantLib' nogil: cdef cppclass BootstrapHelper[T]: BootstrapHelper(Handle[Quote]& quote) BootstrapHelper(Real quote) diff --git a/quantlib/termstructures/yields/_bond_helpers.pxd b/quantlib/termstructures/yields/_bond_helpers.pxd index 16cc29e92..d9840ee57 100644 --- a/quantlib/termstructures/yields/_bond_helpers.pxd +++ b/quantlib/termstructures/yields/_bond_helpers.pxd @@ -16,11 +16,9 @@ from ._flat_forward cimport YieldTermStructure from ._rate_helpers cimport RateHelper -cdef extern from 'ql/termstructures/yield/bondhelpers.hpp' namespace 'QuantLib': +cdef extern from 'ql/termstructures/yield/bondhelpers.hpp' namespace 'QuantLib' nogil: cdef cppclass BondHelper(RateHelper): - # this is added because of Cython. This empty constructor does not exist - # and should never be used BondHelper( Handle[Quote]& cleanPrice, shared_ptr[Bond]& bond, diff --git a/quantlib/termstructures/yields/_rate_helpers.pxd b/quantlib/termstructures/yields/_rate_helpers.pxd index 94a2cc426..d71585559 100644 --- a/quantlib/termstructures/yields/_rate_helpers.pxd +++ b/quantlib/termstructures/yields/_rate_helpers.pxd @@ -28,7 +28,7 @@ from quantlib.instruments.futures cimport FuturesType from ..helpers cimport Pillar -cdef extern from 'ql/termstructures/yield/ratehelpers.hpp' namespace 'QuantLib': +cdef extern from 'ql/termstructures/yield/ratehelpers.hpp' namespace 'QuantLib' nogil: ctypedef BootstrapHelper[YieldTermStructure] RateHelper ctypedef RelativeDateBootstrapHelper[YieldTermStructure] RelativeDateRateHelper diff --git a/quantlib/types.pxd b/quantlib/types.pxd index 9a008d587..0d0e58015 100644 --- a/quantlib/types.pxd +++ b/quantlib/types.pxd @@ -7,7 +7,7 @@ # FOR A PARTICULAR PURPOSE. See the license for more details. # -cdef extern from 'ql/types.hpp' namespace 'QuantLib': +cdef extern from 'ql/types.hpp' namespace 'QuantLib' nogil: ctypedef int Integer ctypedef long BigInteger ctypedef unsigned int Natural From 60b931852c7b1d2885ad9618e0d6fd4a0a23e040 Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Tue, 25 Jun 2024 16:00:20 -0400 Subject: [PATCH 2/6] extend OvernightIndexedCoupon with parameters --- .../cashflows/_overnight_indexed_coupon.pxd | 9 ++++-- .../cashflows/overnight_indexed_coupon.pyx | 26 +++++++++++++--- quantlib/instruments/_make_ois.pxd | 3 ++ .../instruments/_overnightindexedswap.pxd | 28 ++++++++++++----- quantlib/instruments/make_ois.pyx | 12 +++++++ quantlib/instruments/overnightindexedswap.pyx | 31 ++++++++++++------- 6 files changed, 83 insertions(+), 26 deletions(-) diff --git a/quantlib/cashflows/_overnight_indexed_coupon.pxd b/quantlib/cashflows/_overnight_indexed_coupon.pxd index 3c7382062..dc9a5c14b 100644 --- a/quantlib/cashflows/_overnight_indexed_coupon.pxd +++ b/quantlib/cashflows/_overnight_indexed_coupon.pxd @@ -1,4 +1,4 @@ -from quantlib.types cimport Rate, Real, Spread, Time +from quantlib.types cimport Natural, Rate, Real, Spread, Time from libcpp cimport bool from libcpp.vector cimport vector @@ -22,10 +22,15 @@ cdef extern from 'ql/cashflows/overnightindexedcoupon.hpp' namespace 'QuantLib': const Date& refPeriodEnd, #= Date(), const DayCounter& dayCounter, #= DayCounter(), bool telescopicValueDates, #=False, - RateAveraging averagingMethod) # = RateAveraging::Compound + RateAveraging averagingMethod, # = RateAveraging::Compound + Natural lookback_days, + Natural lockout_days, + bool apply_observation_shift) vector[Date]& fixingDates() vector[Time]& dt() vector[Rate]& indexFixings() except + vector[Date]& valueDates() RateAveraging averagingMethod() + Natural lockoutDays() + bool applyObservationShift() diff --git a/quantlib/cashflows/overnight_indexed_coupon.pyx b/quantlib/cashflows/overnight_indexed_coupon.pyx index 833205db6..858f06c7c 100644 --- a/quantlib/cashflows/overnight_indexed_coupon.pyx +++ b/quantlib/cashflows/overnight_indexed_coupon.pyx @@ -1,4 +1,4 @@ -from quantlib.types cimport Real, Spread +from quantlib.types cimport Natural, Real, Spread from libcpp cimport bool from libcpp.vector cimport vector @@ -8,6 +8,7 @@ from quantlib.time.date cimport Date, date_from_qldate from quantlib.time._date cimport Date as QlDate from quantlib.time.daycounter cimport DayCounter from quantlib.indexes.ibor_index cimport OvernightIndex +from quantlib.utilities.null cimport Null cimport quantlib.indexes._ibor_index as _ii cimport quantlib._cashflow as _cf from .rateaveraging cimport RateAveraging @@ -20,14 +21,18 @@ cdef class OvernightIndexedCoupon(FloatingRateCoupon): OvernightIndex index not None, Real gearing=1., Spread spread=0., Date ref_period_start=Date(), Date ref_period_end=Date(), DayCounter day_counter=DayCounter(), bool telescopic_values= False, - RateAveraging averaging_method=RateAveraging.Compound): + RateAveraging averaging_method=RateAveraging.Compound, + Natural lookback_days=Null[Natural](), + Natural lockout_days=0, + bool apply_observation_shift=False): self._thisptr = make_shared[_oic.OvernightIndexedCoupon]( payment_date._thisptr, nominal, start_date._thisptr, end_date._thisptr, static_pointer_cast[_ii.OvernightIndex](index._thisptr), gearing, spread, ref_period_start._thisptr, ref_period_end._thisptr, - deref(day_counter._thisptr), telescopic_values, averaging_method + deref(day_counter._thisptr), telescopic_values, averaging_method, + lookback_days, lockout_days, apply_observation_shift ) def fixing_dates(self): @@ -61,8 +66,19 @@ cdef class OvernightIndexedCoupon(FloatingRateCoupon): l.append(date) preinc(it) return l - - + + @property + def lockout_days(self): + return (<_oic.OvernightIndexedCoupon*>self._thisptr.get()).lockoutDays() + + @property + def averaging_method(self): + return (<_oic.OvernightIndexedCoupon*>self._thisptr.get()).averagingMethod() + + @property + def apply_observation_shift(self): + return (<_oic.OvernightIndexedCoupon*>self._thisptr.get()).applyObservationShift() + cdef class OvernightLeg(Leg): def __iter__(self): diff --git a/quantlib/instruments/_make_ois.pxd b/quantlib/instruments/_make_ois.pxd index d1ebc5bf7..cc979a5bc 100644 --- a/quantlib/instruments/_make_ois.pxd +++ b/quantlib/instruments/_make_ois.pxd @@ -49,5 +49,8 @@ cdef extern from 'ql/instruments/makeois.hpp' namespace 'QuantLib': MakeOIS &withTelescopicValueDates(bool telescopicValueDates) MakeOIS& withAveragingMethod(RateAveraging averagingMethod) + MakeOIS& withLookbackDays(Natural lookbackDays) + MakeOIS& withLockoutDays(Natural lockoutDays) + MakeOIS& withObservationShift(bool ObservationShift) MakeOIS& withPricingEngine(shared_ptr[PricingEngine]& engine) diff --git a/quantlib/instruments/_overnightindexedswap.pxd b/quantlib/instruments/_overnightindexedswap.pxd index ca32b92cd..9f6be1ffa 100644 --- a/quantlib/instruments/_overnightindexedswap.pxd +++ b/quantlib/instruments/_overnightindexedswap.pxd @@ -1,5 +1,5 @@ -from quantlib.types cimport Natural, Rate, Real, Spread +from quantlib.types cimport Integer, Natural, Rate, Real, Spread from quantlib.cashflows.rateaveraging cimport RateAveraging from libcpp cimport bool from libcpp.vector cimport vector @@ -18,35 +18,47 @@ cdef extern from 'ql/instruments/overnightindexedswap.hpp' namespace 'QuantLib': cdef cppclass OvernightIndexedSwap(FixedVsFloatingSwap): OvernightIndexedSwap(Type type, Real nominal, - const Schedule& schedule, + const Schedule& fixedSchedule, Rate fixedRate, DayCounter fixedDC, + const Schedule overnightSchedule, shared_ptr[OvernightIndex] overnightIndex, Spread spread, # = 0.0, - Natural paymentLag, # = 0, + Integer paymentLag, # = 0, BusinessDayConvention paymentAdjustment, # = Following, const Calendar& paymentCalendar, # = Calendar(), bool telescopicValueDates, # = false, - RateAveraging averagingMethod) # = RateAveraging::Compound); + RateAveraging averagingMethod, # = RateAveraging::Compound); + Natural lookbackDays, # = Null(), + Natural lockoutDays, # = 0, + bool applyObservationShift) # = False OvernightIndexedSwap(Type type, - vector[Real] nominals, - const Schedule& schedule, + vector[Real] fixed_nominals, + const Schedule& fixedSchedule, Rate fixedRate, DayCounter fixedDC, + vector[Real] overnight_nominals, + const Schedule overnightSchedule, shared_ptr[OvernightIndex] overnightIndex, Spread spread, # = 0.0, - Natural paymentLag, # = 0, + Integer paymentLag, # = 0, BusinessDayConvention paymentAdjustment, # = Following, const Calendar& paymentCalendar, # = Calendar(), bool telescopicValueDates, # = false, - RateAveraging averagingMethod) # = RateAveraging::Compound); + RateAveraging averagingMethod, # = RateAveraging::Compound); + Natural lookbackDays, # = Null(), + Natural lockoutDays, # = 0, + bool applyObservationShift) # = False Frequency paymentFrequency() const shared_ptr[OvernightIndex]& overnightIndex() const Leg& overnightLeg() const RateAveraging averagingMethod() const + Natural lookbackDays() const + Natural lockoutDays() const + bool applyObservationShift() const Real overnightLegBPS() const Real overnightLegNPV() const diff --git a/quantlib/instruments/make_ois.pyx b/quantlib/instruments/make_ois.pyx index 1c3133bed..9fbc461fe 100644 --- a/quantlib/instruments/make_ois.pyx +++ b/quantlib/instruments/make_ois.pyx @@ -110,6 +110,18 @@ cdef class MakeOIS: self._thisptr.withAveragingMethod(averagingMethod) return self + def with_lookback_days(self, Natural lookback_days): + self._thisptr.withLookbackDays(lookback_days) + return self + + def with_lockout_days(self, Natural lockout_days): + self._thisptr.withLockoutDays(lockout_days) + return self + + def with_apply_observation_shift(self, bool observation_shift): + self._thisptr.withObservationShift(observation_shift) + return self + def with_pricing_engine(self, PricingEngine engine): self._thisptr.withPricingEngine(engine._thisptr) return self diff --git a/quantlib/instruments/overnightindexedswap.pyx b/quantlib/instruments/overnightindexedswap.pyx index 861e72b53..3a7c18e4b 100644 --- a/quantlib/instruments/overnightindexedswap.pyx +++ b/quantlib/instruments/overnightindexedswap.pyx @@ -1,5 +1,5 @@ """Overnight index swap paying compounded overnight vs. fixed""" -from quantlib.types cimport Real +from quantlib.types cimport Real, Integer, Natural from cython.operator cimport dereference as deref from libcpp cimport bool from libcpp.vector cimport vector @@ -13,6 +13,7 @@ from quantlib.time.calendar cimport Calendar from quantlib.time.daycounter cimport DayCounter from quantlib.time.schedule cimport Schedule from quantlib.handle cimport make_shared, static_pointer_cast +from quantlib.utilities.null cimport Null from .swap cimport Type from . cimport _overnightindexedswap as _ois from quantlib._instrument cimport Instrument @@ -25,12 +26,16 @@ cdef inline _ois.OvernightIndexedSwap* get_OIS(OvernightIndexedSwap self): cdef class OvernightIndexedSwap(FixedVsFloatingSwap): """Overnight indexed swap: fix vs compounded overnight rate""" - def __init__(self, Type swap_type, nominal, Schedule schedule, - Rate fixed_rate, DayCounter fixed_dc, OvernightIndex overnight_index, - Spread spread=0.0, Natural payment_lag=0, + def __init__(self, Type swap_type, nominal, Schedule fixed_schedule, + Rate fixed_rate, DayCounter fixed_dc, Schedule overnight_schedule, + OvernightIndex overnight_index, + Spread spread=0.0, Integer payment_lag=0, BusinessDayConvention payment_adjustment=Following, Calendar payment_calendar=Calendar(), bool telescopic_value_dates=False, - RateAveraging averaging_method=RateAveraging.Compound): + RateAveraging averaging_method=RateAveraging.Compound, + Natural lookback_days=Null[Natural](), + Natural lockout_days=0, + bool apply_observation_shift=False): cdef vector[double] nominals cdef double n @@ -38,10 +43,12 @@ cdef class OvernightIndexedSwap(FixedVsFloatingSwap): if isinstance(nominal, float): self._thisptr = static_pointer_cast[Instrument]( make_shared[_ois.OvernightIndexedSwap]( - swap_type, nominal, schedule._thisptr, fixed_rate, - deref(fixed_dc._thisptr), static_pointer_cast[_ii.OvernightIndex](overnight_index._thisptr), + swap_type, nominal, fixed_schedule._thisptr, fixed_rate, + deref(fixed_dc._thisptr), overnight_schedule._thisptr, + static_pointer_cast[_ii.OvernightIndex](overnight_index._thisptr), spread, payment_lag, payment_adjustment, payment_calendar._thisptr, - telescopic_value_dates, averaging_method + telescopic_value_dates, averaging_method, lookback_days, lockout_days, + apply_observation_shift ) ) elif isinstance(nominal, list): @@ -49,10 +56,12 @@ cdef class OvernightIndexedSwap(FixedVsFloatingSwap): nominals.push_back(n) self._thisptr = static_pointer_cast[Instrument]( make_shared[_ois.OvernightIndexedSwap]( - swap_type, nominals, schedule._thisptr, fixed_rate, - deref(fixed_dc._thisptr), static_pointer_cast[_ii.OvernightIndex](overnight_index._thisptr), + swap_type, nominals, fixed_schedule._thisptr, fixed_rate, + deref(fixed_dc._thisptr), nominals, overnight_schedule._thisptr, + static_pointer_cast[_ii.OvernightIndex](overnight_index._thisptr), spread, payment_lag, payment_adjustment, payment_calendar._thisptr, - telescopic_value_dates, averaging_method + telescopic_value_dates, averaging_method, lookback_days, lockout_days, + apply_observation_shift ) ) From 27974e01746cbe41deb99dd174ad7df9f1999463 Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Wed, 21 Aug 2024 14:44:30 -0400 Subject: [PATCH 3/6] extend OISRateHelper constructor --- .../yields/_ois_rate_helper.pxd | 11 +++++-- .../termstructures/yields/ois_rate_helper.pyx | 32 +++++++++++++++---- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/quantlib/termstructures/yields/_ois_rate_helper.pxd b/quantlib/termstructures/yields/_ois_rate_helper.pxd index 9fd7c29c9..43e8a3006 100644 --- a/quantlib/termstructures/yields/_ois_rate_helper.pxd +++ b/quantlib/termstructures/yields/_ois_rate_helper.pxd @@ -1,9 +1,10 @@ -from quantlib.types cimport Natural, Spread +from quantlib.types cimport Integer, Natural, Spread from libcpp cimport bool from quantlib._quote cimport Quote from quantlib.cashflows.rateaveraging cimport RateAveraging +from quantlib.cashflows._coupon_pricer cimport FloatingRateCouponPricer from quantlib.handle cimport shared_ptr, Handle, optional from quantlib.time._date cimport Date from quantlib.time._period cimport Period, Frequency @@ -24,7 +25,7 @@ cdef extern from 'ql/termstructures/yield/oisratehelper.hpp' namespace 'QuantLib # exogenous discounting curve Handle[YieldTermStructure]& discountingCurve, # = Handle() bool telescopicValueDates, # False) - Natural paymentLag, # = 0 + Integer paymentLag, # = 0 BusinessDayConvention paymentConvention, # = Following Frequency paymentFrequency, # = Annual Calendar& paymentCalendar, # = Calendar() @@ -34,6 +35,12 @@ cdef extern from 'ql/termstructures/yield/oisratehelper.hpp' namespace 'QuantLib Date customPillarDate, # = Date(), RateAveraging averagingMethod,# = RateAveraging::Compound, optional[bool] endOfMonth, # = boost::none + optional[Frequency] fixedPaymentFrequency, # = ext::nullopt, + Calendar fixedCalendar, # = Calendar(), + Natural lookbackDays, # = Null(), + Natural lockoutDays, # = 0, + bool applyObservationShift,# = false, + #shared_ptr[FloatingRateCouponPricer] pricer ) except + # = 0.0 cdef cppclass DatedOISRateHelper(RateHelper): diff --git a/quantlib/termstructures/yields/ois_rate_helper.pyx b/quantlib/termstructures/yields/ois_rate_helper.pyx index 066ac43ba..6ad30c468 100644 --- a/quantlib/termstructures/yields/ois_rate_helper.pyx +++ b/quantlib/termstructures/yields/ois_rate_helper.pyx @@ -1,9 +1,10 @@ -from quantlib.types cimport Natural, Spread +from quantlib.types cimport Integer, Natural, Spread from libcpp cimport bool from cython.operator cimport dereference as deref from quantlib.cashflows.rateaveraging cimport RateAveraging +from quantlib.cashflows.coupon_pricer cimport FloatingRateCouponPricer from quantlib.termstructures.helpers cimport Pillar from quantlib.handle cimport shared_ptr, static_pointer_cast, Handle, optional from quantlib.quote cimport Quote @@ -12,6 +13,7 @@ from quantlib.termstructures.yields.rate_helpers cimport RelativeDateRateHelper, from quantlib.indexes.ibor_index cimport OvernightIndex from quantlib.termstructures.yield_term_structure cimport HandleYieldTermStructure from quantlib.time.calendar cimport Calendar +from quantlib.utilities.null cimport Null from . cimport _ois_rate_helper as _orh from . cimport _rate_helpers as _rh @@ -19,7 +21,6 @@ cimport quantlib._quote as _qt cimport quantlib.indexes._ibor_index as _ib from quantlib.time.businessdayconvention cimport BusinessDayConvention, Following from quantlib.time._period cimport Frequency, Days -cimport quantlib.termstructures._yield_term_structure as _yts cdef class OISRateHelper(RelativeDateRateHelper): @@ -29,9 +30,9 @@ cdef class OISRateHelper(RelativeDateRateHelper): Quote fixed_rate not None, OvernightIndex overnight_index not None, # exogenous discounting curve - HandleYieldTermStructure ts not None=HandleYieldTermStructure(), + HandleYieldTermStructure discounting_curve not None=HandleYieldTermStructure(), bool telescopic_value_dates = False, - Natural payment_lag = 0, + Integer payment_lag=0, BusinessDayConvention payment_convention = Following, Frequency payment_frequency = Frequency.Annual, Calendar payment_calendar = Calendar(), @@ -41,17 +42,28 @@ cdef class OISRateHelper(RelativeDateRateHelper): Date custom_pillar_date=Date(), RateAveraging averaging_method=RateAveraging.Compound, end_of_month=None, + fixed_payment_frequency=None, + Calendar fixed_calendar=Calendar(), + Natural lookback_days=Null[Natural](), + Natural lockout_days=0, + bool apply_observation_shift=False, + #FloatingRateCouponPricer pricer=FloatingRateCouponPricer() ): - cdef optional[bool] end_of_month_opt + cdef: + optional[bool] end_of_month_opt + optional[Frequency] fixed_payment_frequency_opt if end_of_month is not None: end_of_month_opt = end_of_month - self._thisptr = shared_ptr[_rh.RateHelper]( + if fixed_payment_frequency is not None: + fixed_payment_frequency_opt = fixed_payment_frequency + + self._thisptr.reset( new _orh.OISRateHelper( settlement_days, deref(tenor._thisptr), fixed_rate.handle(), static_pointer_cast[_ib.OvernightIndex](overnight_index._thisptr), - ts.handle, + discounting_curve.handle, telescopic_value_dates, payment_lag, <_rh.BusinessDayConvention> payment_convention, @@ -63,6 +75,12 @@ cdef class OISRateHelper(RelativeDateRateHelper): custom_pillar_date._thisptr, averaging_method, end_of_month_opt, + fixed_payment_frequency_opt, + fixed_calendar._thisptr, + lookback_days, + lockout_days, + apply_observation_shift, + #pricer._thisptr ) ) From 19839a307e2da1d4eaada5afd35309dc835ac0bd Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Mon, 25 Nov 2024 14:50:13 -0500 Subject: [PATCH 4/6] add OvernightIndexedCoupon pricers --- quantlib/cashflows/_coupon_pricer.pxd | 4 ++-- .../_overnight_indexed_coupon_pricer.pxd | 13 +++++++++++ quantlib/cashflows/coupon_pricer.pyx | 23 ++++++++----------- .../overnight_indexed_coupon_pricer.pxd | 8 +++++++ .../overnight_indexed_coupon_pricer.pyx | 16 +++++++++++++ 5 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 quantlib/cashflows/_overnight_indexed_coupon_pricer.pxd create mode 100644 quantlib/cashflows/overnight_indexed_coupon_pricer.pxd create mode 100644 quantlib/cashflows/overnight_indexed_coupon_pricer.pyx diff --git a/quantlib/cashflows/_coupon_pricer.pxd b/quantlib/cashflows/_coupon_pricer.pxd index 108df9544..9a0106b6a 100644 --- a/quantlib/cashflows/_coupon_pricer.pxd +++ b/quantlib/cashflows/_coupon_pricer.pxd @@ -1,4 +1,4 @@ -include '../types.pxi' +from quantlib.types cimport Rate, Real from quantlib.handle cimport shared_ptr, Handle from quantlib.termstructures.volatility.optionlet._optionlet_volatility_structure cimport OptionletVolatilityStructure @@ -7,7 +7,7 @@ from quantlib._cashflow cimport Leg from quantlib.cashflows._floating_rate_coupon cimport FloatingRateCoupon from quantlib._quote cimport Quote -cdef extern from 'ql/cashflows/couponpricer.hpp' namespace 'QuantLib': +cdef extern from 'ql/cashflows/couponpricer.hpp' namespace 'QuantLib' nogil: cdef cppclass FloatingRateCouponPricer: FloatingRateCouponPricer() except + diff --git a/quantlib/cashflows/_overnight_indexed_coupon_pricer.pxd b/quantlib/cashflows/_overnight_indexed_coupon_pricer.pxd new file mode 100644 index 000000000..b79c368dc --- /dev/null +++ b/quantlib/cashflows/_overnight_indexed_coupon_pricer.pxd @@ -0,0 +1,13 @@ +from quantlib.types cimport Rate, Real +from libcpp cimport bool +from ._coupon_pricer cimport FloatingRateCouponPricer + +cdef extern from 'ql/cashflows/overnightindexedcouponpricer.hpp' namespace 'QuantLib' nogil: + cdef cppclass CompoundingOvernightIndexedCouponPricer(FloatingRateCouponPricer): + pass + cdef cppclass ArithmeticAveragedOvernightIndexedCouponPricer(FloatingRateCouponPricer): + ArithmeticAveragedOvernightIndexedCouponPricer( + Real meanReversion, # = 0.03 + Real volatility, # = 0.00 No convexity adjustment by default + bool byApprox # = false, True to use Katsumi Takada approximation + ) diff --git a/quantlib/cashflows/coupon_pricer.pyx b/quantlib/cashflows/coupon_pricer.pyx index cefeb626c..4c456de9c 100644 --- a/quantlib/cashflows/coupon_pricer.pyx +++ b/quantlib/cashflows/coupon_pricer.pyx @@ -1,5 +1,4 @@ -include '../types.pxi' - +from quantlib.types cimport Rate from cython.operator cimport dereference as deref from quantlib.cashflow cimport Leg from quantlib.termstructures.volatility.optionlet.optionlet_volatility_structure cimport OptionletVolatilityStructure @@ -15,14 +14,18 @@ from quantlib.time.daycounter cimport DayCounter from quantlib.quote cimport Quote from quantlib.quotes.simplequote cimport SimpleQuote from .coupon_pricer cimport FloatingRateCouponPricer +from .floating_rate_coupon cimport FloatingRateCoupon +from . cimport _floating_rate_coupon as _frc cimport quantlib._cashflow as _cf cdef class FloatingRateCouponPricer: - def __init__(self): - raise ValueError( - 'CouponPricer cannot be directly instantiated!' - ) + def __cinit__(self): + if type(self) in (FloatingRateCouponPricer, IborCouponPricer): + raise ValueError(f"'{type(self).__name__}' cannot be directly instantiated!") + + def initialize(self, FloatingRateCoupon coupon not None): + self._thisptr.get().initialize(deref(<_frc.FloatingRateCoupon*>coupon._thisptr.get())) def swaplet_price(self): return self._thisptr.get().swapletPrice() @@ -43,14 +46,6 @@ cdef class FloatingRateCouponPricer: return self._thisptr.get().floorletRate(effective_floor) -cdef class IborCouponPricer(FloatingRateCouponPricer): - - def __init__(self): - raise ValueError( - 'IborCouponPricer cannot be directly instantiated!' - ) - - cpdef enum TimingAdjustment: Black76 = _cp.Black76 BivariateLognormal = _cp.BivariateLognormal diff --git a/quantlib/cashflows/overnight_indexed_coupon_pricer.pxd b/quantlib/cashflows/overnight_indexed_coupon_pricer.pxd new file mode 100644 index 000000000..42e14a891 --- /dev/null +++ b/quantlib/cashflows/overnight_indexed_coupon_pricer.pxd @@ -0,0 +1,8 @@ +from .coupon_pricer cimport FloatingRateCouponPricer + +cdef class CompoundingOvernightIndexedCouponPricer(FloatingRateCouponPricer): + pass + + +cdef class ArithmeticAveragedOvernightIndexedCouponPricer(FloatingRateCouponPricer): + pass diff --git a/quantlib/cashflows/overnight_indexed_coupon_pricer.pyx b/quantlib/cashflows/overnight_indexed_coupon_pricer.pyx new file mode 100644 index 000000000..e359b9996 --- /dev/null +++ b/quantlib/cashflows/overnight_indexed_coupon_pricer.pyx @@ -0,0 +1,16 @@ +from quantlib.types cimport Real +from libcpp cimport bool +from . cimport _overnight_indexed_coupon_pricer as _oicp + +cdef class CompoundingOvernightIndexedCouponPricer(FloatingRateCouponPricer): + def __init__(self): + self._thisptr.reset(new _oicp.CompoundingOvernightIndexedCouponPricer()) + +cdef class ArithmeticAveragedOvernightIndexedCouponPricer(FloatingRateCouponPricer): + def __init__(self, Real mean_reversion = 0.03, Real volatility=0.0, bool by_approx=False): + """ pricer for arithmetically averaged overnight indexed coupons + + Reference: Katsumi Takada 2011, Valuation of Arithmetically Average of + Fed Funds Rates and Construction of the US Dollar Swap Yield Curve""" + + self._thisptr.reset(new _oicp.ArithmeticAveragedOvernightIndexedCouponPricer(mean_reversion, volatility, by_approx)) From 347656a60723f8336438360715fb4d212fbec4d1 Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Mon, 19 May 2025 13:17:17 -0400 Subject: [PATCH 5/6] disambiguate constructor --- .../volatility/equityfx/_local_vol_surface.pxd | 6 ------ .../volatility/equityfx/_local_vol_term_structure.pxd | 4 ++-- .../volatility/equityfx/local_vol_surface.pyx | 2 +- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/quantlib/termstructures/volatility/equityfx/_local_vol_surface.pxd b/quantlib/termstructures/volatility/equityfx/_local_vol_surface.pxd index 6e803105b..fe720a76b 100644 --- a/quantlib/termstructures/volatility/equityfx/_local_vol_surface.pxd +++ b/quantlib/termstructures/volatility/equityfx/_local_vol_surface.pxd @@ -25,9 +25,3 @@ cdef extern from 'ql/termstructures/volatility/equityfx/localvolsurface.hpp' nam Handle[YieldTermStructure] riskFreeTS, Handle[YieldTermStructure] dividendTS, Real underlying) - Volatility localVol(const Date& d, - Real underlyingLevel, - bool extrapolate) const # = false - Volatility localVol_ "localVol" (Time t, - Real underlyingLevel, - bool extrapolate) const # = false diff --git a/quantlib/termstructures/volatility/equityfx/_local_vol_term_structure.pxd b/quantlib/termstructures/volatility/equityfx/_local_vol_term_structure.pxd index b92518d71..f7163441c 100644 --- a/quantlib/termstructures/volatility/equityfx/_local_vol_term_structure.pxd +++ b/quantlib/termstructures/volatility/equityfx/_local_vol_term_structure.pxd @@ -32,7 +32,7 @@ cdef extern from 'ql/termstructures/volatility/equityfx/localvoltermstructure.hp Volatility localVol(const Date& d, Real underlyingLevel, - bool extrapolate = false) const + bool extrapolate) const # = false) const Volatility localVol(Time t, Real underlyingLevel, - bool extrapolate = false) const + bool extrapolate) # = false) const diff --git a/quantlib/termstructures/volatility/equityfx/local_vol_surface.pyx b/quantlib/termstructures/volatility/equityfx/local_vol_surface.pyx index a76ba54b0..df91f643d 100644 --- a/quantlib/termstructures/volatility/equityfx/local_vol_surface.pyx +++ b/quantlib/termstructures/volatility/equityfx/local_vol_surface.pyx @@ -36,7 +36,7 @@ cdef class LocalVolSurface(LocalVolTermStructure): def localVol(self, d, Real underlying_level, bool extrapolate=False): cdef _lvs.LocalVolSurface* surf = <_lvs.LocalVolSurface*>self._thisptr.get() if isinstance(d, float): - return surf.localVol_(