Skip to content
Merged

Legs #346

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions quantlib/_cashflow.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ from libcpp.vector cimport vector
from quantlib.handle cimport shared_ptr, optional
from quantlib.time._date cimport Date

cdef extern from 'ql/event.hpp' namespace 'QuantLib':
cdef extern from 'ql/event.hpp' namespace 'QuantLib' nogil:
cdef cppclass Event:
Date date()
bool hasOccurred(Date& refDate,
optional[bool] includeRefDate)

cdef extern from 'ql/cashflow.hpp' namespace 'QuantLib':
cdef extern from 'ql/cashflow.hpp' namespace 'QuantLib' nogil:
cdef cppclass CashFlow(Event):
Real amount() except +

ctypedef vector[shared_ptr[CashFlow]] Leg

cdef extern from 'ql/cashflows/simplecashflow.hpp' namespace 'QuantLib':
cdef extern from 'ql/cashflows/simplecashflow.hpp' namespace 'QuantLib' nogil:
cdef cppclass SimpleCashFlow(CashFlow):
SimpleCashFlow(Real amount,
Date& date)
2 changes: 1 addition & 1 deletion quantlib/_instrument.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ from quantlib.time._date cimport Date
from libcpp.string cimport string
from libcpp cimport bool

cdef extern from 'ql/instrument.hpp' namespace 'QuantLib':
cdef extern from 'ql/instrument.hpp' namespace 'QuantLib' nogil:
cdef cppclass Instrument:
Instrument()
bool isExpired()
Expand Down
2 changes: 1 addition & 1 deletion quantlib/cashflows/_coupon.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ from quantlib.time._daycounter cimport DayCounter
from quantlib._cashflow cimport CashFlow
from quantlib._interest_rate cimport InterestRate

cdef extern from 'ql/cashflows/coupon.hpp' namespace 'QuantLib':
cdef extern from 'ql/cashflows/coupon.hpp' namespace 'QuantLib' nogil:
cdef cppclass Coupon(CashFlow):
Coupon(const Date& paymentDate,
Real nominal,
Expand Down
2 changes: 1 addition & 1 deletion quantlib/cashflows/_floating_rate_coupon.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ from quantlib.cashflows._coupon cimport Coupon
from ._coupon_pricer cimport FloatingRateCouponPricer
from quantlib.indexes._interest_rate_index cimport InterestRateIndex

cdef extern from 'ql/cashflows/floatingratecoupon.hpp' namespace 'QuantLib':
cdef extern from 'ql/cashflows/floatingratecoupon.hpp' namespace 'QuantLib' nogil:
cdef cppclass FloatingRateCoupon(Coupon):
FloatingRateCoupon(const Date& paymentDate,
Real nominal,
Expand Down
29 changes: 27 additions & 2 deletions quantlib/cashflows/_overnight_indexed_coupon.pxd
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
from quantlib.types cimport Natural, Rate, Real, Spread, Time
from quantlib.types cimport Integer, Natural, Rate, Real, Spread, Time

from libcpp cimport bool
from libcpp.vector cimport vector
from quantlib.handle cimport shared_ptr
from quantlib.time._date cimport Date
from quantlib.time._daycounter cimport DayCounter
from quantlib.time._schedule cimport Schedule
from quantlib.time._calendar cimport Calendar
from quantlib.time.businessdayconvention cimport BusinessDayConvention

from quantlib.indexes._ibor_index cimport OvernightIndex
from ._floating_rate_coupon cimport FloatingRateCoupon
from .rateaveraging cimport RateAveraging
from .._cashflow cimport Leg

cdef extern from 'ql/cashflows/overnightindexedcoupon.hpp' namespace 'QuantLib':
cdef extern from 'ql/cashflows/overnightindexedcoupon.hpp' namespace 'QuantLib' nogil:
cdef cppclass OvernightIndexedCoupon(FloatingRateCoupon):
OvernightIndexedCoupon(const Date& paymentDate,
Real nominal,
Expand All @@ -34,3 +39,23 @@ cdef extern from 'ql/cashflows/overnightindexedcoupon.hpp' namespace 'QuantLib':
RateAveraging averagingMethod()
Natural lockoutDays()
bool applyObservationShift()

cdef cppclass OvernightLeg:
OvernightLeg(Schedule schedule, shared_ptr[OvernightIndex] overnightIndex)
OvernightLeg& withNotionals(Real notional)
OvernightLeg& withPaymentDayCounter(DayCounter dc)
OvernightLeg& withPaymentAdjustment(BusinessDayConvention)
OvernightLeg& withPaymentCalendar(Calendar)
OvernightLeg& withPaymentLag(Integer Lag)
OvernightLeg& withSpreads(Real spread)
OvernightLeg& withObservationShift(bool)
OvernightLeg& withLookbackDays(Natural)
OvernightLeg& withLockoutDays(Natural)
Leg operator() const

cdef extern from 'ql/cashflows/overnightindexedcoupon.hpp':
# this allows to declare the cast operator as raising exceptions
"""
#define to_leg(x) static_cast<QuantLib::Leg>(x)
"""
cdef Leg to_leg(OvernightLeg) except +
5 changes: 3 additions & 2 deletions quantlib/cashflows/api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .overnight_indexed_coupon import OvernightIndexedCoupon
from .overnight_indexed_coupon import OvernightIndexedCoupon, OvernightLeg
from .cms_coupon import CmsCoupon
from .ibor_coupon import IborCoupon
from .fixed_rate_coupon import FixedRateCoupon
from .fixed_rate_coupon import FixedRateCoupon, FixedRateLeg
from ..cashflow import SimpleCashFlow, Leg
4 changes: 3 additions & 1 deletion quantlib/cashflows/fixed_rate_coupon.pyx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from quantlib.types cimport Rate, Real
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.handle cimport shared_ptr
from quantlib.time.businessdayconvention cimport BusinessDayConvention
Expand All @@ -11,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 Leg as QlLeg
cimport quantlib._interest_rate as _ir

cdef class FixedRateCoupon(Coupon):
Expand Down Expand Up @@ -60,7 +62,7 @@ cdef class FixedRateLeg(Leg):
return self

def __call__(self):
self._thisptr = _frc.to_leg(deref(self.frl))
self._thisptr = move[QlLeg](_frc.to_leg(deref(self.frl)))
return self

def __iter__(self):
Expand Down
3 changes: 2 additions & 1 deletion quantlib/cashflows/overnight_indexed_coupon.pxd
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from .floating_rate_coupon cimport FloatingRateCoupon
from quantlib.cashflow cimport Leg
from . cimport _overnight_indexed_coupon as _oic

cdef class OvernightIndexedCoupon(FloatingRateCoupon):
pass

cdef class OvernightLeg(Leg):
pass
cdef _oic.OvernightLeg* leg
56 changes: 55 additions & 1 deletion quantlib/cashflows/overnight_indexed_coupon.pyx
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
from quantlib.types cimport Natural, Real, Spread
from quantlib.types cimport Integer, Natural, 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.handle cimport make_shared, shared_ptr, static_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
from quantlib.time.calendar cimport Calendar
from quantlib.time.schedule cimport Schedule
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
from . cimport _overnight_indexed_coupon as _oic
from .._cashflow cimport Leg as QlLeg

cdef class OvernightIndexedCoupon(FloatingRateCoupon):

Expand Down Expand Up @@ -89,3 +94,52 @@ cdef class OvernightLeg(Leg):
oic._thisptr = deref(it)
yield oic
preinc(it)

def __init__(self, Schedule schedule, OvernightIndex index):
self.leg = new _oic.OvernightLeg(schedule._thisptr,
static_pointer_cast[_ii.OvernightIndex](index._thisptr))

def __dealloc__(self):
if self.leg is not NULL:
del self.leg
self.leg = NULL

def with_notionals(self, Real notional):
self.leg.withNotionals(notional)
return self

def with_payment_day_counter(self, DayCounter dc):
self.leg.withPaymentDayCounter(deref(dc._thisptr))
return self

def with_payment_adjustment(self, BusinessDayConvention bdc):
self.withPaymentAdjustment(bdc)
return self

def with_payment_calendar(self, Calendar cal):
self.leg.withPaymentCalendar(cal._thisptr)
return self

def with_spreads(self, Spread spread):
self.leg.withSpreads(spread)
return self

def with_observation_shift(self, bool apply_observation_shift=True):
self.leg.withObservationShift(apply_observation_shift)
return self

def with_lookback_days(self, Natural lookback_days):
self.leg.withLookbackDays(lookback_days)
return self

def with_lockout_days(self, Natural lockout_days):
self.leg.withLockoutDays(lockout_days)
return self

def with_payment_lag(self, Integer lag):
self.leg.withPaymentLag(lag)
return self

def __call__(self):
self._thisptr = move[QlLeg](_oic.to_leg(deref(self.leg)))
return self
16 changes: 16 additions & 0 deletions quantlib/instruments/_make_ois.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,29 @@ cdef extern from 'ql/instruments/makeois.hpp' namespace 'QuantLib':
MakeOIS& withEffectiveDate(const Date&)
MakeOIS& withTerminationDate(const Date&)
MakeOIS& withRule(DateGeneration r)
MakeOIS& withFixedLegRule(DateGeneration r)
MakeOIS& withOvernightLegRule(DateGeneration r)

MakeOIS& withPaymentFrequency(Frequency f)
MakeOIS& withFixedLegPaymentFrequency(Frequency f)
MakeOIS& withOvernightLegPaymentFrequency(Frequency f)
MakeOIS& withPaymentAdjustment(BusinessDayConvention convention)
MakeOIS& withPaymentLag(Natural lag)
MakeOIS& withPaymentCalendar(const Calendar& cal)
MakeOIS& withCalendar(const Calendar& cal)
MakeOIS& withFixedLegCalendar(const Calendar& cal)
MakeOIS& withOvernightLegCalendar(const Calendar& cal)

MakeOIS& withConvention(BusinessDayConvention bdc)
MakeOIS& withFixedLegConvention(BusinessDayConvention bdc)
MakeOIS& withOvernightLegConvention(BusinessDayConvention bdc)
MakeOIS& withTerminationDateConvention(BusinessDayConvention bdc)
MakeOIS& withFixedLegTerminationDateConvention(BusinessDayConvention bdc)
MakeOIS& withOvernightLegTerminationDateConvention(BusinessDayConvention bdc)
MakeOIS& withEndOfMonth(bool flag) # = true);
MakeOIS& withFixedLegEndOfMonth(bool flag) # = true);
MakeOIS& withOvernightLegEndOfMonth(bool flag) # = true);


MakeOIS& withFixedLegDayCount(const DayCounter& dc)

Expand Down
12 changes: 6 additions & 6 deletions quantlib/instruments/_swap.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
FOR A PARTICULAR PURPOSE. See the license for more details.
"""

include '../types.pxi'

from quantlib.types cimport DiscountFactor, Real, Size
from libcpp.vector cimport vector
from libcpp cimport bool

Expand All @@ -22,11 +21,11 @@ from quantlib._cashflow cimport Leg

cdef extern from 'ql/instruments/swap.hpp' namespace 'QuantLib' nogil:
cdef cppclass Swap(Instrument):
## Swap(Leg& firstLeg,
## Leg& secondLeg)
Swap(Leg& firstLeg,
Leg& secondLeg)

## Swap(vector[Leg]& legs,
## vector[bool]& payer)
Swap(vector[Leg]& legs,
vector[bool]& payer)
bool isExpired()
Size numberOfLegs()
Date startDate()
Expand All @@ -37,3 +36,4 @@ cdef extern from 'ql/instruments/swap.hpp' namespace 'QuantLib' nogil:
DiscountFactor endDiscounts(Size j) except +
DiscountFactor npvDateDiscount() except +
Leg& leg(Size j) except +
const vector[Leg]& legs()
8 changes: 8 additions & 0 deletions quantlib/instruments/make_ois.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ cdef class MakeOIS:
self._thisptr.withPaymentFrequency(f)
return self

def with_fixed_leg_payment_frequency(self, Frequency f):
self._thisptr.withFixedLegPaymentFrequency(f)
return self

def with_overnight_leg_payment_frequency(self, Frequency f):
self._thisptr.withOvernightLegPaymentFrequency(f)
return self

def with_payment_adjustment(self, BusinessDayConvention convention):
self._thisptr.withPaymentAdjustment(convention)
return self
Expand Down
48 changes: 17 additions & 31 deletions quantlib/instruments/swap.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ from quantlib.types cimport Size
from quantlib.cashflow cimport Leg
cimport quantlib.time._date as _date
from quantlib.time.date cimport date_from_qldate
from quantlib._cashflow cimport Leg as QlLeg

from . cimport _swap

cdef inline _swap.Swap* get_swap(Swap swap):
cdef inline _swap.Swap* get_swap(Swap swap) noexcept:
""" Utility function to extract a properly casted Swap pointer out of the
internal _thisptr attribute of the Instrument base class. """

Expand All @@ -27,35 +29,11 @@ cdef class Swap(Instrument):
Payer = Type.Payer
Receiver = Type.Receiver

def __init__(self):
raise NotImplementedError('Generic swap not yet implemented. \
Please use child classes.')

## def __init__(self, Leg firstLeg,
## Leg secondLeg):

## cdef _cf.Leg* leg1 = firstLeg._thisptr.get()
## cdef _cf.Leg* leg2 = secondLeg._thisptr.get()

## self._thisptr = new shared_ptr[_instrument.Instrument](\
## new _swap.Swap(deref(leg1),
## deref(leg2)))


## def __init__(self, vector[Leg] legs,
## vector[bool] payer):

## cdef vector[_cf.Leg]* _legs = new vector[_cf.Leg](len(legs))
## for l in legs:
## _legs.push_back(l)

## cdef vector[bool]* _payer = new vector[bool](len(payer))
## for p in payer:
## _payer.push_back(p)
def __init__(self, Leg first_leg, Leg second_leg):
""" The cash flows belonging to the first leg are paid;
the ones belonging to the second leg are received"""

## self._thisptr = new shared_ptr[_instrument.Instrument](\
## new _swap.Swap(_legs, payer)
## )
self._thisptr.reset(new _swap.Swap(first_leg._thisptr, second_leg._thisptr))

property start_date:
def __get__(self):
Expand Down Expand Up @@ -84,10 +62,18 @@ cdef class Swap(Instrument):

def leg(self, int i):
cdef Leg leg = Leg.__new__(Leg)
leg._thisptr = get_swap(self).leg(i)
cdef _swap.Swap* swap = <_swap.Swap*>self._thisptr.get()
if 0 <= i < swap.numberOfLegs():
leg._thisptr = swap.legs()[i]
else:
raise IndexError(f"leg #{i} doesn't exist")
return leg

def __getitem__(self, int i):
cdef Leg leg = Leg.__new__(Leg)
leg._thisptr = get_swap(self).leg(i)
cdef _swap.Swap* swap = <_swap.Swap*>self._thisptr.get()
if 0 <= i < swap.numberOfLegs():
leg._thisptr = swap.legs()[i]
else:
raise IndexError(f"leg #{i} doesn't exist")
return leg