From 8c1721349b40ec56926c6b74cb5187bb8700fa97 Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Tue, 8 May 2018 14:51:36 -0400 Subject: add default_accrual function --- pyisda/date.pxd | 20 ++++++++++++++++++-- pyisda/date.pyx | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/pyisda/date.pxd b/pyisda/date.pxd index 9755ced..c1f7dd5 100644 --- a/pyisda/date.pxd +++ b/pyisda/date.pxd @@ -1,4 +1,5 @@ from cpython cimport datetime as c_datetime +from cdsone cimport TStubMethod cdef extern from "isda/yearfrac.h" nogil: int JpmcdsStringToDayCountConv(char* day_count, long* type) @@ -9,6 +10,7 @@ cdef long dcc(str day_count) except -1 cdef extern from "isda/cdate.h": ctypedef struct TDateInterval: pass + ctypedef long TDate cdef extern from "isda/mdydate.h": ctypedef struct TMonthDayYear: @@ -16,8 +18,6 @@ cdef extern from "isda/mdydate.h": long day long year -ctypedef long TDate - cdef extern from "isda/convert.h" nogil: int JpmcdsStringToDateInterval(char* input, char* label, TDateInterval* interval) int JpmcdsMakeDateInterval(int num_periods, char period_type, TDateInterval* interval) @@ -58,6 +58,22 @@ cdef extern from "isda/busday.h" nogil: JPMCDS_BAD_DAY_NONE JPMCDS_BAD_DAY_MODIFIED +cdef extern from "isda/defaulted.h" nogil: + int JpmcdsDefaultAccrual( + TDate tradeDate, + TDate edd, + TDate startDate, + TDate endDate, + TDateInterval *couponInterval, + TStubMethod *stubType, + double notional, + double couponRate, + long paymentDcc, + long badDayConv, + char *calendar, + int *accrualDays, + double *defaultAccrual) + cpdef enum BadDay: FOLLOW = JPMCDS_BAD_DAY_FOLLOW PREVIOUS = JPMCDS_BAD_DAY_PREVIOUS diff --git a/pyisda/date.pyx b/pyisda/date.pyx index 821d224..7e13ce1 100644 --- a/pyisda/date.pyx +++ b/pyisda/date.pyx @@ -2,6 +2,7 @@ import datetime from cpython cimport datetime as c_datetime from cpython.version cimport PY_MAJOR_VERSION from libc.stdlib cimport malloc, free +from cdsone cimport JpmcdsStringToStubMethod cimport cython cimport numpy as np @@ -20,6 +21,7 @@ cpdef c_datetime.date TDate_to_pydate(TDate d): else: raise ValueError("incorrect date") + cdef long dcc(str day_count) except -1: cdef long r dc_bytes = day_count.encode('utf-8') @@ -30,6 +32,7 @@ cdef long dcc(str day_count) except -1: 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) if PY_MAJOR_VERSION >= 3: @@ -38,6 +41,7 @@ def dcc_tostring(long day_count): s = c_string return s + cdef TDate _previous_twentieth(TDate d, bint roll) nogil: cdef TMonthDayYear mdy if JpmcdsDateToMDY(d, &mdy) != SUCCESS: @@ -64,15 +68,18 @@ cdef TDate _previous_twentieth(TDate d, bint roll) nogil: else: return r + def previous_twentieth(d, bint roll=True): cdef TDate date = pydate_to_TDate(d) return TDate_to_pydate(_previous_twentieth(date, roll)) + @cython.cdivision(True) def cds_accrued(d, double coupon): cdef TDate date = pydate_to_TDate(d) + 1 return (date - _previous_twentieth(date, True))/360. * coupon + cdef TMonthDayYear next_twentieth(TDate d) nogil: cdef TMonthDayYear mdy JpmcdsDateToMDY(d, &mdy) @@ -159,3 +166,38 @@ def roll_date(d, tenor): tenor_ = tenor _roll_date(date_, &tenor_, 1, &output_date) return TDate_to_pydate(output_date) + + +def default_accrual(trade_date, edd, start_date, end_date, double notional, + double coupon_rate): + cdef: + TDate trade_date_c = pydate_to_TDate(trade_date) + TDate edd_c = pydate_to_TDate(edd) + TDate start_date_c = pydate_to_TDate(start_date) + TDate end_date_c = pydate_to_TDate(end_date) + TDateInterval ivl + TStubMethod stub + int accrual_days + double default_accrual + + if JpmcdsStringToStubMethod(b"f/s", &stub) != SUCCESS: + raise ValueError("can't convert stub") + + if JpmcdsMakeDateInterval(3, "M", &ivl) != SUCCESS: + raise ValueError("can't convert to date interval") + + if JpmcdsDefaultAccrual(trade_date_c, + edd_c, + start_date_c, + end_date_c, + &ivl, + &stub, + notional, + coupon_rate, + ACT_360, + FOLLOW, + b"None", + &accrual_days, + &default_accrual) != SUCCESS: + raise ValueError("failed to compute default accrual") + return accrual_days, default_accrual -- cgit v1.2.3-70-g09d2