summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--curve.pxd52
-rw-r--r--curve.pyx58
-rw-r--r--legs.pxd94
-rw-r--r--legs.pyx67
4 files changed, 261 insertions, 10 deletions
diff --git a/curve.pxd b/curve.pxd
index d652ca0..b365b5a 100644
--- a/curve.pxd
+++ b/curve.pxd
@@ -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
diff --git a/curve.pyx b/curve.pyx
index a5eb2d2..88b1098 100644
--- a/curve.pyx
+++ b/curve.pyx
@@ -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)