From 10e9385b9dce32513d865f75003c0eccff75faa0 Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Tue, 12 Jul 2016 15:37:45 -0400 Subject: reorganize project --- __init__.py | 0 cdsone.pxd | 52 ---------------- cdsone.pyx | 71 ---------------------- curve.pxd | 112 ---------------------------------- curve.pyx | 172 ----------------------------------------------------- date.pxd | 45 -------------- date.pyx | 28 --------- legs.pxd | 101 ------------------------------- legs.pyx | 103 -------------------------------- pyisda/__init__.py | 0 pyisda/cdsone.pxd | 52 ++++++++++++++++ pyisda/cdsone.pyx | 71 ++++++++++++++++++++++ pyisda/curve.pxd | 112 ++++++++++++++++++++++++++++++++++ pyisda/curve.pyx | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++ pyisda/date.pxd | 45 ++++++++++++++ pyisda/date.pyx | 28 +++++++++ pyisda/legs.pxd | 101 +++++++++++++++++++++++++++++++ pyisda/legs.pyx | 103 ++++++++++++++++++++++++++++++++ setup.py | 7 ++- 19 files changed, 689 insertions(+), 686 deletions(-) delete mode 100644 __init__.py delete mode 100644 cdsone.pxd delete mode 100644 cdsone.pyx delete mode 100644 curve.pxd delete mode 100644 curve.pyx delete mode 100644 date.pxd delete mode 100644 date.pyx delete mode 100644 legs.pxd delete mode 100644 legs.pyx create mode 100644 pyisda/__init__.py create mode 100644 pyisda/cdsone.pxd create mode 100644 pyisda/cdsone.pyx create mode 100644 pyisda/curve.pxd create mode 100644 pyisda/curve.pyx create mode 100644 pyisda/date.pxd create mode 100644 pyisda/date.pyx create mode 100644 pyisda/legs.pxd create mode 100644 pyisda/legs.pyx diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/cdsone.pxd b/cdsone.pxd deleted file mode 100644 index b24d3b4..0000000 --- a/cdsone.pxd +++ /dev/null @@ -1,52 +0,0 @@ -from date cimport TDateInterval -from curve cimport TCurve - -cdef extern from "isda/stub.h": - ctypedef struct TStubMethod: - pass - - int JpmcdsStringToStubMethod(char* name, TStubMethod* stub) - -cdef extern from "isda/cdsone.h": - - ctypedef int TBoolean - - ctypedef long int TDate - - int JpmcdsCdsoneUpfrontCharge(TDate today, - TDate valueDate, - TDate benchmarkStartDate, - TDate stepinDate, - TDate startDate, - TDate endDate, - double couponRate, - TBoolean payAccruedOnDefault, - TDateInterval* dateInterval, - TStubMethod* stubType, - long accrueDCC, - long badDayConv, - char* calendar, - TCurve* discCurve, - double oneSpread, - double recoveryRate, - TBoolean payAccruedAtStart, - double* upfrontCharge) - - int JpmcdsCdsoneSpread(TDate today, - TDate valueDate, - TDate benchmarkStartDate, - TDate stepinDate, - TDate startDate, - TDate endDate, - double couponRate, - TBoolean payAccruedOnDefault, - TDateInterval* dateInterval, - TStubMethod* stubType, - long accrueDCC, - long badDayConv, - char* calendar, - TCurve* discCurve, - double upfrontCharge, - double recoveryRate, - TBoolean payAccruedAtStart, - double* oneSpread) diff --git a/cdsone.pyx b/cdsone.pyx deleted file mode 100644 index 13c517e..0000000 --- a/cdsone.pyx +++ /dev/null @@ -1,71 +0,0 @@ -from cdsone cimport (JpmcdsCdsoneUpfrontCharge, - JpmcdsCdsoneSpread, JpmcdsStringToStubMethod) -from curve cimport YieldCurve -from date cimport JpmcdsStringToDateInterval, pydate_to_TDate, dcc - -cdef int SUCCESS = 0 - -def upfront_charge(date, value_date, benchmark_start_date, stepin_date, - start_date, end_date, double coupon_rate, - YieldCurve yc, - double spread, - double recovery_rate, - TBoolean pay_accrued_at_start = True, - TBoolean pay_accrued_on_default = True): - - cdef: - TDate today = pydate_to_TDate(date) - TDate value_date_c = pydate_to_TDate(value_date) - TDate benchmark_start_date_c = pydate_to_TDate(benchmark_start_date) - TDate stepin_date_c = pydate_to_TDate(stepin_date) - TDate start_date_c = pydate_to_TDate(start_date) - TDate end_date_c = pydate_to_TDate(end_date) - double result - TStubMethod stub - TDateInterval ivl - char* routine = "upfront_charge" - - if JpmcdsStringToStubMethod(b"f/s", &stub) != SUCCESS: - raise ValueError("can't convert stub") - if JpmcdsStringToDateInterval(b"3M", routine, &ivl) != SUCCESS: - raise ValueError("can't convert to date interval") - if JpmcdsCdsoneUpfrontCharge(today, value_date_c, benchmark_start_date_c, stepin_date_c, - start_date_c, end_date_c, coupon_rate, pay_accrued_on_default, - &ivl, &stub, - dcc("ACT/360"), b'F', b"None", yc._thisptr, spread, recovery_rate, - pay_accrued_at_start, &result) == SUCCESS: - return result - else: - raise ValueError("computation failed") - -def spread_from_upfront(date, value_date, benchmark_start_date, stepin_date, - start_date, end_date, double coupon_rate, - YieldCurve yc, - double upfront, - double recovery_rate, - TBoolean pay_accrued_at_start = True, - TBoolean pay_accrued_on_default = True): - cdef: - TDate today = pydate_to_TDate(date) - TDate value_date_c = pydate_to_TDate(value_date) - TDate benchmark_start_date_c = pydate_to_TDate(benchmark_start_date) - TDate stepin_date_c = pydate_to_TDate(stepin_date) - TDate start_date_c = pydate_to_TDate(start_date) - TDate end_date_c = pydate_to_TDate(end_date) - double result - TStubMethod stub - TDateInterval ivl - char* routine = "upfront_charge" - - if JpmcdsStringToStubMethod(b"f/s", &stub) != SUCCESS: - raise ValueError("can't convert stub") - if JpmcdsStringToDateInterval(b"3M", routine, &ivl) != SUCCESS: - raise ValueError("can't convert to date interval") - if JpmcdsCdsoneSpread(today, value_date_c, benchmark_start_date_c, stepin_date_c, - start_date_c, end_date_c, coupon_rate, pay_accrued_on_default, - &ivl, &stub, - dcc("ACT/360"), b'F', b"None", yc._thisptr, upfront, recovery_rate, - pay_accrued_at_start, &result) == SUCCESS: - return result - else: - raise ValueError("computation failed") diff --git a/curve.pxd b/curve.pxd deleted file mode 100644 index 50de68f..0000000 --- a/curve.pxd +++ /dev/null @@ -1,112 +0,0 @@ -from cdsone cimport TStubMethod - -cdef extern from "isda/zerocurve.h": - ctypedef int TBoolean - - ctypedef long int TDate - - ctypedef struct TDateInterval: - pass - - TCurve* JpmcdsBuildIRZeroCurve(TDate valueDate, - char* instrNames, - TDate* dates, - double* rates, - long nInstr, - long mmDCC, - long fixedSwapFreq, - long floatSwapFreq, - long fixedSwapDCC, - long floatSwapDCC, - long badDayConv, - char* holidayFile) -cdef extern from "isda/bastypes.h": - ctypedef struct TCurve: - int fNumItems - TRatePt* fArray - TDate fBaseDate - double fBasis - long fDayCountConv - - ctypedef struct TRatePt: - TDate fDate - double fRate - -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) - TCurve* JpmcdsMakeTCurve(TDate baseDate, - TDate *dates, - double *rates, - int numPts, - double basis, - long dayCountConv); - -cdef extern from "isda/cxzerocurve.h": - double JpmcdsZeroPrice(TCurve* curve, TDate date) - -cdef extern from "isda/cfinanci.h": - int JpmcdsDiscountToRateYearFrac(double discount, # (I) Discount factor - double yearFraction, # (I) See JpmcdsDayCountFraction - double basis, # (I) Basis for the rate - double *rate); -cdef enum Basis: - CONTINUOUS = 5000 - DISCOUNT_RATE = 512 - SIMPLE_BASIS = 0 - ANNUAL_BASIS = 1 - DISCOUNT_FACTOR = -2 - -cdef class Curve: - cdef TCurve* _thisptr - -cdef class YieldCurve(Curve): - cdef TDate* _dates - cdef size_t _ninstr - -cdef class SpreadCurve(Curve): - pass - -cdef fArray_to_list(TRatePt* fArray, int fNumItems) diff --git a/curve.pyx b/curve.pyx deleted file mode 100644 index d5bb5ff..0000000 --- a/curve.pyx +++ /dev/null @@ -1,172 +0,0 @@ -from libc.stdlib cimport malloc, free -from curve cimport (JpmcdsBuildIRZeroCurve, JpmcdsZeroPrice, JpmcdsMakeTCurve, - Basis, CONTINUOUS, JpmcdsCleanSpreadCurve) -from date cimport (JpmcdsStringToDateInterval, pydate_to_TDate, dcc, - JpmcdsDateIntervalToFreq, JpmcdsDateFwdThenAdjust, TDate_to_pydate, - JpmcdsDateFromBusDaysOffset) -from date import dcc_tostring -from cdsone cimport JpmcdsStringToStubMethod, TStubMethod - -cdef int SUCCESS = 0 - -cpdef public enum BadDay: - FOLLOW = 'F' - PREVIOUS = 'P' - NONE = 'N' - MODIFIED = 'M' - -cdef class Curve: - def __dealloc__(self): - if self._thisptr is not NULL: - JpmcdsFreeTCurve(self._thisptr) - - def inspect(self): - return {'base_date': TDate_to_pydate(self._thisptr.fBaseDate), - 'basis': self._thisptr.fBasis, - 'day_count_convention': dcc_tostring(self._thisptr.fDayCountConv), - 'data': fArray_to_list(self._thisptr.fArray, self._thisptr.fNumItems)} - -cdef fArray_to_list(TRatePt* fArray, int fNumItems): - cdef size_t i - cdef list l = [] - for i in range(fNumItems): - l.append((TDate_to_pydate(fArray[i].fDate), fArray[i].fRate)) - return l - -cdef class YieldCurve(Curve): - - def __init__(self, date, str types, - list periods, double[:] rates, - str mm_dcc, str fixed_swap_period, str float_swap_period, - str fixed_swap_dcc, str float_swap_dcc, BadDay bad_day_conv): - """ Initialize a yield curve from a list of zero coupon rates - - instruments need to be sorted by tenor - """ - cdef: - double fixed_freq - double float_freq - TDateInterval ivl - char* routine = 'zerocurve' - TDate value_date = pydate_to_TDate(date) - - self._dates = malloc(len(periods) * sizeof(TDate)) - self._ninstr = len(periods) - - cdef TDate settle_date - if JpmcdsDateFromBusDaysOffset(value_date, 2, "None", &settle_date)!= SUCCESS: - raise ValueError - - cdef TDateInterval tmp - for i, p in enumerate(periods): - period_bytes = p.encode('utf-8') - if JpmcdsStringToDateInterval(period_bytes, routine, &tmp) != SUCCESS: - raise ValueError - if JpmcdsDateFwdThenAdjust(settle_date, &tmp, MODIFIED, - "None", &self._dates[i]) != SUCCESS: - raise ValueError('Invalid interval') - - fixed_bytes = fixed_swap_period.encode('utf-8') - float_bytes = float_swap_period.encode('utf-8') - types_bytes = types.encode('utf-8') - - if JpmcdsStringToDateInterval(fixed_bytes, routine, &ivl) != SUCCESS: - raise ValueError - if JpmcdsDateIntervalToFreq(&ivl, &fixed_freq) != SUCCESS: - raise ValueError - if JpmcdsStringToDateInterval(float_bytes, routine, &ivl) != SUCCESS: - raise ValueError - if JpmcdsDateIntervalToFreq(&ivl, &float_freq) != SUCCESS: - raise ValueError - - self._thisptr = JpmcdsBuildIRZeroCurve( - value_date, types_bytes, self._dates, - &rates[0], len(periods), dcc(mm_dcc), fixed_freq, - float_freq, dcc(fixed_swap_dcc), dcc(float_swap_dcc), - bad_day_conv, b"None" - ) - - def __dealloc__(self): - if self._dates is not NULL: - free(self._dates) - - @classmethod - def from_discount_factors(cls, base_date, list dates, double[:] dfs, str day_count_conv): - """ build a yield curve from a list of discount factors """ - cdef TDate base_date_c = pydate_to_TDate(base_date) - cdef YieldCurve yc = cls.__new__(cls) - yc._dates = malloc(sizeof(TDate) * len(dates)) - cdef size_t i - cdef double* rates = malloc(sizeof(double) * len(dfs)) - for i, d in enumerate(dates): - yc._dates[i] = pydate_to_TDate(d) - JpmcdsDiscountToRateYearFrac(dfs[i], (yc._dates[i]-base_date_c)/365., - 1, &rates[i]); - - yc._thisptr = JpmcdsMakeTCurve(base_date_c, yc._dates, rates, len(dfs), - 1, dcc(day_count_conv)) - return yc - - def discount_factor(self, date): - if self._thisptr is NULL: - raise ValueError('curve is empty') - cdef TDate discount_date = pydate_to_TDate(date) - return JpmcdsZeroPrice(self._thisptr, discount_date) - - 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, YieldCurve yc, start_date, step_in_date, - cash_settle_date, list end_dates, double[:] coupon_rates, - double recovery_rate, int pay_accrued_on_default = True): - - cdef TDate today_c = pydate_to_TDate(today) - cdef TDate step_in_date_c = pydate_to_TDate(step_in_date) - cdef TDate cash_settle_date_c = pydate_to_TDate(cash_settle_date) - cdef TDate start_date_c = pydate_to_TDate(start_date) - cdef TDate* end_dates_c = malloc(len(end_dates) * sizeof(TDate)) - self._thisptr = NULL - cdef size_t i - - for i, d in enumerate(end_dates): - end_dates_c[i] = pydate_to_TDate(d) - cdef TStubMethod stub_type - - if JpmcdsStringToStubMethod(b"f/s", &stub_type) != 0: - raise ValueError("can't convert stub") - - self._thisptr = JpmcdsCleanSpreadCurve(today_c, - yc._thisptr, - start_date_c, - step_in_date_c, - cash_settle_date_c, - len(end_dates), - end_dates_c, - &coupon_rates[0], - NULL, - recovery_rate, - pay_accrued_on_default, - NULL, - dcc('ACT/360'), - &stub_type, - 'M', - b'NONE') - - @classmethod - def from_flat_hazard(cls, base_date, double rate, Basis basis = CONTINUOUS, - str day_count_conv = 'Actual/365F'): - cdef TDate base_date_c = pydate_to_TDate(base_date) - cdef SpreadCurve sc = cls.__new__(cls) - cdef TDate max_date = 200000 # can go higher but this should be more than enough - cdef TDate* dates = malloc(sizeof(TDate)) - - cdef double* rates = malloc(sizeof(double)) - dates[0] = max_date - rates[0] = rate - - sc._thisptr = JpmcdsMakeTCurve(base_date_c, dates, rates, 1, - basis, dcc(day_count_conv)) - return sc diff --git a/date.pxd b/date.pxd deleted file mode 100644 index b84d9e5..0000000 --- a/date.pxd +++ /dev/null @@ -1,45 +0,0 @@ -from cpython cimport datetime as c_datetime - -cdef extern from "isda/yearfrac.h": - int JpmcdsStringToDayCountConv(char* day_count, long* type) - char* JpmcdsFormatDayCountConv(long dayCountConv) - -cdef long dcc(str day_count) except -1 - -cdef extern from "isda/cdate.h": - ctypedef struct TDateInterval: - pass - -cdef extern from "isda/mdydate.h": - ctypedef struct TMonthDayYear: - long month - long day - long year - -ctypedef long TDate - -cdef extern from "isda/convert.h": - int JpmcdsStringToDateInterval(char* input, char* label, TDateInterval* interval) - int JpmcdsMakeDateInterval(int num_periods, char period_type, TDateInterval* interval) - char* JpmcdsFormatDate(TDate date) - -cdef extern from "isda/date_sup.h": - int JpmcdsDateIntervalToFreq(TDateInterval* interval, double* freq) - -cdef extern from "isda/dateconv.h": - TDate JpmcdsDate(long year, long month, long day) - int JpmcdsDateToMDY(TDate date, TMonthDayYear *mdyDate) - -cdef extern from "isda/ldate.h": - int JpmcdsDateFwdThenAdjust(TDate date, TDateInterval* interval, long badDayMethod, - char* holidayFile, TDate *advAdjustedDate) - - -cdef extern from "isda/busday.h": - int JpmcdsDateFromBusDaysOffset(TDate fromDate, # (I) input date - long offset, # (I) number of business days - char *holidayFile, # (I) holiday file specification - TDate *result); -cdef TDate pydate_to_TDate(c_datetime.date d) - -cpdef c_datetime.date TDate_to_pydate(TDate d) diff --git a/date.pyx b/date.pyx deleted file mode 100644 index b7a79ab..0000000 --- a/date.pyx +++ /dev/null @@ -1,28 +0,0 @@ -import datetime -from cpython cimport datetime as c_datetime -from date cimport JpmcdsDate, JpmcdsStringToDayCountConv, JpmcdsFormatDayCountConv - -c_datetime.import_datetime() - -cdef TDate pydate_to_TDate(c_datetime.date d): - return JpmcdsDate(d.year, d.month, d.day) - -cpdef c_datetime.date TDate_to_pydate(TDate d): - cdef TMonthDayYear date - if JpmcdsDateToMDY(d, &date) == 0: - return c_datetime.date_new(date.year, date.month, date.day) - -cdef long dcc(str day_count) except -1: - cdef long r - dc_bytes = day_count.encode('utf-8') - cdef char* dc = dc_bytes - cdef err = JpmcdsStringToDayCountConv( dc, &r) - if err == 0: - return r - else: - raise ValueError('{0} is not a valid day count'.format(day_count)) - -def dcc_tostring(long day_count): - cdef char* c_string = JpmcdsFormatDayCountConv(day_count) - s = c_string.decode('utf-8') - return s diff --git a/legs.pxd b/legs.pxd deleted file mode 100644 index 3d8d5bd..0000000 --- a/legs.pxd +++ /dev/null @@ -1,101 +0,0 @@ -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: - int nbDates - TDate* accStartDates - TDate* accEndDates - TDate* payDates - -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 void FeeLegAI(TFeeLeg* fl, - TDate today, - double* ai) - -cdef class ContingentLeg: - cdef TContingentLeg* _thisptr - - -cdef class FeeLeg: - cdef TFeeLeg* _thisptr diff --git a/legs.pyx b/legs.pyx deleted file mode 100644 index 55f1fcb..0000000 --- a/legs.pyx +++ /dev/null @@ -1,103 +0,0 @@ -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 YieldCurve, 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) - if self._thisptr is NULL: - raise ValueError - - def __dealloc__(self): - if self._thisptr is not NULL: - free(self._thisptr) - - def pv(self, today, step_in_date, value_date, YieldCurve yc, SpreadCurve sc, - double recovery_rate): - cdef TDate today_c = pydate_to_TDate(today) - cdef TDate step_in_date_c = pydate_to_TDate(step_in_date) - cdef TDate value_date_c = pydate_to_TDate(value_date) - cdef double pv - if JpmcdsContingentLegPV(self._thisptr, today_c, value_date_c, step_in_date_c, - yc._thisptr, sc._thisptr, recovery_rate, &pv) == 0: - return pv - else: - raise ValueError - -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), - 'M', - b'NONE', - protect_start) - if self._thisptr is NULL: - raise ValueError - - def inspect(self): - cdef list acc_start_dates = [] - cdef list acc_end_dates = [] - cdef list pay_dates = [] - cdef size_t i - for i in range(self._thisptr.nbDates): - acc_start_dates.append(TDate_to_pydate(self._thisptr.accStartDates[i])) - acc_end_dates.append(TDate_to_pydate(self._thisptr.accEndDates[i])) - pay_dates.append(TDate_to_pydate(self._thisptr.payDates[i])) - return {'acc_start_dates': acc_start_dates, - 'acc_end_dates': acc_end_dates, - 'pay_dates': pay_dates} - - @property - def cashflows(self): - cdef TCashFlowList* cfl = JpmcdsFeeLegFlows(self._thisptr) - cdef TCashFlow cf - result = [] - for i in range(cfl.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, YieldCurve yc, SpreadCurve sc, - TBoolean pay_accrued_at_start): - cdef TDate today_c = pydate_to_TDate(today) - cdef TDate step_in_date_c = pydate_to_TDate(step_in_date) - cdef TDate value_date_c = pydate_to_TDate(value_date) - cdef double pv - if JpmcdsFeeLegPV(self._thisptr, today_c, step_in_date_c, value_date_c, - yc._thisptr, sc._thisptr, pay_accrued_at_start, &pv) == 0: - return pv - else: - raise ValueError - - def accrued(self, today): - cdef double ai - FeeLegAI(self._thisptr, pydate_to_TDate(today), &ai) - return ai - - def __dealloc__(self): - if self._thisptr is not NULL: - JpmcdsFeeLegFree(self._thisptr) diff --git a/pyisda/__init__.py b/pyisda/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyisda/cdsone.pxd b/pyisda/cdsone.pxd new file mode 100644 index 0000000..b24d3b4 --- /dev/null +++ b/pyisda/cdsone.pxd @@ -0,0 +1,52 @@ +from date cimport TDateInterval +from curve cimport TCurve + +cdef extern from "isda/stub.h": + ctypedef struct TStubMethod: + pass + + int JpmcdsStringToStubMethod(char* name, TStubMethod* stub) + +cdef extern from "isda/cdsone.h": + + ctypedef int TBoolean + + ctypedef long int TDate + + int JpmcdsCdsoneUpfrontCharge(TDate today, + TDate valueDate, + TDate benchmarkStartDate, + TDate stepinDate, + TDate startDate, + TDate endDate, + double couponRate, + TBoolean payAccruedOnDefault, + TDateInterval* dateInterval, + TStubMethod* stubType, + long accrueDCC, + long badDayConv, + char* calendar, + TCurve* discCurve, + double oneSpread, + double recoveryRate, + TBoolean payAccruedAtStart, + double* upfrontCharge) + + int JpmcdsCdsoneSpread(TDate today, + TDate valueDate, + TDate benchmarkStartDate, + TDate stepinDate, + TDate startDate, + TDate endDate, + double couponRate, + TBoolean payAccruedOnDefault, + TDateInterval* dateInterval, + TStubMethod* stubType, + long accrueDCC, + long badDayConv, + char* calendar, + TCurve* discCurve, + double upfrontCharge, + double recoveryRate, + TBoolean payAccruedAtStart, + double* oneSpread) diff --git a/pyisda/cdsone.pyx b/pyisda/cdsone.pyx new file mode 100644 index 0000000..13c517e --- /dev/null +++ b/pyisda/cdsone.pyx @@ -0,0 +1,71 @@ +from cdsone cimport (JpmcdsCdsoneUpfrontCharge, + JpmcdsCdsoneSpread, JpmcdsStringToStubMethod) +from curve cimport YieldCurve +from date cimport JpmcdsStringToDateInterval, pydate_to_TDate, dcc + +cdef int SUCCESS = 0 + +def upfront_charge(date, value_date, benchmark_start_date, stepin_date, + start_date, end_date, double coupon_rate, + YieldCurve yc, + double spread, + double recovery_rate, + TBoolean pay_accrued_at_start = True, + TBoolean pay_accrued_on_default = True): + + cdef: + TDate today = pydate_to_TDate(date) + TDate value_date_c = pydate_to_TDate(value_date) + TDate benchmark_start_date_c = pydate_to_TDate(benchmark_start_date) + TDate stepin_date_c = pydate_to_TDate(stepin_date) + TDate start_date_c = pydate_to_TDate(start_date) + TDate end_date_c = pydate_to_TDate(end_date) + double result + TStubMethod stub + TDateInterval ivl + char* routine = "upfront_charge" + + if JpmcdsStringToStubMethod(b"f/s", &stub) != SUCCESS: + raise ValueError("can't convert stub") + if JpmcdsStringToDateInterval(b"3M", routine, &ivl) != SUCCESS: + raise ValueError("can't convert to date interval") + if JpmcdsCdsoneUpfrontCharge(today, value_date_c, benchmark_start_date_c, stepin_date_c, + start_date_c, end_date_c, coupon_rate, pay_accrued_on_default, + &ivl, &stub, + dcc("ACT/360"), b'F', b"None", yc._thisptr, spread, recovery_rate, + pay_accrued_at_start, &result) == SUCCESS: + return result + else: + raise ValueError("computation failed") + +def spread_from_upfront(date, value_date, benchmark_start_date, stepin_date, + start_date, end_date, double coupon_rate, + YieldCurve yc, + double upfront, + double recovery_rate, + TBoolean pay_accrued_at_start = True, + TBoolean pay_accrued_on_default = True): + cdef: + TDate today = pydate_to_TDate(date) + TDate value_date_c = pydate_to_TDate(value_date) + TDate benchmark_start_date_c = pydate_to_TDate(benchmark_start_date) + TDate stepin_date_c = pydate_to_TDate(stepin_date) + TDate start_date_c = pydate_to_TDate(start_date) + TDate end_date_c = pydate_to_TDate(end_date) + double result + TStubMethod stub + TDateInterval ivl + char* routine = "upfront_charge" + + if JpmcdsStringToStubMethod(b"f/s", &stub) != SUCCESS: + raise ValueError("can't convert stub") + if JpmcdsStringToDateInterval(b"3M", routine, &ivl) != SUCCESS: + raise ValueError("can't convert to date interval") + if JpmcdsCdsoneSpread(today, value_date_c, benchmark_start_date_c, stepin_date_c, + start_date_c, end_date_c, coupon_rate, pay_accrued_on_default, + &ivl, &stub, + dcc("ACT/360"), b'F', b"None", yc._thisptr, upfront, recovery_rate, + pay_accrued_at_start, &result) == SUCCESS: + return result + else: + raise ValueError("computation failed") diff --git a/pyisda/curve.pxd b/pyisda/curve.pxd new file mode 100644 index 0000000..50de68f --- /dev/null +++ b/pyisda/curve.pxd @@ -0,0 +1,112 @@ +from cdsone cimport TStubMethod + +cdef extern from "isda/zerocurve.h": + ctypedef int TBoolean + + ctypedef long int TDate + + ctypedef struct TDateInterval: + pass + + TCurve* JpmcdsBuildIRZeroCurve(TDate valueDate, + char* instrNames, + TDate* dates, + double* rates, + long nInstr, + long mmDCC, + long fixedSwapFreq, + long floatSwapFreq, + long fixedSwapDCC, + long floatSwapDCC, + long badDayConv, + char* holidayFile) +cdef extern from "isda/bastypes.h": + ctypedef struct TCurve: + int fNumItems + TRatePt* fArray + TDate fBaseDate + double fBasis + long fDayCountConv + + ctypedef struct TRatePt: + TDate fDate + double fRate + +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) + TCurve* JpmcdsMakeTCurve(TDate baseDate, + TDate *dates, + double *rates, + int numPts, + double basis, + long dayCountConv); + +cdef extern from "isda/cxzerocurve.h": + double JpmcdsZeroPrice(TCurve* curve, TDate date) + +cdef extern from "isda/cfinanci.h": + int JpmcdsDiscountToRateYearFrac(double discount, # (I) Discount factor + double yearFraction, # (I) See JpmcdsDayCountFraction + double basis, # (I) Basis for the rate + double *rate); +cdef enum Basis: + CONTINUOUS = 5000 + DISCOUNT_RATE = 512 + SIMPLE_BASIS = 0 + ANNUAL_BASIS = 1 + DISCOUNT_FACTOR = -2 + +cdef class Curve: + cdef TCurve* _thisptr + +cdef class YieldCurve(Curve): + cdef TDate* _dates + cdef size_t _ninstr + +cdef class SpreadCurve(Curve): + pass + +cdef fArray_to_list(TRatePt* fArray, int fNumItems) diff --git a/pyisda/curve.pyx b/pyisda/curve.pyx new file mode 100644 index 0000000..d5bb5ff --- /dev/null +++ b/pyisda/curve.pyx @@ -0,0 +1,172 @@ +from libc.stdlib cimport malloc, free +from curve cimport (JpmcdsBuildIRZeroCurve, JpmcdsZeroPrice, JpmcdsMakeTCurve, + Basis, CONTINUOUS, JpmcdsCleanSpreadCurve) +from date cimport (JpmcdsStringToDateInterval, pydate_to_TDate, dcc, + JpmcdsDateIntervalToFreq, JpmcdsDateFwdThenAdjust, TDate_to_pydate, + JpmcdsDateFromBusDaysOffset) +from date import dcc_tostring +from cdsone cimport JpmcdsStringToStubMethod, TStubMethod + +cdef int SUCCESS = 0 + +cpdef public enum BadDay: + FOLLOW = 'F' + PREVIOUS = 'P' + NONE = 'N' + MODIFIED = 'M' + +cdef class Curve: + def __dealloc__(self): + if self._thisptr is not NULL: + JpmcdsFreeTCurve(self._thisptr) + + def inspect(self): + return {'base_date': TDate_to_pydate(self._thisptr.fBaseDate), + 'basis': self._thisptr.fBasis, + 'day_count_convention': dcc_tostring(self._thisptr.fDayCountConv), + 'data': fArray_to_list(self._thisptr.fArray, self._thisptr.fNumItems)} + +cdef fArray_to_list(TRatePt* fArray, int fNumItems): + cdef size_t i + cdef list l = [] + for i in range(fNumItems): + l.append((TDate_to_pydate(fArray[i].fDate), fArray[i].fRate)) + return l + +cdef class YieldCurve(Curve): + + def __init__(self, date, str types, + list periods, double[:] rates, + str mm_dcc, str fixed_swap_period, str float_swap_period, + str fixed_swap_dcc, str float_swap_dcc, BadDay bad_day_conv): + """ Initialize a yield curve from a list of zero coupon rates + + instruments need to be sorted by tenor + """ + cdef: + double fixed_freq + double float_freq + TDateInterval ivl + char* routine = 'zerocurve' + TDate value_date = pydate_to_TDate(date) + + self._dates = malloc(len(periods) * sizeof(TDate)) + self._ninstr = len(periods) + + cdef TDate settle_date + if JpmcdsDateFromBusDaysOffset(value_date, 2, "None", &settle_date)!= SUCCESS: + raise ValueError + + cdef TDateInterval tmp + for i, p in enumerate(periods): + period_bytes = p.encode('utf-8') + if JpmcdsStringToDateInterval(period_bytes, routine, &tmp) != SUCCESS: + raise ValueError + if JpmcdsDateFwdThenAdjust(settle_date, &tmp, MODIFIED, + "None", &self._dates[i]) != SUCCESS: + raise ValueError('Invalid interval') + + fixed_bytes = fixed_swap_period.encode('utf-8') + float_bytes = float_swap_period.encode('utf-8') + types_bytes = types.encode('utf-8') + + if JpmcdsStringToDateInterval(fixed_bytes, routine, &ivl) != SUCCESS: + raise ValueError + if JpmcdsDateIntervalToFreq(&ivl, &fixed_freq) != SUCCESS: + raise ValueError + if JpmcdsStringToDateInterval(float_bytes, routine, &ivl) != SUCCESS: + raise ValueError + if JpmcdsDateIntervalToFreq(&ivl, &float_freq) != SUCCESS: + raise ValueError + + self._thisptr = JpmcdsBuildIRZeroCurve( + value_date, types_bytes, self._dates, + &rates[0], len(periods), dcc(mm_dcc), fixed_freq, + float_freq, dcc(fixed_swap_dcc), dcc(float_swap_dcc), + bad_day_conv, b"None" + ) + + def __dealloc__(self): + if self._dates is not NULL: + free(self._dates) + + @classmethod + def from_discount_factors(cls, base_date, list dates, double[:] dfs, str day_count_conv): + """ build a yield curve from a list of discount factors """ + cdef TDate base_date_c = pydate_to_TDate(base_date) + cdef YieldCurve yc = cls.__new__(cls) + yc._dates = malloc(sizeof(TDate) * len(dates)) + cdef size_t i + cdef double* rates = malloc(sizeof(double) * len(dfs)) + for i, d in enumerate(dates): + yc._dates[i] = pydate_to_TDate(d) + JpmcdsDiscountToRateYearFrac(dfs[i], (yc._dates[i]-base_date_c)/365., + 1, &rates[i]); + + yc._thisptr = JpmcdsMakeTCurve(base_date_c, yc._dates, rates, len(dfs), + 1, dcc(day_count_conv)) + return yc + + def discount_factor(self, date): + if self._thisptr is NULL: + raise ValueError('curve is empty') + cdef TDate discount_date = pydate_to_TDate(date) + return JpmcdsZeroPrice(self._thisptr, discount_date) + + 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, YieldCurve yc, start_date, step_in_date, + cash_settle_date, list end_dates, double[:] coupon_rates, + double recovery_rate, int pay_accrued_on_default = True): + + cdef TDate today_c = pydate_to_TDate(today) + cdef TDate step_in_date_c = pydate_to_TDate(step_in_date) + cdef TDate cash_settle_date_c = pydate_to_TDate(cash_settle_date) + cdef TDate start_date_c = pydate_to_TDate(start_date) + cdef TDate* end_dates_c = malloc(len(end_dates) * sizeof(TDate)) + self._thisptr = NULL + cdef size_t i + + for i, d in enumerate(end_dates): + end_dates_c[i] = pydate_to_TDate(d) + cdef TStubMethod stub_type + + if JpmcdsStringToStubMethod(b"f/s", &stub_type) != 0: + raise ValueError("can't convert stub") + + self._thisptr = JpmcdsCleanSpreadCurve(today_c, + yc._thisptr, + start_date_c, + step_in_date_c, + cash_settle_date_c, + len(end_dates), + end_dates_c, + &coupon_rates[0], + NULL, + recovery_rate, + pay_accrued_on_default, + NULL, + dcc('ACT/360'), + &stub_type, + 'M', + b'NONE') + + @classmethod + def from_flat_hazard(cls, base_date, double rate, Basis basis = CONTINUOUS, + str day_count_conv = 'Actual/365F'): + cdef TDate base_date_c = pydate_to_TDate(base_date) + cdef SpreadCurve sc = cls.__new__(cls) + cdef TDate max_date = 200000 # can go higher but this should be more than enough + cdef TDate* dates = malloc(sizeof(TDate)) + + cdef double* rates = malloc(sizeof(double)) + dates[0] = max_date + rates[0] = rate + + sc._thisptr = JpmcdsMakeTCurve(base_date_c, dates, rates, 1, + basis, dcc(day_count_conv)) + return sc diff --git a/pyisda/date.pxd b/pyisda/date.pxd new file mode 100644 index 0000000..b84d9e5 --- /dev/null +++ b/pyisda/date.pxd @@ -0,0 +1,45 @@ +from cpython cimport datetime as c_datetime + +cdef extern from "isda/yearfrac.h": + int JpmcdsStringToDayCountConv(char* day_count, long* type) + char* JpmcdsFormatDayCountConv(long dayCountConv) + +cdef long dcc(str day_count) except -1 + +cdef extern from "isda/cdate.h": + ctypedef struct TDateInterval: + pass + +cdef extern from "isda/mdydate.h": + ctypedef struct TMonthDayYear: + long month + long day + long year + +ctypedef long TDate + +cdef extern from "isda/convert.h": + int JpmcdsStringToDateInterval(char* input, char* label, TDateInterval* interval) + int JpmcdsMakeDateInterval(int num_periods, char period_type, TDateInterval* interval) + char* JpmcdsFormatDate(TDate date) + +cdef extern from "isda/date_sup.h": + int JpmcdsDateIntervalToFreq(TDateInterval* interval, double* freq) + +cdef extern from "isda/dateconv.h": + TDate JpmcdsDate(long year, long month, long day) + int JpmcdsDateToMDY(TDate date, TMonthDayYear *mdyDate) + +cdef extern from "isda/ldate.h": + int JpmcdsDateFwdThenAdjust(TDate date, TDateInterval* interval, long badDayMethod, + char* holidayFile, TDate *advAdjustedDate) + + +cdef extern from "isda/busday.h": + int JpmcdsDateFromBusDaysOffset(TDate fromDate, # (I) input date + long offset, # (I) number of business days + char *holidayFile, # (I) holiday file specification + TDate *result); +cdef TDate pydate_to_TDate(c_datetime.date d) + +cpdef c_datetime.date TDate_to_pydate(TDate d) diff --git a/pyisda/date.pyx b/pyisda/date.pyx new file mode 100644 index 0000000..b7a79ab --- /dev/null +++ b/pyisda/date.pyx @@ -0,0 +1,28 @@ +import datetime +from cpython cimport datetime as c_datetime +from date cimport JpmcdsDate, JpmcdsStringToDayCountConv, JpmcdsFormatDayCountConv + +c_datetime.import_datetime() + +cdef TDate pydate_to_TDate(c_datetime.date d): + return JpmcdsDate(d.year, d.month, d.day) + +cpdef c_datetime.date TDate_to_pydate(TDate d): + cdef TMonthDayYear date + if JpmcdsDateToMDY(d, &date) == 0: + return c_datetime.date_new(date.year, date.month, date.day) + +cdef long dcc(str day_count) except -1: + cdef long r + dc_bytes = day_count.encode('utf-8') + cdef char* dc = dc_bytes + cdef err = JpmcdsStringToDayCountConv( dc, &r) + if err == 0: + return r + else: + raise ValueError('{0} is not a valid day count'.format(day_count)) + +def dcc_tostring(long day_count): + cdef char* c_string = JpmcdsFormatDayCountConv(day_count) + s = c_string.decode('utf-8') + return s diff --git a/pyisda/legs.pxd b/pyisda/legs.pxd new file mode 100644 index 0000000..3d8d5bd --- /dev/null +++ b/pyisda/legs.pxd @@ -0,0 +1,101 @@ +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: + int nbDates + TDate* accStartDates + TDate* accEndDates + TDate* payDates + +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 void FeeLegAI(TFeeLeg* fl, + TDate today, + double* ai) + +cdef class ContingentLeg: + cdef TContingentLeg* _thisptr + + +cdef class FeeLeg: + cdef TFeeLeg* _thisptr diff --git a/pyisda/legs.pyx b/pyisda/legs.pyx new file mode 100644 index 0000000..55f1fcb --- /dev/null +++ b/pyisda/legs.pyx @@ -0,0 +1,103 @@ +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 YieldCurve, 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) + if self._thisptr is NULL: + raise ValueError + + def __dealloc__(self): + if self._thisptr is not NULL: + free(self._thisptr) + + def pv(self, today, step_in_date, value_date, YieldCurve yc, SpreadCurve sc, + double recovery_rate): + cdef TDate today_c = pydate_to_TDate(today) + cdef TDate step_in_date_c = pydate_to_TDate(step_in_date) + cdef TDate value_date_c = pydate_to_TDate(value_date) + cdef double pv + if JpmcdsContingentLegPV(self._thisptr, today_c, value_date_c, step_in_date_c, + yc._thisptr, sc._thisptr, recovery_rate, &pv) == 0: + return pv + else: + raise ValueError + +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), + 'M', + b'NONE', + protect_start) + if self._thisptr is NULL: + raise ValueError + + def inspect(self): + cdef list acc_start_dates = [] + cdef list acc_end_dates = [] + cdef list pay_dates = [] + cdef size_t i + for i in range(self._thisptr.nbDates): + acc_start_dates.append(TDate_to_pydate(self._thisptr.accStartDates[i])) + acc_end_dates.append(TDate_to_pydate(self._thisptr.accEndDates[i])) + pay_dates.append(TDate_to_pydate(self._thisptr.payDates[i])) + return {'acc_start_dates': acc_start_dates, + 'acc_end_dates': acc_end_dates, + 'pay_dates': pay_dates} + + @property + def cashflows(self): + cdef TCashFlowList* cfl = JpmcdsFeeLegFlows(self._thisptr) + cdef TCashFlow cf + result = [] + for i in range(cfl.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, YieldCurve yc, SpreadCurve sc, + TBoolean pay_accrued_at_start): + cdef TDate today_c = pydate_to_TDate(today) + cdef TDate step_in_date_c = pydate_to_TDate(step_in_date) + cdef TDate value_date_c = pydate_to_TDate(value_date) + cdef double pv + if JpmcdsFeeLegPV(self._thisptr, today_c, step_in_date_c, value_date_c, + yc._thisptr, sc._thisptr, pay_accrued_at_start, &pv) == 0: + return pv + else: + raise ValueError + + def accrued(self, today): + cdef double ai + FeeLegAI(self._thisptr, pydate_to_TDate(today), &ai) + return ai + + def __dealloc__(self): + if self._thisptr is not NULL: + JpmcdsFeeLegFree(self._thisptr) diff --git a/setup.py b/setup.py index 9162d58..8aae177 100644 --- a/setup.py +++ b/setup.py @@ -2,8 +2,11 @@ from distutils.core import setup from distutils.extension import Extension from Cython.Build import cythonize -extensions = Extension("*", ["*.pyx"], +extensions = Extension("*", ["pyisda/*.pyx"], libraries = ["cds"]) setup( name = "pyisda", - ext_modules = cythonize(extensions)) + version = '0.1', + author = 'Guillaume Horel', + ext_modules = cythonize(extensions, nthreads = 4), + packages = ['pyisda']) -- cgit v1.2.3-70-g09d2