summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pyisda/credit_index.pxd14
-rw-r--r--pyisda/credit_index.pyx194
-rw-r--r--pyisda/curve.pxd14
-rw-r--r--pyisda/curve.pyx178
4 files changed, 213 insertions, 187 deletions
diff --git a/pyisda/credit_index.pxd b/pyisda/credit_index.pxd
new file mode 100644
index 0000000..88a3e3a
--- /dev/null
+++ b/pyisda/credit_index.pxd
@@ -0,0 +1,14 @@
+from legs cimport TContingentLeg, TFeeLeg
+from date cimport TDate
+from curve cimport TCurve
+
+cdef class CreditIndexCurve:
+ cdef TDate _base_date
+ cdef TCurve** _curves
+ cdef int _len_curves
+ cdef TDate* _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
new file mode 100644
index 0000000..25337ed
--- /dev/null
+++ b/pyisda/credit_index.pyx
@@ -0,0 +1,194 @@
+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 cdsone cimport JpmcdsStringToStubMethod, TStubMethod
+cimport numpy as np
+np.import_array()
+
+cdef class CreditIndexCurve:
+ def __init__(self, start_date, maturities, curves):
+ cdef SpreadCurve sc = <SpreadCurve?>curves[0]
+ self._len_T = sc._thisptr.fNumItems
+ self._base_date = sc._thisptr.fBaseDate
+ self._T = <double*>malloc(sizeof(double) * self._len_T)
+ cdef size_t i
+ for i in range(self._len_T):
+ self._T[i] = (sc._thisptr.fArray[i].fDate - self._base_date) / 365.
+ cdef TDate start_date_c = pydate_to_TDate(start_date)
+ self._len_maturities = len(maturities)
+ self._maturities = <TDate*>malloc(sizeof(TDate) * self._len_maturities)
+ 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))
+ self._fee_legs = <TFeeLeg**> malloc(self._len_maturities *
+ sizeof(TFeeLeg))
+ cdef TStubMethod stub_type
+ if JpmcdsStringToStubMethod(b"f/s", &stub_type) != 0:
+ raise ValueError("can't convert stub")
+ for i in range(self._len_maturities):
+ self._contingent_legs[i] = JpmcdsCdsContingentLegMake(start_date_c,
+ self._maturities[i],
+ 1.,
+ True)
+
+ self._fee_legs[i] = JpmcdsCdsFeeLegMake(start_date_c,
+ self._maturities[i],
+ True,
+ NULL,
+ &stub_type,
+ 1.,
+ 1.0,
+ 3, #ACT_360
+ <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:
+ for i in range(self._len_maturities):
+ free(self._contingent_legs[i])
+ 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)
+ def pv_vec(self, step_in_date, value_date, YieldCurve yc, double recovery_rate):
+ cdef TDate step_in_date_c = pydate_to_TDate(step_in_date)
+ cdef TDate value_date_c = pydate_to_TDate(value_date)
+ cdef np.npy_intp[2] n = [self._len_curves, self._len_maturities]
+ cdef double accrued
+ FeeLegAI(self._fee_legs[0], self._base_date, &accrued)
+ cdef size_t i, j
+
+ cdef np.ndarray[np.float64_t,ndim=2] cl_pv = np.PyArray_EMPTY(2, n, np.NPY_DOUBLE, 0)
+ cdef np.ndarray[np.float64_t,ndim=2] fl_pv = np.PyArray_EMPTY(2, n, np.NPY_DOUBLE, 0)
+ cdef TCurve* sc
+ for i in range(self._len_curves):
+ sc = self._curves[i]
+ for j in range(self._len_maturities):
+ JpmcdsContingentLegPV(self._contingent_legs[j],
+ sc.fBaseDate,
+ value_date_c,
+ step_in_date_c,
+ yc._thisptr,
+ sc,
+ recovery_rate,
+ &cl_pv[i,j])
+ JpmcdsFeeLegPV(self._fee_legs[j],
+ sc.fBaseDate,
+ step_in_date_c,
+ value_date_c,
+ yc._thisptr,
+ sc,
+ True,
+ &fl_pv[i,j])
+ return (fl_pv-accrued, cl_pv)
+
+ def pv(self, step_in_date, value_date, maturity, YieldCurve yc not None,
+ double recovery_rate, double fixed_rate):
+
+ 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 double accrued
+ FeeLegAI(self._fee_legs[0], self._base_date, &accrued)
+
+ 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
+ else:
+ ValueError("This maturity is not available.")
+
+ @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)
+
+ @property
+ def maturities(self):
+ cdef list r = []
+ 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)
+ 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 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)
+ 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 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
diff --git a/pyisda/curve.pxd b/pyisda/curve.pxd
index e42e8de..63da78d 100644
--- a/pyisda/curve.pxd
+++ b/pyisda/curve.pxd
@@ -117,15 +117,7 @@ cdef class YieldCurve(Curve):
cdef class SpreadCurve(Curve):
pass
-cdef class CreditIndexCurve:
- cdef TDate _base_date
- cdef TCurve** _curves
- cdef int _len_curves
- cdef TDate* _maturities
- cdef TContingentLeg** _contingent_legs
- cdef TFeeLeg** _fee_legs
- cdef int _len_maturities
- cdef double* _T
- cdef int _len_T
-
cdef fArray_to_list(TRatePt* fArray, int fNumItems)
+
+cdef void tweak_curve(TCurve* sc, TCurve* sc_tweaked, double epsilon,
+ double* h, double* T, bint* mask, int n)
diff --git a/pyisda/curve.pyx b/pyisda/curve.pyx
index 9662961..d306dd9 100644
--- a/pyisda/curve.pyx
+++ b/pyisda/curve.pyx
@@ -1,6 +1,7 @@
from libc.stdlib cimport malloc, free
from libc.string cimport memcpy
from libc.math cimport log1p
+from libc.stdio cimport printf
from date cimport (JpmcdsStringToDateInterval, pydate_to_TDate, dcc,
JpmcdsDateIntervalToFreq, JpmcdsDateFwdThenAdjust, TDate_to_pydate,
JpmcdsDateFromBusDaysOffset, JpmcdsStringToDayCountConv)
@@ -108,6 +109,7 @@ cdef class Curve(object):
t1 = 0
h1 = 0
cdef double* data = <double*>malloc(self._thisptr.fNumItems * sizeof(double))
+ cdef size_t i
if <Basis>self._thisptr.fBasis == Basis.CONTINUOUS:
for i in range(self._thisptr.fNumItems):
h2 = self._thisptr.fArray[i].fRate
@@ -482,179 +484,3 @@ cdef class SpreadCurve(Curve):
free(h)
free(T)
return sc
-
-cdef class CreditIndexCurve:
- def __init__(self, start_date, maturities, curves):
- cdef SpreadCurve sc = <SpreadCurve?>curves[0]
- self._len_T = sc._thisptr.fNumItems
- self._base_date = sc._thisptr.fBaseDate
- self._T = <double*>malloc(sizeof(double) * self._len_T)
- cdef size_t i
- for i in range(self._len_T):
- self._T[i] = (sc._thisptr.fArray[i].fDate - self._base_date) / 365.
- cdef TDate start_date_c = pydate_to_TDate(start_date)
- self._len_maturities = len(maturities)
- self._maturities = <TDate*>malloc(sizeof(TDate) * self._len_maturities)
- 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))
- self._fee_legs = <TFeeLeg**> malloc(self._len_maturities *
- sizeof(TFeeLeg))
- cdef TStubMethod stub_type
- if JpmcdsStringToStubMethod(b"f/s", &stub_type) != 0:
- raise ValueError("can't convert stub")
- for i in range(self._len_maturities):
- self._contingent_legs[i] = JpmcdsCdsContingentLegMake(start_date_c,
- self._maturities[i],
- 1.,
- True)
-
- self._fee_legs[i] = JpmcdsCdsFeeLegMake(start_date_c,
- self._maturities[i],
- True,
- NULL,
- &stub_type,
- 1.,
- 1.0,
- 3, #ACT_360
- 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:
- for i in range(self._len_maturities):
- free(self._contingent_legs[i])
- 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)
- def pv_vec(self, step_in_date, value_date, YieldCurve yc, double recovery_rate):
- cdef TDate step_in_date_c = pydate_to_TDate(step_in_date)
- cdef TDate value_date_c = pydate_to_TDate(value_date)
- cdef np.npy_intp[2] n = [self._len_curves, self._len_maturities]
- cdef double accrued
- FeeLegAI(self._fee_legs[0], self._base_date, &accrued)
- cdef size_t i, j
-
- cdef np.ndarray[np.float64_t,ndim=2] cl_pv = np.PyArray_EMPTY(2, n, np.NPY_DOUBLE, 0)
- cdef np.ndarray[np.float64_t,ndim=2] fl_pv = np.PyArray_EMPTY(2, n, np.NPY_DOUBLE, 0)
- cdef TCurve* sc
- for i in range(self._len_curves):
- sc = self._curves[i]
- for j in range(self._len_maturities):
- JpmcdsContingentLegPV(self._contingent_legs[j],
- sc.fBaseDate,
- value_date_c,
- step_in_date_c,
- yc._thisptr,
- sc,
- recovery_rate,
- &cl_pv[i,j])
- JpmcdsFeeLegPV(self._fee_legs[j],
- sc.fBaseDate,
- step_in_date_c,
- value_date_c,
- yc._thisptr,
- sc,
- True,
- &fl_pv[i,j])
- return (fl_pv-accrued, cl_pv)
-
- def pv(self, step_in_date, value_date, YieldCurve yc not None,
- double recovery_rate):
-
- cdef TDate step_in_date_c = pydate_to_TDate(step_in_date)
- cdef TDate value_date_c = pydate_to_TDate(value_date)
-
- r = []
- for j in range(self._len_maturities):
- r.append(pv(self._base_date, step_in_date_c, value_date_c,
- yc._thisptr, recovery_rate, 0.01,
- self._contingent_legs[j],
- self._fee_legs[j], self._curves, self._len_curves))
-
- cdef double accrued
- FeeLegAI(self._fee_legs[0], self._base_date, &accrued)
- return r
-
- @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)
-
- @property
- def maturities(self):
- cdef list r = []
- for i in range(self._len_maturities):
- r.append(TDate_to_pydate(self._maturities[i]))
-
- def tweak_portfolio(self, quotes):
- if len(quotes) != self._len_maturities:
- raise ValueError("length of quotes must equal length of maturities")
- cdef bint* mask = <bint*>malloc(sizeof(bint) * self._len_T)
- cdef double* basis = <double*>malloc(sizeof(double) * self._len_T)
- cdef TCurve* sc = self._curves[0]
- cdef TDate maturity, prev_maturity
- prev_maturity = 0
- cdef size_t i
- for i in range(self._len_maturities):
- maturity = self._maturities[i]
- for j in range(self._len_T):
- mask[j] = (sc.fArray[i].fDate <= maturity ) and \
- (sc.fArray[i].fDate > prev_maturity)
-
- free(mask)
- free(basis)
-
-@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 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