diff options
| -rw-r--r-- | pyisda/credit_index.pxd | 10 | ||||
| -rw-r--r-- | pyisda/credit_index.pyx | 210 |
2 files changed, 133 insertions, 87 deletions
diff --git a/pyisda/credit_index.pxd b/pyisda/credit_index.pxd index 88a3e3a..24ccf6f 100644 --- a/pyisda/credit_index.pxd +++ b/pyisda/credit_index.pxd @@ -2,13 +2,15 @@ from legs cimport TContingentLeg, TFeeLeg from date cimport TDate from curve cimport TCurve -cdef class CreditIndexCurve: +cdef class CurveList: cdef TDate _base_date cdef TCurve** _curves cdef int _len_curves + cdef double* _T + cdef int _len_T + +cdef class CreditIndex(CurveList): cdef TDate* _maturities + cdef int _len_maturities cdef TContingentLeg** _contingent_legs cdef TFeeLeg** _fee_legs - cdef int _len_maturities - cdef double* _T - cdef int _len_T diff --git a/pyisda/credit_index.pyx b/pyisda/credit_index.pyx index 25337ed..0ea469c 100644 --- a/pyisda/credit_index.pyx +++ b/pyisda/credit_index.pyx @@ -2,14 +2,16 @@ from libc.stdlib cimport malloc, free cimport cython from legs cimport (JpmcdsCdsContingentLegMake, JpmcdsCdsFeeLegMake, JpmcdsContingentLegPV, JpmcdsFeeLegPV, FeeLegAI, JpmcdsFeeLegFree) -from curve cimport SpreadCurve, JpmcdsCopyCurve, tweak_curve, YieldCurve, JpmcdsFreeTCurve -from date cimport pydate_to_TDate, TDate_to_pydate +from curve cimport (SpreadCurve, JpmcdsCopyCurve, tweak_curve, YieldCurve, + JpmcdsFreeTCurve, JpmcdsNewTCurve) +from date cimport pydate_to_TDate, TDate_to_pydate, ACT_365F from cdsone cimport JpmcdsStringToStubMethod, TStubMethod +from date cimport ACT_365F cimport numpy as np np.import_array() -cdef class CreditIndexCurve: - def __init__(self, start_date, maturities, curves): +cdef class CurveList: + def __init__(self, curves): cdef SpreadCurve sc = <SpreadCurve?>curves[0] self._len_T = sc._thisptr.fNumItems self._base_date = sc._thisptr.fBaseDate @@ -17,16 +19,50 @@ cdef class CreditIndexCurve: cdef size_t i for i in range(self._len_T): self._T[i] = (sc._thisptr.fArray[i].fDate - self._base_date) / 365. + self._len_curves = len(curves) + self._curves = <TCurve**>malloc(sizeof(TCurve*) * self._len_curves) + for i, c in enumerate(curves): + self._curves[i] = JpmcdsCopyCurve((<SpreadCurve?>c)._thisptr) + + def __dealloc__(self): + if self._T is not NULL: + free(self._T) + cdef size_t i + for i in range(self._len_curves): + JpmcdsFreeTCurve(self._curves[i]) + free(self._curves) + + @property + def curves(self): + """returns the list of curves inside the porfolio. + + This is returning the curves by reference so don't delete them.""" + cdef list r = [] + cdef SpreadCurve sc + for i in range(self._len_curves): + sc = SpreadCurve.__new__(SpreadCurve) + sc._thisptr = self._curves[i] + r.append(sc) + + @curves.setter + def curves(self, list l): + if len(l) != self._len_curves: + raise ValueError("l should have {} elements".format(len(l))) + + cdef size_t i + for i, c in enumerate(l): + JpmcdsFreeTCurve(self._curves[i]) + self._curves[i] = JpmcdsCopyCurve((<SpreadCurve?>c)._thisptr) + +cdef class CreditIndex(CurveList): + def __init__(self, start_date, maturities, curves): + CurveList.__init__(self, curves) cdef TDate start_date_c = pydate_to_TDate(start_date) self._len_maturities = len(maturities) self._maturities = <TDate*>malloc(sizeof(TDate) * self._len_maturities) + cdef size_t i for i, d in enumerate(maturities): self._maturities[i] = pydate_to_TDate(d) - self._len_curves = len(curves) - self._curves = <TCurve**>malloc(sizeof(TCurve*) * self._len_curves) - - for i, c in enumerate(curves): - self._curves[i] = JpmcdsCopyCurve((<SpreadCurve?>c)._thisptr) self._contingent_legs = <TContingentLeg**> malloc(self._len_maturities * sizeof(TContingentLeg)) @@ -52,9 +88,8 @@ cdef class CreditIndexCurve: <long>'M', # MODIFIED b'NONE', True) + def __dealloc__(self): - if self._T is not NULL: - free(self._T) if self._maturities is not NULL: free(self._maturities) if self._contingent_legs is not NULL: @@ -63,9 +98,6 @@ cdef class CreditIndexCurve: if self._fee_legs is not NULL: for i in range(self._len_maturities): JpmcdsFeeLegFree(self._fee_legs[i]) - for i in range(self._len_curves): - JpmcdsFreeTCurve(self._curves[i]) - free(self._curves) #@cython.initializedcheck(False) @cython.boundscheck(False) @@ -99,38 +131,76 @@ cdef class CreditIndexCurve: sc, True, &fl_pv[i,j]) - return (fl_pv-accrued, cl_pv) + return (fl_pv - accrued, cl_pv) + @cython.boundscheck(False) + @cython.cdivision(True) def pv(self, step_in_date, value_date, maturity, YieldCurve yc not None, - double recovery_rate, double fixed_rate): + double recovery_rate, double fixed_rate, double epsilon=0.): - cdef TDate step_in_date_c = pydate_to_TDate(step_in_date) - cdef TDate value_date_c = pydate_to_TDate(value_date) - cdef TDate maturity_c = pydate_to_TDate(value_date) + cdef: + TDate step_in_date_c = pydate_to_TDate(step_in_date) + TDate value_date_c = pydate_to_TDate(value_date) + TDate maturity_c = pydate_to_TDate(maturity) cdef double accrued FeeLegAI(self._fee_legs[0], self._base_date, &accrued) + cdef: + TContingentLeg* cl + TFeeLeg* fl - for j in range(self._len_maturities): - if self._maturities[j] == maturity_c: - return pv(self._base_date, step_in_date_c, value_date_c, - yc._thisptr, recovery_rate, fixed_rate, - self._contingent_legs[j], self._fee_legs[j], - self._curves, self._len_curves) - accrued + for i in range(self._len_maturities): + if self._maturities[i] == maturity_c: + cl = self._contingent_legs[i] + fl = self._fee_legs[i] + break else: - ValueError("This maturity is not available.") + raise ValueError("maturity is not correct") - @property - def curves(self): - """returns the list of curves inside the porfolio. + cdef bint* mask + cdef double* h + cdef TCurve* tweaked_curve + if epsilon != 0: + mask = fill_mask(maturity_c, self._maturities, self._len_maturities, + self._curves[0]) + if mask == NULL: + raise ValueError("maturity is not correct") + h = <double*>malloc(sizeof(double) * self._len_T) + tweaked_curve = JpmcdsNewTCurve(self._base_date, + self._len_T, + 5000., + ACT_365F) + + cdef: + double fl_pv, cl_pv, r=0 - This is returning the curves by reference so don't delete them.""" - cdef list r = [] - cdef SpreadCurve sc for i in range(self._len_curves): - sc = SpreadCurve.__new__(SpreadCurve) - sc._thisptr = self._curves[i] - r.append(sc) + if epsilon != 0: + tweak_curve(self._curves[i], tweaked_curve, epsilon, h, self._T, mask, self._len_T) + else: + tweaked_curve = self._curves[i] + JpmcdsContingentLegPV(cl, + self._base_date, + value_date_c, + step_in_date_c, + yc._thisptr, + tweaked_curve, + recovery_rate, + &cl_pv) + JpmcdsFeeLegPV(fl, + self._base_date, + step_in_date_c, + value_date_c, + yc._thisptr, + tweaked_curve, + True, + &fl_pv) + r += cl_pv - fl_pv * fixed_rate + if epsilon != 0: + JpmcdsFreeTCurve(tweaked_curve) + free(h) + free(mask) + return r / <double>self._len_curves @property def maturities(self): @@ -138,57 +208,31 @@ cdef class CreditIndexCurve: for i in range(self._len_maturities): r.append(TDate_to_pydate(self._maturities[i])) - def tweak_portfolio(self, epsilon, maturity): - cdef bint* mask = <bint*>malloc(sizeof(bint) * self._len_T) + def tweak_portfolio(self, double epsilon, maturity, bint inplace=True): cdef TDate maturity_c = pydate_to_TDate(maturity) - cdef TDate prev_maturity - prev_maturity = 0 - cdef size_t i, j - for i in range(self._len_maturities): - if self._maturities[i] > maturity_c: - break - if self._maturities[i] == maturity_c: - prev_maturity = self._maturities[i-1] - else: - raise ValueError("maturity is not correct") - cdef TCurve* sc = self._curves[0] - for j in range(self._len_T): - mask[j] = (sc.fArray[i].fDate <= maturity_c ) and \ - (sc.fArray[i].fDate > prev_maturity) - + cdef bint* mask = fill_mask(maturity_c, self._maturities, + self._len_maturities, self._curves[0]) cdef double* h = <double*>malloc(sizeof(double) * self._len_T) - for j in self._len_curves: - sc = self._curves[j] - tweak_curve(sc, sc, epsilon, h, self._T, mask, self._len_curves) + cdef size_t i + for i in range(self._len_curves): + sc = self._curves[i] + tweak_curve(sc, sc, epsilon, h, self._T, mask, self._len_T) free(h) free(mask) -@cython.boundscheck(False) -cdef double pv(TDate base_date, TDate step_in_date, TDate value_date, TCurve* yc, - double recovery_rate, double coupon, - TContingentLeg* cl, TFeeLeg* fl, TCurve** curves, int n_curves): - +cdef bint* fill_mask(TDate maturity, TDate* maturities, int n_maturities, + TCurve* sc) nogil: + cdef TDate prev_maturity = 0 cdef size_t i - cdef TCurve* sc - cdef double r = 0 - cdef double cl_pv, fl_pv - for i in range(n_curves): - sc = curves[i] - JpmcdsContingentLegPV(cl, - base_date, - value_date, - step_in_date, - yc, - sc, - recovery_rate, - &cl_pv) - JpmcdsFeeLegPV(fl, - base_date, - step_in_date, - value_date, - yc, - sc, - True, - &fl_pv) - r += cl_pv - fl_pv*coupon - return r / <double>n_curves + for i in range(n_maturities): + if maturities[i] == maturity: + if i > 0: + prev_maturity = maturities[i-1] + break + else: + return NULL + cdef bint* mask = <bint*>malloc(sc.fNumItems * sizeof(bint)) + for i in range(sc.fNumItems): + mask[i] = (sc.fArray[i].fDate <= maturity ) and \ + (sc.fArray[i].fDate > prev_maturity) + return mask |
