diff --git a/quantlib/cashflows/_cashflows.pxd b/quantlib/cashflows/_cashflows.pxd index b0173176b..d521f4971 100644 --- a/quantlib/cashflows/_cashflows.pxd +++ b/quantlib/cashflows/_cashflows.pxd @@ -1,11 +1,12 @@ from libcpp cimport bool from libcpp.pair cimport pair +from quantlib.ext cimport optional from quantlib.time._date cimport Date from quantlib.types cimport Rate, Real from quantlib.termstructures._yield_term_structure cimport YieldTermStructure from .._cashflow cimport Leg -cdef extern from 'ql/cashflows/cashflows.hpp' namespace 'QuantLib': +cdef extern from 'ql/cashflows/cashflows.hpp' namespace 'QuantLib' nogil: cdef cppclass CashFlows: @staticmethod Date startDate(const Leg& leg) @@ -15,26 +16,26 @@ cdef extern from 'ql/cashflows/cashflows.hpp' namespace 'QuantLib': @staticmethod bool isExpired(const Leg& leg, - bool includeSettlementDateFlows, - Date settlementDate = Date()) + optional[bool] includeSettlementDateFlows, # = nullopt + Date settlementDate) # = Date() @staticmethod Date previousCashFlowDate(const Leg& leg, - bool includeSettlementDateFlows, + optional[bool] includeSettlementDateFlows, # = nullopt Date settlementDate)# = Date()) @staticmethod Date nextCashFlowDate(const Leg& leg, - bool includeSettlementDateFlows, + optional[bool] includeSettlementDateFlows, # = nullopt Date settlementDate)# = Date()) @staticmethod Real previousCashFlowAmount(const Leg& leg, - bool includeSettlementDateFlows, - Date settlementDate)# = Date()) + optional[bool] includeSettlementDateFlows, # = nullopt + Date settlementDate)# = Date()) @staticmethod Real nextCashFlowAmount(const Leg& leg, - bool includeSettlementDateFlows, + optional[bool] includeSettlementDateFlows, # = nullopt Date settlementDate)# = Date()) # static Rate # previousCouponRate(const Leg& leg, @@ -49,14 +50,14 @@ cdef extern from 'ql/cashflows/cashflows.hpp' namespace 'QuantLib': # nominal(const Leg& leg, # bool includeSettlementDateFlows, # Date settlDate = Date()); - # static Date - # accrualStartDate(const Leg& leg, - # bool includeSettlementDateFlows, - # Date settlDate = Date()); - # static Date - # accrualEndDate(const Leg& leg, - # bool includeSettlementDateFlows, - # Date settlementDate = Date()); + @staticmethod + Date accrualStartDate(const Leg& leg, + optional[bool] includeSettlementDateFlows, # = nullopt + Date settlDate) # = Date() + @staticmethod + Date accrualEndDate(const Leg& leg, + optional[bool] includeSettlementDateFlows, # = nullopt + Date settlementDate) # = Date() # static Date # referencePeriodStart(const Leg& leg, # bool includeSettlementDateFlows, @@ -69,39 +70,39 @@ cdef extern from 'ql/cashflows/cashflows.hpp' namespace 'QuantLib': # accrualPeriod(const Leg& leg, # bool includeSettlementDateFlows, # Date settlementDate = Date()); - # static Date::serial_type - # accrualDays(const Leg& leg, - # bool includeSettlementDateFlows, - # Date settlementDate = Date()); + @staticmethod + Date.serial_type accrualDays(const Leg& leg, + optional[bool] includeSettlementDateFlows, # = nullopt + Date settlementDate) # = Date() # static Time # accruedPeriod(const Leg& leg, # bool includeSettlementDateFlows, # Date settlementDate = Date()); - # static Date::serial_type - # accruedDays(const Leg& leg, - # bool includeSettlementDateFlows, - # Date settlementDate = Date()); - # static Real - # accruedAmount(const Leg& leg, - # bool includeSettlementDateFlows, - # Date settlementDate = Date()); + @staticmethod + Date.serial_type accruedDays(const Leg& leg, + optional[bool] includeSettlementDateFlows, # = nullopt + Date settlementDate) # = Date() + @staticmethod + Real accruedAmount(const Leg& leg, + optional[bool] includeSettlementDateFlows, # =nullopt + Date settlementDate) # = Date() @staticmethod Real npv(const Leg& leg, const YieldTermStructure& discountCurve, - bool includeSettlementDateFlows, + optional[bool] includeSettlementDateFlows, # = nullopt Date settlementDate, # = Date(), Date npvDate) # = Date()) @staticmethod Real bps(const Leg& leg, const YieldTermStructure& discountCurve, - bool includeSettlementDateFlows, + optional[bool] includeSettlementDateFlows, # = nullopt Date settlementDate, # = Date(), Date npvDate) # = Date()) @staticmethod pair[Real, Real] npvbps(const Leg& leg, const YieldTermStructure& discountCurve, - bool includeSettlementDateFlows, + optional[bool] includeSettlementDateFlows, # = nullopt Date settlementDate, # = Date(), Date npvDate) #= Date()) diff --git a/quantlib/cashflows/_floating_rate_coupon.pxd b/quantlib/cashflows/_floating_rate_coupon.pxd index ed1402694..2859840d9 100644 --- a/quantlib/cashflows/_floating_rate_coupon.pxd +++ b/quantlib/cashflows/_floating_rate_coupon.pxd @@ -1,11 +1,13 @@ from quantlib.types cimport Natural, Rate, Real, Spread from libcpp cimport bool from quantlib.ext cimport shared_ptr +from quantlib.handle cimport Handle from quantlib.time._date cimport Date from quantlib.time._daycounter cimport DayCounter from quantlib._cashflow cimport CashFlow from quantlib._interest_rate cimport InterestRate from quantlib.cashflows._coupon cimport Coupon +from quantlib.termstructures._yield_term_structure cimport YieldTermStructure from ._coupon_pricer cimport FloatingRateCouponPricer from quantlib.indexes._interest_rate_index cimport InterestRateIndex @@ -29,6 +31,7 @@ cdef extern from 'ql/cashflows/floatingratecoupon.hpp' namespace 'QuantLib' nogi Date fixingDate() Real gearing() Spread spread() + Real price(Handle[YieldTermStructure]) Rate indexFixing() Rate convexityAdjustment() except + Rate adjustedFixing() except + diff --git a/quantlib/cashflows/_overnight_indexed_coupon.pxd b/quantlib/cashflows/_overnight_indexed_coupon.pxd index 91d226cff..c0aa631ba 100644 --- a/quantlib/cashflows/_overnight_indexed_coupon.pxd +++ b/quantlib/cashflows/_overnight_indexed_coupon.pxd @@ -2,8 +2,9 @@ from quantlib.types cimport Integer, Natural, Rate, Real, Spread, Time from libcpp cimport bool from libcpp.vector cimport vector -from quantlib.ext cimport shared_ptr +from quantlib.ext cimport shared_ptr, optional from quantlib.time._date cimport Date +from quantlib.time._period cimport Period from quantlib.time._daycounter cimport DayCounter from quantlib.time._schedule cimport Schedule from quantlib.time._calendar cimport Calendar @@ -11,6 +12,7 @@ from quantlib.time.businessdayconvention cimport BusinessDayConvention from quantlib.indexes._ibor_index cimport OvernightIndex from ._floating_rate_coupon cimport FloatingRateCoupon +from ._overnight_indexed_coupon_pricer cimport OvernightIndexedCouponPricer from .rateaveraging cimport RateAveraging from .._cashflow cimport Leg @@ -28,9 +30,11 @@ cdef extern from 'ql/cashflows/overnightindexedcoupon.hpp' namespace 'QuantLib' const DayCounter& dayCounter, #= DayCounter(), bool telescopicValueDates, #=False, RateAveraging averagingMethod, # = RateAveraging::Compound - Natural lookback_days, - Natural lockout_days, - bool apply_observation_shift) + Natural lookback_days, # = Null + Natural lockout_days, # = 0 + bool apply_observation_shift, #+ False + bool compound_spread, # = False + ) vector[Date]& fixingDates() vector[Time]& dt() @@ -39,6 +43,10 @@ cdef extern from 'ql/cashflows/overnightindexedcoupon.hpp' namespace 'QuantLib' RateAveraging averagingMethod() Natural lockoutDays() bool applyObservationShift() + bool compoundSpreadDaily() + Real effectiveSpread() + Real effectiveIndexFixing() + cdef cppclass OvernightLeg: OvernightLeg(Schedule schedule, shared_ptr[OvernightIndex] overnightIndex) @@ -48,9 +56,25 @@ cdef extern from 'ql/cashflows/overnightindexedcoupon.hpp' namespace 'QuantLib' OvernightLeg& withPaymentCalendar(Calendar) OvernightLeg& withPaymentLag(Integer Lag) OvernightLeg& withSpreads(Real spread) - OvernightLeg& withObservationShift(bool) + OvernightLeg& withSpreads(const vector[Spread]& spreads) + OvernightLeg& withTelescopicValueDates(bool telescopicValueDates) + OvernightLeg& withAveragingMethod(RateAveraging averagingMethod) OvernightLeg& withLookbackDays(Natural) OvernightLeg& withLockoutDays(Natural) + OvernightLeg& withObservationShift(bool applyObservationShift) # = true); + OvernightLeg& compoundingSpreadDaily(bool compoundSpreadDaily) # = true); + OvernightLeg& withLookback(const Period& lookback) + OvernightLeg& withCaps(Rate cap) + OvernightLeg& withCaps(const vector[Rate]& caps) + OvernightLeg& withFloors(Rate floor) + OvernightLeg& withFloors(const vector[Rate]& floors); + OvernightLeg& withNakedOption(bool nakedOption) + OvernightLeg& withDailyCapFloor(bool dailyCapFloor) # = true); + OvernightLeg& inArrears(bool inArrears) + OvernightLeg& withLastRecentPeriod(const optional[Period]& lastRecentPeriod) + OvernightLeg& withLastRecentPeriodCalendar(const Calendar& lastRecentPeriodCalendar) + OvernightLeg& withPaymentDates(const vector[Date]& paymentDates) + OvernightLeg& withCouponPricer(const shared_ptr[OvernightIndexedCouponPricer]& couponPricer) Leg operator() const cdef extern from 'ql/cashflows/overnightindexedcoupon.hpp': diff --git a/quantlib/cashflows/_overnight_indexed_coupon_pricer.pxd b/quantlib/cashflows/_overnight_indexed_coupon_pricer.pxd index b79c368dc..e68c56de2 100644 --- a/quantlib/cashflows/_overnight_indexed_coupon_pricer.pxd +++ b/quantlib/cashflows/_overnight_indexed_coupon_pricer.pxd @@ -1,13 +1,21 @@ from quantlib.types cimport Rate, Real from libcpp cimport bool +from quantlib.handle cimport Handle from ._coupon_pricer cimport FloatingRateCouponPricer +from quantlib.termstructures.volatility.optionlet._optionlet_volatility_structure cimport OptionletVolatilityStructure cdef extern from 'ql/cashflows/overnightindexedcouponpricer.hpp' namespace 'QuantLib' nogil: - cdef cppclass CompoundingOvernightIndexedCouponPricer(FloatingRateCouponPricer): + + cdef cppclass OvernightIndexedCouponPricer(FloatingRateCouponPricer): + pass + + cdef cppclass CompoundingOvernightIndexedCouponPricer(OvernightIndexedCouponPricer): pass - cdef cppclass ArithmeticAveragedOvernightIndexedCouponPricer(FloatingRateCouponPricer): + cdef cppclass ArithmeticAveragedOvernightIndexedCouponPricer(OvernightIndexedCouponPricer): ArithmeticAveragedOvernightIndexedCouponPricer( Real meanReversion, # = 0.03 Real volatility, # = 0.00 No convexity adjustment by default - bool byApprox # = false, True to use Katsumi Takada approximation + bool byApprox, # = false, True to use Katsumi Takada approximation + Handle[OptionletVolatilityStructure] v, # = Handle[OptionletVolatilityStructure]() + const bool effective_volatility_input, # = False ) diff --git a/quantlib/cashflows/api.py b/quantlib/cashflows/api.py index a554a163d..727d09b63 100644 --- a/quantlib/cashflows/api.py +++ b/quantlib/cashflows/api.py @@ -1,5 +1,7 @@ -from .overnight_indexed_coupon import OvernightIndexedCoupon, OvernightLeg +from .overnight_indexed_coupon import OvernightIndexedCoupon, OvernightLeg, as_overnight_indexed_coupon from .cms_coupon import CmsCoupon -from .ibor_coupon import IborCoupon -from .fixed_rate_coupon import FixedRateCoupon, FixedRateLeg +from .ibor_coupon import IborCoupon, as_ibor_coupon +from .floating_rate_coupon import FloatingRateCoupon, as_floating_rate_coupon +from .fixed_rate_coupon import FixedRateCoupon, FixedRateLeg, as_fixed_rate_coupon from ..cashflow import SimpleCashFlow, Leg +from .cap_floored_coupon import CappedFlooredCoupon, as_capped_floored_coupon diff --git a/quantlib/cashflows/cap_floored_coupon.pxd b/quantlib/cashflows/cap_floored_coupon.pxd index 26af624d6..fb20d689c 100644 --- a/quantlib/cashflows/cap_floored_coupon.pxd +++ b/quantlib/cashflows/cap_floored_coupon.pxd @@ -2,7 +2,7 @@ from .floating_rate_coupon cimport FloatingRateCoupon from . cimport _cap_floored_coupon as _cfc cdef class CappedFlooredCoupon(FloatingRateCoupon): - cdef inline _cfc.CappedFlooredCoupon* as_ptr(self) + cdef inline _cfc.CappedFlooredCoupon* as_ptr(self) noexcept cdef class CappedFlooredIborCoupon(CappedFlooredCoupon): pass diff --git a/quantlib/cashflows/cap_floored_coupon.pyx b/quantlib/cashflows/cap_floored_coupon.pyx index 48cd4126c..6321d92bb 100644 --- a/quantlib/cashflows/cap_floored_coupon.pyx +++ b/quantlib/cashflows/cap_floored_coupon.pyx @@ -1,15 +1,15 @@ -include '../types.pxi' +from quantlib.types cimport Natural, Rate, Real, Spread from libcpp cimport bool from cython.operator cimport dereference as deref from quantlib.utilities.null cimport Null -from quantlib.ext cimport shared_ptr, static_pointer_cast +from quantlib.ext cimport static_pointer_cast, dynamic_pointer_cast from quantlib.cashflows.coupon_pricer cimport FloatingRateCouponPricer from quantlib.indexes.ibor_index cimport IborIndex from quantlib.indexes.swap_index cimport SwapIndex from quantlib.time.date cimport Date, Period from quantlib.time.daycounter cimport DayCounter -from .._cashflow cimport CashFlow +from ..cashflow cimport CashFlow from . cimport _floating_rate_coupon as _frc cimport quantlib.indexes._ibor_index as _ii cimport quantlib.indexes._swap_index as _si @@ -18,12 +18,15 @@ cdef class CappedFlooredCoupon(FloatingRateCoupon): def __init__(self, FloatingRateCoupon underlying not None, Rate cap=Null[Real](), Rate floor=Null[Real]()): - self._thisptr = shared_ptr[CashFlow](new _cfc.CappedFlooredCoupon( - static_pointer_cast[_frc.FloatingRateCoupon](underlying._thisptr), - cap, - floor)) + self._thisptr.reset( + new _cfc.CappedFlooredCoupon( + static_pointer_cast[_frc.FloatingRateCoupon](underlying._thisptr), + cap, + floor + ) + ) - cdef inline _cfc.CappedFlooredCoupon* as_ptr(self): + cdef inline _cfc.CappedFlooredCoupon* as_ptr(self) noexcept: return <_cfc.CappedFlooredCoupon*>self._thisptr.get() @property @@ -56,15 +59,22 @@ cdef class CappedFlooredCoupon(FloatingRateCoupon): @property def is_floored(self): - return (<_cfc.CappedFlooredCoupon*>self._thisptr.get()).isFloored() + return self.as_ptr().isFloored() @property def underlying(self): cdef FloatingRateCoupon instance = FloatingRateCoupon.__new__(FloatingRateCoupon) - instance._thisptr = static_pointer_cast[CashFlow]( - (<_cfc.CappedFlooredCoupon*>self._thisptr.get()).underlying()) + instance._thisptr = self.as_ptr().underlying() return instance +def as_capped_floored_coupon(CashFlow cf): + cdef CappedFlooredCoupon coupon = CappedFlooredCoupon.__new__(CappedFlooredCoupon) + coupon._thisptr = dynamic_pointer_cast[_cfc.CappedFlooredCoupon](cf._thisptr) + if not coupon._thisptr: + return None + else: + return coupon + cdef class CappedFlooredIborCoupon(CappedFlooredCoupon): def __init__(self, Date payment_date not None, Real nominal, @@ -80,7 +90,8 @@ cdef class CappedFlooredIborCoupon(CappedFlooredCoupon): Date ref_period_end=Date(), DayCounter day_counter=DayCounter(), bool is_in_arrears=False): - self._thisptr = shared_ptr[CashFlow](new _cfc.CappedFlooredIborCoupon( + self._thisptr.reset( + new _cfc.CappedFlooredIborCoupon( payment_date._thisptr, nominal, start_date._thisptr, @@ -94,7 +105,8 @@ cdef class CappedFlooredIborCoupon(CappedFlooredCoupon): ref_period_start._thisptr, ref_period_end._thisptr, deref(day_counter._thisptr), - is_in_arrears)) + is_in_arrears) + ) cdef class CappedFlooredCmsCoupon(CappedFlooredCoupon): def __init__(self, Date payment_date not None, @@ -111,7 +123,8 @@ cdef class CappedFlooredCmsCoupon(CappedFlooredCoupon): Date ref_period_end=Date(), DayCounter day_counter=DayCounter(), bool is_in_arrears=False): - self._thisptr = shared_ptr[CashFlow](new _cfc.CappedFlooredCmsCoupon( + self._thisptr.reset( + new _cfc.CappedFlooredCmsCoupon( payment_date._thisptr, nominal, start_date._thisptr, @@ -125,4 +138,6 @@ cdef class CappedFlooredCmsCoupon(CappedFlooredCoupon): ref_period_start._thisptr, ref_period_end._thisptr, deref(day_counter._thisptr), - is_in_arrears)) + is_in_arrears + ) + ) diff --git a/quantlib/cashflows/cashflows.pyx b/quantlib/cashflows/cashflows.pyx index f66680132..bd5bea6ed 100644 --- a/quantlib/cashflows/cashflows.pyx +++ b/quantlib/cashflows/cashflows.pyx @@ -1,37 +1,105 @@ from cython.operator cimport dereference as deref from libcpp cimport bool +from quantlib.ext cimport optional, nullopt from quantlib.termstructures.yield_term_structure cimport YieldTermStructure -from quantlib.time.date cimport Date +from quantlib.time.date cimport Date, _pydate_from_qldate +from quantlib.time._date cimport Date as QlDate from ..cashflow cimport Leg from ._cashflows cimport CashFlows -def previous_cash_flow_amount(Leg leg, bool include_settlement_date_flows, Date settlement_date=Date()): - return CashFlows.previousCashFlowAmount(leg._thisptr, include_settlement_date_flows, settlement_date._thisptr) +def previous_cash_flow_amount(Leg leg, include_settlement_date_flows=None, Date settlement_date=Date()): + cdef optional[bool] include_settlement_date_flows_opt = nullopt + if include_settlement_date_flows is not None: + include_settlement_date_flows_opt = include_settlement_date_flows + return CashFlows.previousCashFlowAmount(leg._thisptr, include_settlement_date_flows_opt, settlement_date._thisptr) -def next_cash_flow_amount(Leg leg, bool include_settlement_date_flows, Date settlement_date=Date()): - return CashFlows.nextCashFlowAmount(leg._thisptr, include_settlement_date_flows, settlement_date._thisptr) +def next_cash_flow_amount(Leg leg, include_settlement_date_flows=None, Date settlement_date=Date()): + cdef optional[bool] include_settlement_date_flows_opt = nullopt + if include_settlement_date_flows is not None: + include_settlement_date_flows_opt = include_settlement_date_flows + return CashFlows.nextCashFlowAmount(leg._thisptr, include_settlement_date_flows_opt, settlement_date._thisptr) -def npv(Leg leg, YieldTermStructure discount_curve, bool include_settlement_date_flows, +def npv(Leg leg, YieldTermStructure discount_curve, include_settlement_date_flows=None, Date settlement_date=Date(), Date npv_date=Date()): + cdef optional[bool] include_settlement_date_flows_opt = nullopt + if include_settlement_date_flows is not None: + include_settlement_date_flows_opt = include_settlement_date_flows + return CashFlows.npv(leg._thisptr, deref(discount_curve.as_yts_ptr()), - include_settlement_date_flows, + include_settlement_date_flows_opt, settlement_date._thisptr, npv_date._thisptr) -def bps(Leg leg, YieldTermStructure discount_curve, bool include_settlement_date_flows, +def bps(Leg leg, YieldTermStructure discount_curve, include_settlement_date_flows=None, Date settlement_date=Date(), Date npv_date=Date()): + cdef optional[bool] include_settlement_date_flows_opt = nullopt + if include_settlement_date_flows is not None: + include_settlement_date_flows_opt = include_settlement_date_flows return CashFlows.bps(leg._thisptr, deref(discount_curve.as_yts_ptr()), - include_settlement_date_flows, + include_settlement_date_flows_opt, settlement_date._thisptr, npv_date._thisptr) -def npvbps(Leg leg, YieldTermStructure discount_curve, bool include_settlement_date_flows, +def npvbps(Leg leg, YieldTermStructure discount_curve, include_settlement_date_flows=None, Date settlement_date=Date(), Date npv_date=Date()): + cdef optional[bool] include_settlement_date_flows_opt = nullopt + if include_settlement_date_flows is not None: + include_settlement_date_flows_opt = include_settlement_date_flows return CashFlows.npvbps(leg._thisptr, deref(discount_curve.as_yts_ptr()), - include_settlement_date_flows, + include_settlement_date_flows_opt, settlement_date._thisptr, npv_date._thisptr) + + +def accrual_start_date(Leg leg, include_settlement_date_flows=None, + Date settlement_date=Date()): + cdef optional[bool] include_settlement_date_flows_opt = nullopt + cdef QlDate d + if include_settlement_date_flows is not None: + include_settlement_date_flows_opt = include_settlement_date_flows + d = CashFlows.accrualStartDate(leg._thisptr, + include_settlement_date_flows_opt, + settlement_date._thisptr) + return _pydate_from_qldate(d) + +def accrual_end_date(Leg leg, include_settlement_date_flows=None, + Date settlement_date=Date()): + cdef optional[bool] include_settlement_date_flows_opt = nullopt + if include_settlement_date_flows is not None: + include_settlement_date_flows_opt = include_settlement_date_flows + d = CashFlows.accrualEndDate(leg._thisptr, + include_settlement_date_flows_opt, + settlement_date._thisptr) + return _pydate_from_qldate(d) + + +def accrual_days(Leg leg, include_settlement_date_flows=None, + Date settlement_date=Date()): + cdef optional[bool] include_settlement_date_flows_opt = nullopt + if include_settlement_date_flows is not None: + include_settlement_date_flows_opt = include_settlement_date_flows + return CashFlows.accrualDays(leg._thisptr, + include_settlement_date_flows_opt, + settlement_date._thisptr) + +def accrued_days(Leg leg, include_settlement_date_flows=None, + Date settlement_date=Date()): + cdef optional[bool] include_settlement_date_flows_opt = nullopt + if include_settlement_date_flows is not None: + include_settlement_date_flows_opt = include_settlement_date_flows + return CashFlows.accruedDays(leg._thisptr, + include_settlement_date_flows_opt, + settlement_date._thisptr) + +def accrued_amount(Leg leg, include_settlement_date_flows=None, + Date settlement_date=Date()): + cdef optional[bool] include_settlement_date_flows_opt = nullopt + if include_settlement_date_flows is not None: + include_settlement_date_flows_opt = include_settlement_date_flows + return CashFlows.accruedAmount(leg._thisptr, + include_settlement_date_flows_opt, + settlement_date._thisptr) diff --git a/quantlib/cashflows/coupon.pxd b/quantlib/cashflows/coupon.pxd index 76c502f7a..310f1829c 100644 --- a/quantlib/cashflows/coupon.pxd +++ b/quantlib/cashflows/coupon.pxd @@ -2,4 +2,4 @@ from quantlib.cashflow cimport CashFlow cimport quantlib.cashflows._coupon as _coupon cdef class Coupon(CashFlow): - cdef inline _coupon.Coupon* _get_coupon(self) + cdef inline _coupon.Coupon* _get_coupon(self) noexcept diff --git a/quantlib/cashflows/coupon.pyx b/quantlib/cashflows/coupon.pyx index 7b53e7601..1c2830bfb 100644 --- a/quantlib/cashflows/coupon.pyx +++ b/quantlib/cashflows/coupon.pyx @@ -8,7 +8,7 @@ cimport quantlib._cashflow as _cf cdef class Coupon(CashFlow): - cdef inline _coupon.Coupon* _get_coupon(self): + cdef inline _coupon.Coupon* _get_coupon(self) noexcept: return <_coupon.Coupon*>self._thisptr.get() @property @@ -61,3 +61,8 @@ cdef class Coupon(CashFlow): cdef DayCounter dc = DayCounter.__new__(DayCounter) dc._thisptr = new _dc.DayCounter(self._get_coupon().dayCounter()) return dc + +def as_coupon(CashFlow cf): + cdef Coupon coupon = Coupon.__new__(Coupon) + coupon._thisptr = cf._thisptr + return coupon diff --git a/quantlib/cashflows/fixed_rate_coupon.pyx b/quantlib/cashflows/fixed_rate_coupon.pyx index 47639fc57..d38e39091 100644 --- a/quantlib/cashflows/fixed_rate_coupon.pyx +++ b/quantlib/cashflows/fixed_rate_coupon.pyx @@ -3,7 +3,7 @@ from cython.operator cimport dereference as deref, preincrement as preinc from libcpp.vector cimport vector from libcpp.utility cimport move from quantlib.compounding cimport Compounding -from quantlib.ext cimport shared_ptr +from quantlib.ext cimport shared_ptr, dynamic_pointer_cast from quantlib.time.businessdayconvention cimport BusinessDayConvention from quantlib.time.calendar cimport Calendar from quantlib.time.date cimport Date @@ -12,6 +12,7 @@ from quantlib.time.daycounter cimport DayCounter from quantlib.time.schedule cimport Schedule cimport quantlib._cashflow as _cf from quantlib.interest_rate cimport InterestRate +from ..cashflow cimport CashFlow from .._cashflow cimport Leg as QlLeg cimport quantlib._interest_rate as _ir @@ -36,6 +37,15 @@ cdef class FixedRateCoupon(Coupon): ir._thisptr = (<_frc.FixedRateCoupon*>self._thisptr.get()).interestRate() return ir +def as_fixed_rate_coupon(CashFlow cf): + cdef FixedRateCoupon coupon = FixedRateCoupon.__new__(FixedRateCoupon) + coupon._thisptr = dynamic_pointer_cast[_frc.FixedRateCoupon](cf._thisptr) + if not coupon._thisptr: + return None + else: + return coupon + + cdef class FixedRateLeg(Leg): def __init__(self, Schedule schedule): diff --git a/quantlib/cashflows/floating_rate_coupon.pxd b/quantlib/cashflows/floating_rate_coupon.pxd index dcc085f9f..e47a9b973 100644 --- a/quantlib/cashflows/floating_rate_coupon.pxd +++ b/quantlib/cashflows/floating_rate_coupon.pxd @@ -2,4 +2,4 @@ from quantlib.cashflows.coupon cimport Coupon from . cimport _floating_rate_coupon as _frc cdef class FloatingRateCoupon(Coupon): - cdef inline _frc.FloatingRateCoupon* _get_frc(self) + cdef inline _frc.FloatingRateCoupon* _get_frc(self) noexcept diff --git a/quantlib/cashflows/floating_rate_coupon.pyx b/quantlib/cashflows/floating_rate_coupon.pyx index 9ec4a397f..497389074 100644 --- a/quantlib/cashflows/floating_rate_coupon.pyx +++ b/quantlib/cashflows/floating_rate_coupon.pyx @@ -1,11 +1,13 @@ from quantlib.types cimport Natural, Real, Spread from libcpp cimport bool from cython.operator cimport dereference as deref -from quantlib.ext cimport shared_ptr, static_pointer_cast +from quantlib.ext cimport shared_ptr, static_pointer_cast, dynamic_pointer_cast +from quantlib.handle cimport HandleYieldTermStructure from quantlib.time.date cimport Date, date_from_qldate from quantlib.time.daycounter cimport DayCounter from .coupon_pricer cimport FloatingRateCouponPricer cimport quantlib._cashflow as _cf +from ..cashflow cimport CashFlow from quantlib.indexes.interest_rate_index cimport InterestRateIndex cimport quantlib.indexes._interest_rate_index as _iri from quantlib._index cimport Index @@ -28,7 +30,7 @@ cdef class FloatingRateCoupon(Coupon): deref(day_counter._thisptr), is_in_arrears) ) - cdef inline _frc.FloatingRateCoupon* _get_frc(self): + cdef inline _frc.FloatingRateCoupon* _get_frc(self) noexcept: return <_frc.FloatingRateCoupon*>self._thisptr.get() def set_pricer(self, FloatingRateCouponPricer pricer not None): @@ -38,6 +40,14 @@ cdef class FloatingRateCoupon(Coupon): def fixing_days(self): return self._get_frc().fixingDays() + @property + def gearing(self): + return self._get_frc().gearing() + + @property + def spread(self): + return self._get_frc().spread() + @property def fixing_date(self): return date_from_qldate(self._get_frc().fixingDate()) @@ -63,3 +73,14 @@ cdef class FloatingRateCoupon(Coupon): @property def is_in_arrears(self): return self._get_frc().isInArrears() + + def price(self, HandleYieldTermStructure discountingCurve): + return self._get_frc().price(discountingCurve.handle()) + +def as_floating_rate_coupon(CashFlow cf): + cdef FloatingRateCoupon coupon = FloatingRateCoupon.__new__(FloatingRateCoupon) + coupon._thisptr = dynamic_pointer_cast[_frc.FloatingRateCoupon](cf._thisptr) + if not coupon._thisptr: + return None + else: + return coupon diff --git a/quantlib/cashflows/ibor_coupon.pyx b/quantlib/cashflows/ibor_coupon.pyx index c242c565c..43bc454a0 100644 --- a/quantlib/cashflows/ibor_coupon.pyx +++ b/quantlib/cashflows/ibor_coupon.pyx @@ -2,11 +2,12 @@ include '../types.pxi' from libcpp cimport bool from cython.operator cimport dereference as deref -from quantlib.ext cimport shared_ptr, static_pointer_cast +from quantlib.ext cimport shared_ptr, static_pointer_cast, dynamic_pointer_cast from quantlib.time.date cimport Date from quantlib.time.daycounter cimport DayCounter cimport quantlib.cashflows._ibor_coupon as _ic -cimport quantlib._cashflow as _cf +from ..cashflow cimport CashFlow +from .. cimport _cashflow as _cf cimport quantlib.indexes._ibor_index as _ii from quantlib.indexes.ibor_index cimport IborIndex @@ -18,7 +19,7 @@ cdef class IborCoupon(FloatingRateCoupon): Spread spread=0., Date ref_period_start=Date(), Date ref_period_end=Date(), DayCounter day_counter=DayCounter(), bool is_in_arrears=False): - self._thisptr = shared_ptr[_cf.CashFlow]( + self._thisptr.reset( new _ic.IborCoupon( payment_date._thisptr, nominal, start_date._thisptr, end_date._thisptr, @@ -26,10 +27,19 @@ cdef class IborCoupon(FloatingRateCoupon): static_pointer_cast[_ii.IborIndex](index._thisptr), gearing, spread, ref_period_start._thisptr, ref_period_end._thisptr, - deref(day_counter._thisptr), is_in_arrears) + deref(day_counter._thisptr), is_in_arrears + ) ) Settings = IborCouponSettings() +def as_ibor_coupon(CashFlow cf): + cdef IborCoupon coupon = IborCoupon.__new__(IborCoupon) + coupon._thisptr = dynamic_pointer_cast[_ic.IborCoupon](cf._thisptr) + if not coupon._thisptr: + return None + else: + return coupon + cdef class IborCouponSettings: @staticmethod def create_at_par_coupons(): diff --git a/quantlib/cashflows/overnight_indexed_coupon.pyx b/quantlib/cashflows/overnight_indexed_coupon.pyx index 27ced848e..2f5fed1bc 100644 --- a/quantlib/cashflows/overnight_indexed_coupon.pyx +++ b/quantlib/cashflows/overnight_indexed_coupon.pyx @@ -1,10 +1,10 @@ -from quantlib.types cimport Integer, Natural, Real, Spread +from quantlib.types cimport Integer, Natural, Rate, Real, Spread from libcpp cimport bool from libcpp.vector cimport vector from libcpp.utility cimport move from cython.operator cimport dereference as deref, preincrement as preinc -from quantlib.ext cimport make_shared, shared_ptr, static_pointer_cast +from quantlib.ext cimport make_shared, shared_ptr, static_pointer_cast, dynamic_pointer_cast from quantlib.time.businessdayconvention cimport BusinessDayConvention from quantlib.time.date cimport Date, date_from_qldate from quantlib.time._date cimport Date as QlDate @@ -16,8 +16,10 @@ from quantlib.utilities.null cimport Null cimport quantlib.indexes._ibor_index as _ii cimport quantlib._cashflow as _cf from .rateaveraging cimport RateAveraging +from .overnight_indexed_coupon_pricer cimport OvernightIndexedCouponPricer from . cimport _overnight_indexed_coupon as _oic from .._cashflow cimport Leg as QlLeg +from ..cashflow cimport CashFlow cdef class OvernightIndexedCoupon(FloatingRateCoupon): @@ -84,6 +86,19 @@ cdef class OvernightIndexedCoupon(FloatingRateCoupon): def apply_observation_shift(self): return (<_oic.OvernightIndexedCoupon*>self._thisptr.get()).applyObservationShift() + @property + def compound_spread_daily(self): + return (<_oic.OvernightIndexedCoupon*>self._thisptr.get()).compoundSpreadDaily() + +def as_overnight_indexed_coupon(CashFlow cf): + cdef OvernightIndexedCoupon coupon = OvernightIndexedCoupon.__new__(OvernightIndexedCoupon) + coupon._thisptr = dynamic_pointer_cast[_oic.OvernightIndexedCoupon](cf._thisptr) + if not coupon._thisptr: + return None + else: + return coupon + + cdef class OvernightLeg(Leg): def __iter__(self): @@ -124,6 +139,10 @@ cdef class OvernightLeg(Leg): self.leg.withSpreads(spread) return self + def with_averaging_method(self, RateAveraging averaging_method): + self.leg.withAveragingMethod(averaging_method) + return self + def with_observation_shift(self, bool apply_observation_shift=True): self.leg.withObservationShift(apply_observation_shift) return self @@ -140,6 +159,34 @@ cdef class OvernightLeg(Leg): self.leg.withPaymentLag(lag) return self + def compounding_spread_daily(self, bool compound_spread_daily=True): + self.leg.compoundingSpreadDaily(compound_spread_daily) + return self + + def with_caps(self, caps): + cdef vector[Rate] c_caps + if isinstance(caps, list): + c_caps = caps + self.leg.withCaps(c_caps) + else: + self.leg.withCaps(caps) + return self + + def with_floors(self, floors): + cdef vector[Rate] c_floors + if isinstance(floors, list): + c_floors = floors + self.leg.withFloors(c_floors) + else: + self.leg.withFloors(floors) + return self + + def with_coupon_pricer(self, OvernightIndexedCouponPricer coupon_pricer): + self.leg.withCouponPricer( + static_pointer_cast[_oic.OvernightIndexedCouponPricer](coupon_pricer._thisptr) + ) + return self + def __call__(self): self._thisptr = move[QlLeg](_oic.to_leg(deref(self.leg))) return self diff --git a/quantlib/cashflows/overnight_indexed_coupon_pricer.pxd b/quantlib/cashflows/overnight_indexed_coupon_pricer.pxd index 42e14a891..431049f81 100644 --- a/quantlib/cashflows/overnight_indexed_coupon_pricer.pxd +++ b/quantlib/cashflows/overnight_indexed_coupon_pricer.pxd @@ -1,8 +1,11 @@ from .coupon_pricer cimport FloatingRateCouponPricer -cdef class CompoundingOvernightIndexedCouponPricer(FloatingRateCouponPricer): +cdef class OvernightIndexedCouponPricer(FloatingRateCouponPricer): + pass + +cdef class CompoundingOvernightIndexedCouponPricer(OvernightIndexedCouponPricer): pass -cdef class ArithmeticAveragedOvernightIndexedCouponPricer(FloatingRateCouponPricer): +cdef class ArithmeticAveragedOvernightIndexedCouponPricer(OvernightIndexedCouponPricer): pass diff --git a/quantlib/cashflows/overnight_indexed_coupon_pricer.pyx b/quantlib/cashflows/overnight_indexed_coupon_pricer.pyx index e359b9996..2ea198d42 100644 --- a/quantlib/cashflows/overnight_indexed_coupon_pricer.pyx +++ b/quantlib/cashflows/overnight_indexed_coupon_pricer.pyx @@ -1,16 +1,26 @@ from quantlib.types cimport Real from libcpp cimport bool +from quantlib.handle cimport Handle, HandleOptionletVolatilityStructure from . cimport _overnight_indexed_coupon_pricer as _oicp -cdef class CompoundingOvernightIndexedCouponPricer(FloatingRateCouponPricer): + +cdef class CompoundingOvernightIndexedCouponPricer(OvernightIndexedCouponPricer): 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): +cdef class ArithmeticAveragedOvernightIndexedCouponPricer(OvernightIndexedCouponPricer): + def __init__(self, Real mean_reversion = 0.03, Real volatility=0.0, bool by_approx=False, HandleOptionletVolatilityStructure v = HandleOptionletVolatilityStructure(), bool effective_volatility_input = 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)) + self._thisptr.reset( + new _oicp.ArithmeticAveragedOvernightIndexedCouponPricer( + mean_reversion, + volatility, + by_approx, + v.handle(), + effective_volatility_input + ) + ) diff --git a/quantlib/ext.pxd b/quantlib/ext.pxd index 5de844ed7..4b52acce8 100644 --- a/quantlib/ext.pxd +++ b/quantlib/ext.pxd @@ -27,9 +27,10 @@ cdef extern from 'ql/optional.hpp' namespace 'QuantLib::ext' nogil: optional() optional(nullopt_t) optional(const T&) except + - T& value() + T& value() except + T& value_or[U](U& default_value) bool operator!() optional& operator=(optional&) + optional& operator=[U](U&) optional[T] make_optional[T](...) except + diff --git a/quantlib/indexes/api.py b/quantlib/indexes/api.py index 5901a44b0..f4747fad4 100644 --- a/quantlib/indexes/api.py +++ b/quantlib/indexes/api.py @@ -10,6 +10,7 @@ from .ibor.libor import Libor from .ibor.euribor import Euribor, Euribor3M, Euribor6M from .ibor.eonia import Eonia +from .ibor.fedfunds import FedFunds from .ibor.sofr import Sofr from .ibor.usdlibor import USDLibor from .ibor_index import IborIndex diff --git a/quantlib/indexes/ibor/_fedfunds.pxd b/quantlib/indexes/ibor/_fedfunds.pxd new file mode 100644 index 000000000..6f22fbfc1 --- /dev/null +++ b/quantlib/indexes/ibor/_fedfunds.pxd @@ -0,0 +1,8 @@ +from quantlib._handle cimport Handle +from quantlib.termstructures._yield_term_structure cimport YieldTermStructure +from quantlib.indexes._ibor_index cimport OvernightIndex + +cdef extern from 'ql/indexes/ibor/fedfunds.hpp' namespace 'QuantLib' nogil: + + cdef cppclass FedFunds(OvernightIndex): + FedFunds(Handle[YieldTermStructure]& h) except + diff --git a/quantlib/indexes/ibor/_sofr.pxd b/quantlib/indexes/ibor/_sofr.pxd index f6381db0c..7e5de49ae 100644 --- a/quantlib/indexes/ibor/_sofr.pxd +++ b/quantlib/indexes/ibor/_sofr.pxd @@ -2,7 +2,7 @@ from quantlib._handle cimport Handle from quantlib.termstructures._yield_term_structure cimport YieldTermStructure from quantlib.indexes._ibor_index cimport OvernightIndex -cdef extern from 'ql/indexes/ibor/sofr.hpp' namespace 'QuantLib': +cdef extern from 'ql/indexes/ibor/sofr.hpp' namespace 'QuantLib' nogil: cdef cppclass Sofr(OvernightIndex): Sofr(Handle[YieldTermStructure]& h) except + diff --git a/quantlib/indexes/ibor/fedfunds.pxd b/quantlib/indexes/ibor/fedfunds.pxd new file mode 100644 index 000000000..65356410e --- /dev/null +++ b/quantlib/indexes/ibor/fedfunds.pxd @@ -0,0 +1,4 @@ +from ..ibor_index cimport OvernightIndex + +cdef class FedFunds(OvernightIndex): + pass diff --git a/quantlib/indexes/ibor/fedfunds.pyx b/quantlib/indexes/ibor/fedfunds.pyx new file mode 100644 index 000000000..009e84d76 --- /dev/null +++ b/quantlib/indexes/ibor/fedfunds.pyx @@ -0,0 +1,7 @@ +from quantlib.handle cimport HandleYieldTermStructure +from . cimport _fedfunds as _ff +from ... cimport _index as _in + +cdef class FedFunds(OvernightIndex): + def __init__(self, HandleYieldTermStructure yts=HandleYieldTermStructure()): + self._thisptr.reset(new _ff.FedFunds(yts.handle())) diff --git a/quantlib/methods/montecarlo/_pathgenerator.pxd b/quantlib/methods/montecarlo/_pathgenerator.pxd new file mode 100644 index 000000000..d749d3ec2 --- /dev/null +++ b/quantlib/methods/montecarlo/_pathgenerator.pxd @@ -0,0 +1,17 @@ +from libcpp cimport bool +from quantlib._time_grid cimport TimeGrid +from libcpp.vector cimport vector +from ._multipath cimport Path +from ._sample cimport Sample +from quantlib._stochastic_process cimport StochasticProcess + +cdef extern from 'ql/methods/montecarlo/pathgenerator.hpp' namespace 'QuantLib' nogil: + cdef cppclass PathGenerator[GSG]: + ctypedef Sample[Path] sample_type + MultiPathGenerator(const shared_ptr[StochasticProcess]&, + const TimeGrid&, + GSG generator, + bool brownianBridge) # = false) + const sample_type& next() + const sample_type& antithetic() + Size size() diff --git a/quantlib/models/shortrate/_twofactor_model.pxd b/quantlib/models/shortrate/_twofactor_model.pxd index b69638b75..720b99307 100644 --- a/quantlib/models/shortrate/_twofactor_model.pxd +++ b/quantlib/models/shortrate/_twofactor_model.pxd @@ -2,7 +2,7 @@ from quantlib.types cimport DiscountFactor, Rate, Real, Time from quantlib.math._array cimport Array from quantlib.models._model cimport ShortRateModel, AffineModel from quantlib.ext cimport shared_ptr -from quantlib._stochastic_process cimport StochasticProcess1D +from quantlib._stochastic_process cimport StochasticProcess, StochasticProcess1D cdef extern from 'ql/models/shortrate/twofactormodel.hpp' namespace 'QuantLib' nogil: @@ -11,7 +11,9 @@ cdef extern from 'ql/models/shortrate/twofactormodel.hpp' namespace 'QuantLib' n ShortRateDynamics(shared_ptr[StochasticProcess1D]& xProcess, shared_ptr[StochasticProcess1D]& yProcess, Real correlation) + Real correlation() Rate shortRate(Time t, Real x, Real y) shared_ptr[StochasticProcess1D]& xProcess() shared_ptr[StochasticProcess1D]& yProcess() + shared_ptr[StochasticProcess]& process() shared_ptr[ShortRateDynamics] dynamics() diff --git a/quantlib/models/shortrate/twofactor_model.pyx b/quantlib/models/shortrate/twofactor_model.pyx index fe874e64f..027b7277c 100644 --- a/quantlib/models/shortrate/twofactor_model.pyx +++ b/quantlib/models/shortrate/twofactor_model.pyx @@ -22,6 +22,11 @@ cdef class ShortRateDynamics: def short_rate(self, Time t, Real x, Real y): return self._thisptr.get().shortRate(t, x, y) + @property + def correlation(self): + """Correlation :math:`rho` between the two brownian motions""" + return self._thisptr.get().correlation() + cdef class TwoFactorModel(ShortRateModel): @property diff --git a/quantlib/pricingengines/bond/_riskybondengine.pxd b/quantlib/pricingengines/bond/_riskybondengine.pxd new file mode 100644 index 000000000..4060636ca --- /dev/null +++ b/quantlib/pricingengines/bond/_riskybondengine.pxd @@ -0,0 +1,5 @@ +from .._pricing_engine cimport PricingEngine + +cdef extrn from 'ql/pricingengines/bond/riskybondengine.hpp' namespace 'QuantLib' nogil: + cdef cppclass RiskyBondEngine(PricingEngine): + pass diff --git a/quantlib/termstructure.pyx b/quantlib/termstructure.pyx index 9850fcdd9..66362a4a7 100644 --- a/quantlib/termstructure.pyx +++ b/quantlib/termstructure.pyx @@ -2,6 +2,7 @@ from quantlib.ext cimport static_pointer_cast 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.time.calendar cimport Calendar cimport quantlib.time._daycounter as _dc cdef class TermStructure(Observable): @@ -18,20 +19,24 @@ cdef class TermStructure(Observable): return static_pointer_cast[QlObservable](self._thisptr) def time_from_reference(self, Date dt): + """date/time conversion""" return self.as_ptr().timeFromReference(dt._thisptr) @property def reference_date(self): + """ the date at which discount = 1.0 and/or variance = 0.0""" cdef QlDate ref_date = self.as_ptr().referenceDate() return date_from_qldate(ref_date) @property def max_date(self): + """the latest date for which the curve can return values""" cdef QlDate max_date = self.as_ptr().maxDate() return date_from_qldate(max_date) @property def max_time(self): + """the latest time for which the curve can return values""" return self.as_ptr().maxTime() @property @@ -42,4 +47,11 @@ cdef class TermStructure(Observable): @property def settlement_days(self): + """ number of settlement days used for reference date calculation""" return self.as_ptr().settlementDays() + + @property + def calendar(self): + cdef Calendar instance = Calendar.__new__(Calendar) + instance._thisptr = self.as_ptr().calendar() + return instance diff --git a/quantlib/termstructures/_inflation_term_structure.pxd b/quantlib/termstructures/_inflation_term_structure.pxd index 45d982137..638ed3390 100644 --- a/quantlib/termstructures/_inflation_term_structure.pxd +++ b/quantlib/termstructures/_inflation_term_structure.pxd @@ -12,52 +12,36 @@ include '../types.pxi' from libcpp cimport bool from quantlib.ext cimport shared_ptr -from quantlib.handle cimport Handle from quantlib.time._date cimport Date from quantlib.time._calendar cimport Calendar from quantlib.time._daycounter cimport DayCounter from quantlib.time._period cimport Period, Frequency -from quantlib.termstructures._yield_term_structure cimport YieldTermStructure from quantlib.termstructures.inflation._seasonality cimport Seasonality - +from .._termstructure cimport TermStructure cdef extern from 'ql/termstructures/inflationtermstructure.hpp' namespace 'QuantLib' nogil: - cdef cppclass InflationTermStructure: - - InflationTermStructure() except + - Date& referenceDate() - Date& maxDate() - Date& baseDate() - Rate baseRate() - + cdef cppclass InflationTermStructure(TermStructure): + Date baseDate() + Real baseRate() cdef cppclass ZeroInflationTermStructure(InflationTermStructure): - - ZeroInflationTermStructure() except + - ZeroInflationTermStructure(DayCounter& dayCounter, - Rate baseZeroRate, - Period& lag, + ZeroInflationTermStructure(Date baseDate, Frequency frequency, - const Handle[YieldTermStructure]& yTS, + DayCounter& dayCounter, const shared_ptr[Seasonality]& seasonality # = shared_ptr() ) except + ZeroInflationTermStructure(const Date& referenceDate, - const Calendar& calendar, - const DayCounter& dayCounter, - Rate baseZeroRate, - const Period& lag, + Date baseDate, Frequency frequency, - const Handle[YieldTermStructure]& yTS, + const DayCounter& dayCounter, const shared_ptr[Seasonality] &seasonality # = shared_ptr()) ) except + ZeroInflationTermStructure(Natural settlementDays, const Calendar& calendar, - const DayCounter& dayCounter, - Rate baseZeroRate, - const Period& lag, + Date baseDate, Frequency frequency, - const Handle[YieldTermStructure]& yTS, + const DayCounter& dayCounter, const shared_ptr[Seasonality] &seasonality # = boost::shared_ptr() ) except + @@ -71,15 +55,23 @@ cdef extern from 'ql/termstructures/inflationtermstructure.hpp' namespace 'Quant cdef cppclass YoYInflationTermStructure(InflationTermStructure): - - YoYInflationTermStructure() except + - YoYInflationTermStructure(DayCounter& dayCounter, - Rate baseZeroRate, - Period& lag, + Rate baseYoYRate, + Frequency frequency, + const DayCounter& dayCounter, + const shared_ptr[Seasonality]& seasonality) except + + YoYInflationTermStructure(Date& referenceDate, + Date baseDate, + Rate baseYoYRate, + Frequency frequency, + const DayCounter& dayCounter, + const shared_ptr[Seasonality]& seasonality) except + + YoYInflationTermStructure(Natural settlmentDays, + const Calendar& calendar, + Date baseDate, + Rate baseYoYRate, Frequency frequency, - bool indexIsInterpolated, - const Handle[YieldTermStructure]& yTS, + const DayCounter& dayCounter, const shared_ptr[Seasonality]& seasonality) except + Rate yoyRate(Date& d, diff --git a/quantlib/termstructures/_vol_term_structure.pxd b/quantlib/termstructures/_vol_term_structure.pxd index e49da1fb9..5cf12ba0f 100644 --- a/quantlib/termstructures/_vol_term_structure.pxd +++ b/quantlib/termstructures/_vol_term_structure.pxd @@ -5,9 +5,10 @@ from quantlib.time._calendar cimport Calendar from quantlib.time._date cimport Date from quantlib.time._period cimport Period from quantlib.time.businessdayconvention cimport BusinessDayConvention +from .._termstructure cimport TermStructure cdef extern from 'ql/termstructures/voltermstructure.hpp' namespace 'QuantLib' nogil: - cdef cppclass VolatilityTermStructure: + cdef cppclass VolatilityTermStructure(TermStructure): VolatilityTermStructure(BusinessDayConvention bdc, const DayCounter& dc) # = DayCounter() #initialize with a fixed reference date diff --git a/quantlib/termstructures/inflation/seasonality.pyx b/quantlib/termstructures/inflation/seasonality.pyx index 8dddf7e53..f856ce219 100644 --- a/quantlib/termstructures/inflation/seasonality.pyx +++ b/quantlib/termstructures/inflation/seasonality.pyx @@ -35,7 +35,8 @@ cdef class Seasonality: return self._thisptr.get().correctZeroRate( d._thisptr, r, - deref(iTS._thisptr)) + deref(<_if.InflationTermStructure*>iTS._thisptr.get()) + ) def correctYoYRate(self, Date d, @@ -45,13 +46,14 @@ cdef class Seasonality: return self._thisptr.get().correctYoYRate( d._thisptr, r, - deref(iTS._thisptr)) + deref(<_if.InflationTermStructure*>iTS._thisptr.get())) def isConsistent(self, InflationTermStructure iTS): return self._thisptr.get().isConsistent( - deref(iTS._thisptr)) + deref(<_if.InflationTermStructure*>iTS._thisptr.get()) + ) cdef class MultiplicativePriceSeasonality(Seasonality): @@ -92,4 +94,5 @@ cdef class MultiplicativePriceSeasonality(Seasonality): def isConsistent(self, InflationTermStructure iTS): return self._thisptr.get().isConsistent( - deref(iTS._thisptr)) + deref(<_if.InflationTermStructure*>iTS._thisptr.get()) + ) diff --git a/quantlib/termstructures/inflation_term_structure.pxd b/quantlib/termstructures/inflation_term_structure.pxd index 02b985677..024b9e94f 100644 --- a/quantlib/termstructures/inflation_term_structure.pxd +++ b/quantlib/termstructures/inflation_term_structure.pxd @@ -1,8 +1,7 @@ -cimport quantlib.termstructures._inflation_term_structure as _its -from quantlib.ext cimport shared_ptr +from ..termstructure cimport TermStructure -cdef class InflationTermStructure: - cdef shared_ptr[_its.InflationTermStructure] _thisptr +cdef class InflationTermStructure(TermStructure): + pass cdef class ZeroInflationTermStructure(InflationTermStructure): pass diff --git a/quantlib/termstructures/inflation_term_structure.pyx b/quantlib/termstructures/inflation_term_structure.pyx index e2d47f9bd..d45af4a33 100644 --- a/quantlib/termstructures/inflation_term_structure.pyx +++ b/quantlib/termstructures/inflation_term_structure.pyx @@ -14,45 +14,23 @@ from quantlib.time.date cimport Date, Period, date_from_qldate, period_from_qlpe from libcpp.vector cimport vector from cython.operator cimport dereference as deref -from quantlib.ext cimport static_pointer_cast -cimport quantlib.time._daycounter as _dc -from quantlib.time.daycounter cimport DayCounter +from quantlib.time._period cimport Days -from quantlib.time._period cimport Frequency, Days -from quantlib.time.calendar cimport Calendar - -from quantlib.termstructures.yield_term_structure cimport YieldTermStructure - -cimport quantlib.termstructures.yields._flat_forward as _ff -cimport quantlib._interest_rate as _ir cimport quantlib.termstructures._inflation_term_structure as _if -cimport quantlib.termstructures.inflation._seasonality as _se - -from quantlib.termstructures.inflation.seasonality cimport Seasonality -cdef class InflationTermStructure: +cdef class InflationTermStructure(TermStructure): """Abstract Base Class. """ - property max_date: - def __get__(self): - cdef _date.Date max_date = self._thisptr.get().maxDate() - return date_from_qldate(max_date) - - @property - def reference_date(self): - cdef _date.Date reference_date = self._thisptr.get().referenceDate() - return date_from_qldate(reference_date) - @property def base_date(self): - cdef _date.Date base_date = self._thisptr.get().baseDate() + cdef _date.Date base_date = (<_if.InflationTermStructure*>self._thisptr.get()).baseDate() return date_from_qldate(base_date) @property def base_rate(self): - return self._thisptr.get().baseRate() + return (<_if.InflationTermStructure*>self._thisptr.get()).baseRate() cdef class ZeroInflationTermStructure(InflationTermStructure): diff --git a/quantlib/termstructures/vol_term_structure.pxd b/quantlib/termstructures/vol_term_structure.pxd index 56ab8605c..87124719b 100644 --- a/quantlib/termstructures/vol_term_structure.pxd +++ b/quantlib/termstructures/vol_term_structure.pxd @@ -1,7 +1,5 @@ -from libcpp cimport bool as cbool -from quantlib.ext cimport shared_ptr +from ..termstructure cimport TermStructure from . cimport _vol_term_structure as _vts -cdef class VolatilityTermStructure: - cdef shared_ptr[_vts.VolatilityTermStructure] _thisptr - cdef _vts.VolatilityTermStructure* as_ptr(self) nogil +cdef class VolatilityTermStructure(TermStructure): + cdef _vts.VolatilityTermStructure* as_vol_ts(self) noexcept nogil diff --git a/quantlib/termstructures/vol_term_structure.pyx b/quantlib/termstructures/vol_term_structure.pyx index fdf24a9b8..e7e03c301 100644 --- a/quantlib/termstructures/vol_term_structure.pyx +++ b/quantlib/termstructures/vol_term_structure.pyx @@ -1,40 +1,21 @@ from libcpp cimport bool from cython.operator cimport dereference as deref from quantlib.time.date cimport date_from_qldate -from quantlib.time.calendar cimport Calendar -from quantlib.time.date cimport Date, Period -cimport quantlib.time._calendar as _calendar +from quantlib.time.date cimport Period -cdef class VolatilityTermStructure: +cdef class VolatilityTermStructure(TermStructure): - cdef inline _vts.VolatilityTermStructure* as_ptr(self) nogil: - return self._thisptr.get() - - def time_from_reference(self, Date date not None): - return self.as_ptr().timeFromReference(date._thisptr) - - @property - def reference_date(self): - return date_from_qldate(self.as_ptr().referenceDate()) - - @property - def calendar(self): - cdef Calendar instance = Calendar.__new__(Calendar) - instance._thisptr = self.as_ptr().calendar() - return instance - - @property - def settlement_days(self): - return self.as_ptr().settlementDays() + cdef inline _vts.VolatilityTermStructure* as_vol_ts(self) noexcept nogil: + return <_vts.VolatilityTermStructure*>self._thisptr.get() def option_date_from_tenor(self, Period period not None): return date_from_qldate( - self.as_ptr().optionDateFromTenor(deref(period._thisptr))) + self.as_vol_ts().optionDateFromTenor(deref(period._thisptr))) @property def extrapolation(self): - return self.as_ptr().allowsExtrapolation() + return self.as_vol_ts().allowsExtrapolation() @extrapolation.setter def extrapolation(self, bool b): - self.as_ptr().enableExtrapolation(b) + self.as_vol_ts().enableExtrapolation(b) diff --git a/quantlib/termstructures/volatility/api.py b/quantlib/termstructures/volatility/api.py index 9d7ad1526..5ec5656d7 100644 --- a/quantlib/termstructures/volatility/api.py +++ b/quantlib/termstructures/volatility/api.py @@ -4,4 +4,6 @@ from .volatilitytype import VolatilityType from .swaption.swaption_vol_matrix import SwaptionVolatilityMatrix from .swaption.swaption_constant_vol import ConstantSwaptionVolatility -from quantlib.handle import HandleSwaptionVolatilityStructure, HandleBlackVolTermStructure, HandleOptionletVolatilityStructure +from quantlib.handle import ( + HandleSwaptionVolatilityStructure, HandleBlackVolTermStructure, HandleOptionletVolatilityStructure, + RelinkableHandleSwaptionVolatilityStructure, RelinkableHandleBlackVolTermStructure, RelinkableHandleOptionletVolatilityStructure) diff --git a/quantlib/termstructures/yields/_flat_forward.pxd b/quantlib/termstructures/yields/_flat_forward.pxd index 049867e7f..28d032af3 100644 --- a/quantlib/termstructures/yields/_flat_forward.pxd +++ b/quantlib/termstructures/yields/_flat_forward.pxd @@ -11,7 +11,7 @@ from quantlib.types cimport * from libcpp cimport bool from libcpp.vector cimport vector -from quantlib.handle cimport Handle +from quantlib._handle cimport Handle from quantlib.time._calendar cimport Calendar from quantlib.time._date cimport Date from quantlib.time._daycounter cimport DayCounter diff --git a/quantlib/termstructures/yields/_implied_term_structure.pxd b/quantlib/termstructures/yields/_implied_term_structure.pxd index e8b3f8c4e..26798a42c 100644 --- a/quantlib/termstructures/yields/_implied_term_structure.pxd +++ b/quantlib/termstructures/yields/_implied_term_structure.pxd @@ -1,8 +1,8 @@ -from quantlib.handle cimport Handle +from quantlib._handle cimport Handle from quantlib.time._date cimport Date from .._yield_term_structure cimport YieldTermStructure -cdef extern from 'ql/termstructures/yield/impliedtermstructure.hpp' namespace 'QuantLib': +cdef extern from 'ql/termstructures/yield/impliedtermstructure.hpp' namespace 'QuantLib' nogil: cdef cppclass ImpliedTermStructure(YieldTermStructure): ImpliedTermStructure(const Handle[YieldTermStructure]&, const Date& referenceDate) diff --git a/quantlib/termstructures/yields/_piecewise_zerospreaded_termstructure.pxd b/quantlib/termstructures/yields/_piecewise_zerospreaded_termstructure.pxd index 00b7bedba..c17538066 100644 --- a/quantlib/termstructures/yields/_piecewise_zerospreaded_termstructure.pxd +++ b/quantlib/termstructures/yields/_piecewise_zerospreaded_termstructure.pxd @@ -1,5 +1,5 @@ from libcpp.vector cimport vector -from quantlib.handle cimport Handle +from quantlib._handle cimport Handle from quantlib.time._date cimport Date from quantlib.time._daycounter cimport DayCounter from quantlib.time.frequency cimport Frequency @@ -9,7 +9,7 @@ from quantlib._quote cimport Quote from quantlib.math._interpolations cimport Linear from quantlib.compounding cimport Compounding -cdef extern from 'ql/termstructures/yield/piecewisezerospreadedtermstructure.hpp' namespace 'QuantLib': +cdef extern from 'ql/termstructures/yield/piecewisezerospreadedtermstructure.hpp' namespace 'QuantLib' nogil: cdef cppclass InterpolatedPiecewiseZeroSpreadedTermStructure[I](YieldTermStructure): InterpolatedPiecewiseZeroSpreadedTermStructure( const Handle[YieldTermStructure]&, diff --git a/quantlib/termstructures/yields/_rate_helpers.pxd b/quantlib/termstructures/yields/_rate_helpers.pxd index 4ad4b6716..5aa8838b1 100644 --- a/quantlib/termstructures/yields/_rate_helpers.pxd +++ b/quantlib/termstructures/yields/_rate_helpers.pxd @@ -11,7 +11,7 @@ include '../../types.pxi' from libcpp cimport bool -from quantlib.handle cimport Handle +from quantlib._handle cimport Handle from quantlib.ext cimport shared_ptr from quantlib._quote cimport Quote from quantlib.time._calendar cimport BusinessDayConvention, Calendar diff --git a/quantlib/termstructures/yields/_zero_spreaded_term_structure.pxd b/quantlib/termstructures/yields/_zero_spreaded_term_structure.pxd index 251f6095a..8a48723cd 100644 --- a/quantlib/termstructures/yields/_zero_spreaded_term_structure.pxd +++ b/quantlib/termstructures/yields/_zero_spreaded_term_structure.pxd @@ -1,5 +1,5 @@ from libcpp.vector cimport vector -from quantlib.handle cimport Handle +from quantlib._handle cimport Handle from quantlib.time._date cimport Date from quantlib.time._daycounter cimport DayCounter from quantlib.time.frequency cimport Frequency @@ -9,7 +9,7 @@ from quantlib._quote cimport Quote from quantlib.math._interpolations cimport Linear from quantlib.compounding cimport Compounding -cdef extern from 'ql/termstructures/yield/zerospreadedtermstructure.hpp' namespace 'QuantLib': +cdef extern from 'ql/termstructures/yield/zerospreadedtermstructure.hpp' namespace 'QuantLib' nogil: cdef cppclass ZeroSpreadedTermStructure(YieldTermStructure): ZeroSpreadedTermStructure( const Handle[YieldTermStructure]&,