summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pyisda/credit_index.pxd10
-rw-r--r--pyisda/credit_index.pyx210
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