diff options
| author | Guillaume Horel <guillaume.horel@serenitascapital.com> | 2016-06-30 15:03:44 -0400 |
|---|---|---|
| committer | Guillaume Horel <guillaume.horel@serenitascapital.com> | 2016-06-30 15:03:44 -0400 |
| commit | ed83c435dcb32b5afd7f58a0fde72b41dc0d09e6 (patch) | |
| tree | 8d452dff2ac51a02eea4df3960b61d7f45f3e8d6 | |
| parent | f1bed268cfd976966b6bab376a59c52dfd0216fa (diff) | |
| download | pyisda-ed83c435dcb32b5afd7f58a0fde72b41dc0d09e6.tar.gz | |
legs functions
| -rw-r--r-- | curve.pxd | 52 | ||||
| -rw-r--r-- | curve.pyx | 58 | ||||
| -rw-r--r-- | legs.pxd | 94 | ||||
| -rw-r--r-- | legs.pyx | 67 |
4 files changed, 261 insertions, 10 deletions
@@ -1,4 +1,7 @@ +from cdsone cimport TStubMethod + cdef extern from "isda/zerocurve.h": + ctypedef int TBoolean ctypedef long int TDate @@ -20,6 +23,48 @@ cdef extern from "isda/zerocurve.h": long floatSwapDCC, long badDayConv, char* holidayFile) +cdef extern from "isda/cds.h": + + TCurve* JpmcdsCleanSpreadCurve( + # Risk starts at the end of today + TDate today, + # Interest rate discount curve - assumes flat forward interpolation + TCurve *discCurve, + # Effective date of the benchmark CDS + TDate startDate, + # Step in date of the benchmark CDS + TDate stepinDate, + # Date when payment should be make + TDate cashSettleDate, + # Number of benchmark dates + long nbDate, + # Dates when protection ends for each benchmark (end of day). + # Array of size nbDate + TDate *endDates, + # Coupon rates for each benchmark instrument. Array of size nbDate + double *couponRates, + # Flags to denote that we include particular benchmarks. This makes it + # easy for the user to include or exclude benchmarks on a one-by-one + # basis. Can be NULL if all are included. Otherwise an array of size + # nbDate. + TBoolean *includes, + # Recovery rate in case of default + double recoveryRate, + # Should accrued interest be paid on default. Usually set to TRUE + TBoolean payAccOnDefault, + # Interval between coupon payments. Can be NULL when 3M is assumed + TDateInterval *couponInterval, + # Day count convention for coupon payment. Normal is ACT_360 + long paymentDcc, + # If the startDate and endDate are not on cycle, then this parameter + # determines location of coupon dates. */ + TStubMethod *stubType, + # Bad day convention for adjusting coupon payment dates. */ + long badDayConv, + # Calendar used when adjusting coupon dates. Can be NULL which equals + # a calendar with no holidays and including weekends. */ + char *calendar + ) cdef extern from "isda/tcurve.h": void JpmcdsFreeTCurve(TCurve* curve) @@ -27,7 +72,12 @@ cdef extern from "isda/tcurve.h": cdef extern from "isda/cxzerocurve.h": double JpmcdsZeroPrice(TCurve* curve, TDate date) -cdef class ZeroCurve: +cdef class Curve: cdef TCurve* _thisptr + +cdef class ZeroCurve(Curve): cdef TDate* _dates cdef size_t _ninstr + +cdef class SpreadCurve(Curve): + pass @@ -1,11 +1,10 @@ from cpython cimport datetime from libc.stdlib cimport malloc, free -from pyisda.zerocurve cimport JpmcdsBuildIRZeroCurve, JpmcdsZeroPrice -from pyisda.yearfrac cimport dcc -from pyisda.date cimport (JpmcdsStringToDateInterval, pydate_to_TDate, - JpmcdsDateIntervalToFreq, JpmcdsDateFwdThenAdjust, TDate_to_pydate, - JpmcdsDateFromBusDaysOffset) - +from curve cimport JpmcdsBuildIRZeroCurve, JpmcdsZeroPrice, +from date cimport (JpmcdsStringToDateInterval, pydate_to_TDate, dcc, + JpmcdsDateIntervalToFreq, JpmcdsDateFwdThenAdjust, TDate_to_pydate, + JpmcdsDateFromBusDaysOffset) +from cdsone cimport JpmcdsStringToStubMethod, TStubMethod cdef int SUCCESS = 0 cpdef public enum BadDay: @@ -14,7 +13,12 @@ cpdef public enum BadDay: NONE = <long>'N' MODIFIED = <long>'M' -cdef class ZeroCurve: +cdef class Curve: + def __dealloc__(self): + if self._thisptr is not NULL: + JpmcdsFreeTCurve(self._thisptr) + +cdef class ZeroCurve(Curve): def __init__(self, date, str types, list periods, double[:] rates, @@ -68,8 +72,6 @@ cdef class ZeroCurve: ) def __dealloc__(self): - if self._thisptr is not NULL: - JpmcdsFreeTCurve(self._thisptr) if self._dates is not NULL: free(self._dates) @@ -82,3 +84,41 @@ cdef class ZeroCurve: def list_dates(self): cdef size_t i return [TDate_to_pydate(self._dates[i]) for i in range(self._ninstr)] + +cdef class SpreadCurve(Curve): + + def __init__(self, today, ZeroCurve zc, start_date, step_in_date, cash_settle_date, + list end_dates, double[:] coupon_rates, double recovery_rate, + TBoolean pay_accrued_on_default): + + cdef today_c = pydate_to_TDate(today) + cdef step_in_date_c = pydate_to_TDate(step_in_date) + cdef cash_settle_date_c = pydate_to_TDate(cash_settle_date) + cdef start_date_c = pydate_to_TDate(start_date) + cdef TDate* end_dates_c = <TDate*>malloc(len(end_dates) * sizeof(TDate)) + + cdef size_t i + + for i, d in enumerate(end_dates): + end_dates_c[i] = pydate_to_TDate(end_dates) + cdef TStubMethod stub_type + + if JpmcdsStringToStubMethod(b"f/s", &stub_type) != 0: + raise ValueError("can't convert stub") + + self._thisptr = JpmcdsCleanSpreadCurve(today_c, + zc._thisptr, + start_date_c, + step_in_date_c, + cash_settle_date, + len(end_dates), + end_dates_c, + &coupon_rates[0], + NULL, + recovery_rate, + pay_accrued_on_default, + NULL, + dcc('ACT/360'), + &stub_type, + <long>'M', + NULL) diff --git a/legs.pxd b/legs.pxd new file mode 100644 index 0000000..0b1ded3 --- /dev/null +++ b/legs.pxd @@ -0,0 +1,94 @@ +from date cimport TDate, TDateInterval +from cdsone cimport TStubMethod +from curve cimport TCurve + +ctypedef int TBoolean + +cdef extern from "isda/cx.h": + ctypedef struct TContingentLeg: + pass + + ctypedef struct TFeeLeg: + pass + +cdef extern from "isda/bastypes.h": + ctypedef struct TCashFlow: + TDate fDate + double fAmount + + ctypedef struct TCashFlowList: + int fNumItems + TCashFlow *fArray + +cdef extern from "isda/cds.h": + + cdef TContingentLeg* JpmcdsCdsContingentLegMake( + # Date when protection begins. Either at start or end of day (depends + # on protectStart) + TDate startDate, + # Date when protection ends (end of day) + TDate endDate, + # Notional value protected + double notional, + # Should protection include the start date + TBoolean protectStart) + + cdef TFeeLeg* JpmcdsCdsFeeLegMake( + # Date when protection begins. Either at start or end of day (depends + # on protectStart) + TDate startDate, + # Date when protection ends (end of day) + TDate endDate, + # Should accrued interest be paid on default. Usually set to TRUE + TBoolean payAccOnDefault, + # Interval between coupon payments. Can be NULL when 3M is assumed + TDateInterval *couponInterval, + # If the startDate and endDate are not on cycle, then this parameter + # determines location of coupon dates. + TStubMethod *stubType, + # Notional value protected + double notional, + # Fixed coupon rate (a.k.a. spread) for the fee leg + double couponRate, + # Day count convention for coupon payment. Normal is ACT_360 + long paymentDcc, + # Bad day convention for adjusting coupon payment dates. + long badDayConv, + # Calendar used when adjusting coupon dates. Can be NULL which equals + # a calendar with no holidays and including weekends. + char *calendar, + # Should protection include the start date */ + TBoolean protectStart) + + + +cdef extern from "isda/contingentleg.h": + cdef int JpmcdsContingentLegPV(TContingentLeg *cl, # Contingent leg + TDate today, # No observations before today + TDate valueDate, # Value date for discounting + TDate stepinDate, # Step-in date + TCurve *discountCurve, # Risk-free curve + TCurve *spreadCurve, # Spread curve + double recoveryRate, # Recovery rate + double *pv) + +cdef extern from "isda/feeleg.h": + cdef int JpmcdsFeeLegPV(TFeeLeg *fl, + TDate today, + TDate stepinDate, + TDate valueDate, + TCurve *discCurve, + TCurve *spreadCurve, + TBoolean payAccruedAtStart, + double *pv) + + cdef TCashFlowList* JpmcdsFeeLegFlows(TFeeLeg *fl) + + cdef void JpmcdsFeeLegFree(TFeeLeg *p) + +cdef class ContingentLeg: + cdef TContingentLeg* _thisptr + + +cdef class FeeLeg: + cdef TFeeLeg* _thisptr diff --git a/legs.pyx b/legs.pyx new file mode 100644 index 0000000..5db39d3 --- /dev/null +++ b/legs.pyx @@ -0,0 +1,67 @@ +from legs cimport (JpmcdsCdsContingentLegMake, + JpmcdsCdsFeeLegMake, JpmcdsFeeLegFlows, TBoolean) +from libc.stdlib cimport free +from date cimport pydate_to_TDate, TDate_to_pydate, dcc +from cdsone cimport JpmcdsStringToStubMethod, TStubMethod +from curve cimport ZeroCurve, SpreadCurve + +cdef class ContingentLeg: + + def __cinit__(self, start_date, end_date, double notional, + TBoolean protect_start = True): + + self._thisptr = JpmcdsCdsContingentLegMake(pydate_to_TDate(start_date), + pydate_to_TDate(end_date), + notional, + protect_start) + def __dealloc__(self): + if self._thisptr is not NULL: + free(self._thisptr) + +cdef class FeeLeg: + + def __cinit__(self, start_date, end_date, TBoolean pay_accrued_on_default, + double notional, double coupon_rate, str payment_dcc = 'ACT/360', + TBoolean protect_start = True): + + cdef TStubMethod stub_type + + if JpmcdsStringToStubMethod(b"f/s", &stub_type) != 0: + raise ValueError("can't convert stub") + + self._thisptr = JpmcdsCdsFeeLegMake(pydate_to_TDate(start_date), + pydate_to_TDate(end_date), + pay_accrued_on_default, + NULL, + &stub_type, + notional, + coupon_rate, + dcc(payment_dcc), + <long>'M', + NULL, + protect_start) + @property + def cashflows(self): + cdef TCashFlowList* cfl = JpmcdsFeeLegFlows(self._thisptr) + cdef TCashFlow cf + result = [] + for i in range(cf.fNumItems): + cf = cfl.fArray[i] + result.append((TDate_to_pydate(cf.fDate), cf.fAmount)) + return result + + def pv(self, today, step_in_date, value_date, ZeroCurve zc, SpreadCurve sc, + TBoolean pay_accrued_at_start): + cdef today_c = pydate_to_TDate(today) + cdef step_in_date_c = pydate_to_TDate(step_in_date) + cdef value_date_c = pydate_to_TDate(value_date) + cdef double pv + if JpmcdsFeeLegPV(self._thisptr, today, step_in_date, value_date, + zc._thisptr, sc._thisptr, pay_accrued_at_start, &pv) == 0: + return pv + else: + raise ValueError + + def __dealloc__(self): + if self._thisptr is not NULL: + JpmcdsFeeLegFree(self._thisptr) |
