summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuillaume Horel <guillaume.horel@gmail.com>2017-02-23 11:17:58 -0500
committerGuillaume Horel <guillaume.horel@gmail.com>2017-02-23 12:49:12 -0500
commit39df288240394e74903b3c70986ede40b0b243a8 (patch)
tree486a5a94c66af323666f8e1ad7adfa6b0bcfc392
parent1fe8d4a980ce2bdcef093946d360767f7e65976c (diff)
downloadpyisda-39df288240394e74903b3c70986ede40b0b243a8.tar.gz
Finish C++ switch
not sure if it's worth it, but we'll see...
-rw-r--r--cpp_layer/curve.hpp5
-rw-r--r--pyisda/cdsone.pyx8
-rw-r--r--pyisda/credit_index.pxd13
-rw-r--r--pyisda/credit_index.pyx113
-rw-r--r--pyisda/curve.pxd19
-rw-r--r--pyisda/curve.pyx144
-rw-r--r--pyisda/flat_hazard.pyx10
-rw-r--r--pyisda/legs.pyx5
8 files changed, 164 insertions, 153 deletions
diff --git a/cpp_layer/curve.hpp b/cpp_layer/curve.hpp
index e4fddb8..fd1db3b 100644
--- a/cpp_layer/curve.hpp
+++ b/cpp_layer/curve.hpp
@@ -38,7 +38,10 @@ public:
TCurve* data() {
return _ptr;
}
-
+ typedef TRatePt* iterator;
+ typedef const TRatePt* const_iterator;
+ iterator begin() { return _ptr->fArray; }
+ iterator end() {return &_ptr->fArray[_ptr->fNumItems];}
int size() {
return _ptr->fNumItems;
}
diff --git a/pyisda/cdsone.pyx b/pyisda/cdsone.pyx
index 95fc6a6..ddc3336 100644
--- a/pyisda/cdsone.pyx
+++ b/pyisda/cdsone.pyx
@@ -58,8 +58,8 @@ def upfront_charge(date, value_date, benchmark_start_date, stepin_date,
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,
+ &ivl, &stub, dcc("ACT/360"), b'F', b"None",
+ yc._thisptr.get().data(), spread, recovery_rate,
pay_accrued_at_start, &result) == SUCCESS:
return result
else:
@@ -120,8 +120,8 @@ def spread_from_upfront(date, value_date, benchmark_start_date, stepin_date,
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,
+ &ivl, &stub, dcc("ACT/360"), b'F', b"None",
+ yc._thisptr.get().data(), upfront, recovery_rate,
pay_accrued_at_start, &result) == SUCCESS:
return result
else:
diff --git a/pyisda/credit_index.pxd b/pyisda/credit_index.pxd
index cb7c944..8051726 100644
--- a/pyisda/credit_index.pxd
+++ b/pyisda/credit_index.pxd
@@ -1,18 +1,17 @@
from legs cimport TContingentLeg, TFeeLeg
from date cimport TDate
-from curve cimport TCurve
+from curve cimport CurveObject, TCurve
+from libcpp.memory cimport shared_ptr
+from libcpp.vector cimport vector
cdef class CurveList:
cdef TDate _base_date
- cdef TCurve** _curves
- cdef int _len_curves
- cdef double* _T
- cdef int _len_T
+ cdef vector[shared_ptr[CurveObject]] _curves
+ cdef vector[double] _T
cdef list _tickers
cdef dict _tickersdict
cdef class CreditIndex(CurveList):
- cdef TDate* _maturities
- cdef int _len_maturities
+ cdef vector[TDate] _maturities
cdef TContingentLeg** _contingent_legs
cdef TFeeLeg** _fee_legs
diff --git a/pyisda/credit_index.pyx b/pyisda/credit_index.pyx
index c7cd4e9..774c8e9 100644
--- a/pyisda/credit_index.pyx
+++ b/pyisda/credit_index.pyx
@@ -1,4 +1,5 @@
from libc.stdlib cimport malloc, free
+from cython.operator cimport dereference as deref, preincrement as preinc
cimport cython
from legs cimport (JpmcdsCdsContingentLegMake, JpmcdsCdsFeeLegMake,
JpmcdsContingentLegPV, JpmcdsFeeLegPV, FeeLegAI, JpmcdsFeeLegFree)
@@ -20,47 +21,35 @@ cdef class CurveList:
else:
raise TypeError("curves need to be a list of SpreadCurve "\
"or a list of tuple (SpreadCurve, ticker)")
- self._len_T = sc._thisptr.fNumItems
- self._base_date = sc._thisptr.fBaseDate
- self._T = <double*>malloc(sizeof(double) * self._len_T)
+ self._T = vector[double](sc._thisptr.get().size())
+ self._base_date = sc._thisptr.get().BaseDate()
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 in range(self._T.size()):
+ self._T[i] = (sc._thisptr.get().data().fArray[i].fDate - self._base_date) / 365.
self._tickers = []
self._tickersdict = {}
if isinstance(curves[0], tuple):
for i, (t, c) in enumerate(curves):
- self._curves[i] = JpmcdsCopyCurve((<SpreadCurve?>c)._thisptr)
+ self._curves.push_back((<SpreadCurve?>c)._thisptr)
self._tickers.append(t)
self._tickersdict[t] = i
else:
- for i, c in enumerate(curves):
- self._curves[i] = JpmcdsCopyCurve((<SpreadCurve?>c)._thisptr)
+ for c in curves:
+ self._curves.push_back((<SpreadCurve?>c)._thisptr)
if tickers and not self._tickers:
- if len(tickers) != self._len_curves:
+ if len(tickers) != self._curves.size():
raise ValueError("tickers must have the same length as curves")
else:
self._tickers = tickers
self._tickersdict = {t: i for i, t in enumerate(tickers)}
- 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)
-
def __getitem__(self, str ticker):
- ## would need to use a shared pointer to avoid a copy
cdef SpreadCurve sc
if ticker in self._tickers:
sc = SpreadCurve.__new__(SpreadCurve)
- sc._thisptr = JpmcdsCopyCurve(self._curves[self._tickersdict[ticker]])
+ sc._thisptr = self._curves[self._tickersdict[ticker]]
return sc
else:
raise KeyError(ticker)
@@ -68,10 +57,14 @@ cdef class CurveList:
def iteritems(self):
## would need to use a shared pointer to avoid a copy
cdef SpreadCurve sc
- for i in range(self._len_curves):
+ cdef vector[shared_ptr[CurveObject]].iterator it = self._curves.begin()
+ cdef size_t i
+ while it != self._curves.end():
sc = SpreadCurve.__new__(SpreadCurve)
- sc._thisptr = self._curves[i]
+ sc._thisptr = deref(it)
yield (self._tickers[i], sc)
+ preinc(it)
+ i = i+1
@property
def curves(self):
@@ -87,31 +80,28 @@ cdef class CurveList:
@curves.setter
def curves(self, list l):
- if len(l) != self._len_curves:
+ if len(l) != self._curves.size():
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)
+ self._curves[i] = (<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)
+ for d in maturities:
+ self._maturities.push_back(pydate_to_TDate(d))
- self._contingent_legs = <TContingentLeg**> malloc(self._len_maturities *
+ self._contingent_legs = <TContingentLeg**> malloc(self._maturities.size() *
sizeof(TContingentLeg))
- self._fee_legs = <TFeeLeg**> malloc(self._len_maturities *
+ self._fee_legs = <TFeeLeg**> malloc(self._maturities.size() *
sizeof(TFeeLeg))
cdef TStubMethod stub_type
if JpmcdsStringToStubMethod(b"f/s", &stub_type) != 0:
raise ValueError("can't convert stub")
+ cdef size_t i
for i in range(self._len_maturities):
self._contingent_legs[i] = JpmcdsCdsContingentLegMake(start_date_c,
self._maturities[i],
@@ -131,8 +121,6 @@ cdef class CreditIndex(CurveList):
True)
def __dealloc__(self):
- 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])
@@ -145,7 +133,7 @@ cdef class CreditIndex(CurveList):
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 np.npy_intp[2] n = [self._curves.size(), self._maturities.size()]
cdef double accrued
FeeLegAI(self._fee_legs[0], self._base_date, &accrued)
cdef size_t i, j
@@ -153,14 +141,14 @@ cdef class CreditIndex(CurveList):
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 i in range(self._curves.size()):
+ sc = self._curves[i].get().data()
for j in range(self._len_maturities):
JpmcdsContingentLegPV(self._contingent_legs[j],
sc.fBaseDate,
value_date_c,
step_in_date_c,
- yc._thisptr,
+ yc._thisptr.get().data(),
sc,
recovery_rate,
&cl_pv[i,j])
@@ -168,7 +156,7 @@ cdef class CreditIndex(CurveList):
sc.fBaseDate,
step_in_date_c,
value_date_c,
- yc._thisptr,
+ yc._thisptr.get().data(),
sc,
True,
&fl_pv[i,j])
@@ -190,7 +178,7 @@ cdef class CreditIndex(CurveList):
TContingentLeg* cl
TFeeLeg* fl
- for i in range(self._len_maturities):
+ for i in range(self._maturities.size()):
if self._maturities[i] == maturity_c:
cl = self._contingent_legs[i]
fl = self._fee_legs[i]
@@ -202,26 +190,25 @@ cdef class CreditIndex(CurveList):
cdef double* h
cdef TCurve* tweaked_curve
if epsilon != 0:
- mask = fill_mask(maturity_c, self._maturities, self._len_maturities,
- self._curves[0])
+ mask = fill_mask(maturity_c, self._maturities, self._curves[0])
if mask == NULL:
raise ValueError("maturity is not correct")
h = <double*>malloc(sizeof(double) * self._len_T)
- tweaked_curve = JpmcdsCopyCurve(self._curves[0])
+ tweaked_curve = JpmcdsCopyCurve(self._curves[0].get().data())
cdef:
double fl_pv, cl_pv, r = 0
- for i in range(self._len_curves):
+ for i in range(self._curves.size()):
if epsilon != 0:
- tweak_curve(self._curves[i], tweaked_curve, epsilon, h, self._T, mask, self._len_T)
+ tweak_curve(self._curves[i].get().data(), tweaked_curve, epsilon, h, self._T, mask)
else:
- tweaked_curve = self._curves[i]
+ tweaked_curve = self._curves[i].get().data()
JpmcdsContingentLegPV(cl,
self._base_date,
value_date_c,
step_in_date_c,
- yc._thisptr,
+ yc._thisptr.get().data(),
tweaked_curve,
recovery_rate,
&cl_pv)
@@ -229,7 +216,7 @@ cdef class CreditIndex(CurveList):
self._base_date,
step_in_date_c,
value_date_c,
- yc._thisptr,
+ yc._thisptr.get().data(),
tweaked_curve,
True,
&fl_pv)
@@ -243,35 +230,37 @@ cdef class CreditIndex(CurveList):
@property
def maturities(self):
cdef list r = []
- for i in range(self._len_maturities):
+ for i in range(self._maturities.size()):
r.append(TDate_to_pydate(self._maturities[i]))
return r
def tweak_portfolio(self, double epsilon, maturity, bint inplace=True):
cdef TDate maturity_c = pydate_to_TDate(maturity)
- cdef bint* mask = fill_mask(maturity_c, self._maturities,
- self._len_maturities, self._curves[0])
+ cdef bint* mask = fill_mask(maturity_c, self._maturities, self._curves[0])
cdef double* h = <double*>malloc(sizeof(double) * self._len_T)
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)
+ cdef TCurve* sc
+ for i in range(self._curves.size()):
+ sc = self._curves[i].get().data()
+ tweak_curve(sc, sc, epsilon, h, self._T, mask)
free(h)
free(mask)
-cdef bint* fill_mask(TDate maturity, TDate* maturities, int n_maturities,
- TCurve* sc) nogil:
+cdef bint* fill_mask(TDate maturity, const vector[TDate]& maturities,
+ const shared_ptr[CurveObject]& sc) nogil:
cdef TDate prev_maturity = 0
cdef size_t i
- for i in range(n_maturities):
+ for i in range(maturities.size()):
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)
+ cdef bint* mask = <bint*>malloc(sc.get().size() * sizeof(bint))
+ cdef TDate date
+ for i in range(sc.get().size()):
+ date = sc.get().data().fArray[i].fDate
+ mask[i] = (date <= maturity ) and \
+ (date > prev_maturity)
return mask
diff --git a/pyisda/curve.pxd b/pyisda/curve.pxd
index 63da78d..31b36b3 100644
--- a/pyisda/curve.pxd
+++ b/pyisda/curve.pxd
@@ -1,5 +1,7 @@
from cdsone cimport TStubMethod
from legs cimport TContingentLeg, TFeeLeg
+from libcpp.memory cimport shared_ptr
+from libcpp.vector cimport vector
cdef extern from "isda/zerocurve.h" nogil:
ctypedef int TBoolean
@@ -91,6 +93,19 @@ cdef extern from "isda/tcurve.h" nogil:
double basis, # (I) Compounding periods/year
long dayCountConv)
+cdef extern from "../cpp_layer/curve.hpp" nogil:
+ cdef cppclass CurveObject:
+ CurveObject(TDate baseDate, vector[TDate] dates, vector[double] rates,
+ double basis, long dayCountConv)
+ TCurve* data()
+ double ForwardZeroPrice(TDate d2)
+ double ForwardZeroPrice(TDate d2, TDate d1)
+ int size()
+ TDate BaseDate()
+ ctypedef TRatePt* iterator
+ iterator begin()
+ iterator end()
+
cdef extern from "isda/cxzerocurve.h" nogil:
double JpmcdsZeroPrice(TCurve* curve, TDate date)
double JpmcdsForwardZeroPrice(TCurve* curve, TDate startDate, TDate maturityDate)
@@ -108,7 +123,7 @@ cdef enum Basis:
DISCOUNT_FACTOR = -2
cdef class Curve:
- cdef TCurve* _thisptr
+ cdef shared_ptr[CurveObject] _thisptr
cdef class YieldCurve(Curve):
cdef TDate* _dates
@@ -120,4 +135,4 @@ cdef class SpreadCurve(Curve):
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)
+ double* h, const vector[double]& T, bint* mask)
diff --git a/pyisda/curve.pyx b/pyisda/curve.pyx
index d306dd9..a6c81f3 100644
--- a/pyisda/curve.pyx
+++ b/pyisda/curve.pyx
@@ -1,7 +1,10 @@
from libc.stdlib cimport malloc, free
from libc.string cimport memcpy
from libc.math cimport log1p
-from libc.stdio cimport printf
+from libcpp.memory cimport make_shared, shared_ptr
+from libcpp.vector cimport vector
+from cython.operator cimport preincrement as preinc
+
from date cimport (JpmcdsStringToDateInterval, pydate_to_TDate, dcc,
JpmcdsDateIntervalToFreq, JpmcdsDateFwdThenAdjust, TDate_to_pydate,
JpmcdsDateFromBusDaysOffset, JpmcdsStringToDayCountConv)
@@ -27,17 +30,15 @@ cpdef public enum BadDay:
MODIFIED = <long>'M'
cdef class Curve(object):
- def __dealloc__(self):
- if self._thisptr is not NULL:
- JpmcdsFreeTCurve(self._thisptr)
def __getstate__(self):
- cdef int num_items = self._thisptr.fNumItems
+ cdef TCurve* curve = self._thisptr.get().data()
+ cdef int num_items = curve.fNumItems;
return (num_items,
- <bytes>(<char*>self._thisptr.fArray)[:sizeof(TRatePt)*num_items],
- self._thisptr.fBaseDate,
- self._thisptr.fBasis,
- self._thisptr.fDayCountConv)
+ <bytes>(<char*>curve.fArray)[:sizeof(TRatePt)*num_items],
+ curve.fBaseDate,
+ curve.fBasis,
+ curve.fDayCountConv)
def __setstate__(self, state):
cdef:
@@ -55,7 +56,7 @@ cdef class Curve(object):
new_curve.fBaseDate = base_date
new_curve.fBasis = basis
new_curve.fDayCountConv = dcc
- self._thisptr = new_curve
+ self._thisptr = make_shared[CurveObject](new_curve)
def inspect(self):
""" method to inspect the content of the C struct
@@ -67,60 +68,63 @@ cdef class Curve(object):
"""
return {'base_date': self.base_date,
- 'basis': self._thisptr.fBasis,
- 'day_count_convention': dcc_tostring(self._thisptr.fDayCountConv),
- 'data': fArray_to_list(self._thisptr.fArray, self._thisptr.fNumItems)}
+ 'basis': self._thisptr.get().data().fBasis,
+ 'day_count_convention': dcc_tostring(self._thisptr.get().data().fDayCountConv),
+ 'data': fArray_to_list(self._thisptr.get().data().fArray, self._thisptr.get().data().fNumItems)}
@cython.boundscheck(False)
def to_df(self):
- cdef np.npy_intp n = self._thisptr.fNumItems
+ cdef np.npy_intp n = self._thisptr.get().data().fNumItems
cdef np.ndarray[np.float64_t,ndim=1] h = np.PyArray_EMPTY(1, &n, np.NPY_DOUBLE, 0)
cdef np.ndarray[np.int64_t,ndim=1] d = np.PyArray_EMPTY(1, &n, np.NPY_INT64, 0)
- cdef size_t i
- for i in range(self._thisptr.fNumItems):
- h[i] = self._thisptr.fArray[i].fRate
- d[i] = self._thisptr.fArray[i].fDate
- d[i] -= 134774
+ cdef size_t i = 0
+ cdef CurveObject.iterator it = self._thisptr.get().begin()
+ while it != self._thisptr.get().end():
+ h[i] = it.fRate
+ d[i] = it.fDate -134774
+ preinc(it)
+ preinc(i)
+
return {'hazard_rates': h, 'dates':d.view('M8[D]')}
def __iter__(self):
cdef:
- size_t i
- double h
- int d
- for i in range(self._thisptr.fNumItems):
- h = self._thisptr.fArray[i].fRate
- d = self._thisptr.fArray[i].fDate
- yield TDate_to_pydate(d), h
+ size_t i = 0
+ CurveObject.iterator it = self._thisptr.get().begin()
+ while it != self._thisptr.get().end():
+ yield (TDate_to_pydate(it.fDate), it.fRate)
+ preinc(it)
+ preinc(i)
def __len__(self):
- return self._thisptr.fNumItems
+ return self._thisptr.get().size()
def __deepcopy__(self, memo):
cdef Curve sc = type(self).__new__(type(self))
- sc._thisptr = JpmcdsCopyCurve(self._thisptr)
+ sc._thisptr = self._thisptr
return sc
@property
@cython.cdivision(True)
def forward_hazard_rates(self):
cdef double t1, h1, t2, h2
- cdef np.npy_intp shape = self._thisptr.fNumItems
+ cdef np.npy_intp shape = self._thisptr.get().size()
t1 = 0
h1 = 0
- cdef double* data = <double*>malloc(self._thisptr.fNumItems * sizeof(double))
+ cdef TCurve* curve = self._thisptr.get().data()
+ cdef double* data = <double*>malloc(curve.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
- t2 = (self._thisptr.fArray[i].fDate - self._thisptr.fBaseDate)/365.
+ if <Basis>curve.fBasis == Basis.CONTINUOUS:
+ for i in range(curve.fNumItems):
+ h2 = curve.fArray[i].fRate
+ t2 = (curve.fArray[i].fDate - curve.fBaseDate)/365.
data[i] = (h2 * t2 - h1 * t1) / (t2 - t1)
h1 = h2
t1 = t2
- elif <Basis>self._thisptr.fBasis == Basis.ANNUAL_BASIS:
- for i in range(self._thisptr.fNumItems):
- h2 = log1p(self._thisptr.fArray[i].fRate)
- t2 = (self._thisptr.fArray[i].fDate - self._thisptr.fBaseDate)/365.
+ elif <Basis>curve.fBasis == Basis.ANNUAL_BASIS:
+ for i in range(curve.fNumItems):
+ h2 = log1p(curve.fArray[i].fRate)
+ t2 = (curve.fArray[i].fDate - curve.fBaseDate)/365.
data[i] = (h2 * t2 - h1 * t1) / (t2 - t1)
h1 = h2
t1 = t2
@@ -134,7 +138,7 @@ cdef class Curve(object):
@property
def base_date(self):
- return TDate_to_pydate(self._thisptr.fBaseDate)
+ return TDate_to_pydate(self._thisptr.get().BaseDate())
def __forward_zero_price(self, d2, d1=None):
""" computes the forward zero price at a given date.
@@ -147,16 +151,14 @@ cdef class Curve(object):
-------
float
"""
- if self._thisptr is NULL:
+ if not self._thisptr:
raise ValueError('curve is empty')
cdef TDate start_date
if d1 is None:
- start_date = self._thisptr.fBaseDate
+ return self._thisptr.get().ForwardZeroPrice(pydate_to_TDate(d2))
else:
- start_date = pydate_to_TDate(d1)
- return JpmcdsForwardZeroPrice(self._thisptr,
- start_date,
- pydate_to_TDate(d2))
+ return self._thisptr.get().ForwardZeroPrice(pydate_to_TDate(d2),
+ pydate_to_TDate(d1))
cdef fArray_to_list(TRatePt* fArray, int fNumItems):
cdef size_t i
@@ -241,12 +243,12 @@ cdef class YieldCurve(Curve):
if JpmcdsDateIntervalToFreq(&ivl, &float_freq) != SUCCESS:
raise ValueError
- self._thisptr = JpmcdsBuildIRZeroCurve(
+ self._thisptr = make_shared[CurveObject](JpmcdsBuildIRZeroCurve(
value_date, types_bytes, self._dates,
&rates[0], self._ninstr, dcc(mm_dcc), <long> fixed_freq,
<long> float_freq, dcc(fixed_swap_dcc), dcc(float_swap_dcc),
bad_day_conv, b"None"
- )
+ ))
def __dealloc__(self):
## __dealloc__ of superclass is called by cython so no need to call here
@@ -279,8 +281,9 @@ cdef class YieldCurve(Curve):
JpmcdsDiscountToRateYearFrac(dfs[i], <double>(yc._dates[i]-base_date_c)/365.,
<double>1, &rates[i])
- yc._thisptr = JpmcdsMakeTCurve(base_date_c, yc._dates, rates, dfs.shape[0],
- <double>1, dcc(day_count_conv))
+ yc._thisptr = make_shared[CurveObject](
+ JpmcdsMakeTCurve(base_date_c, yc._dates, rates, dfs.shape[0],
+ <double>1, dcc(day_count_conv)))
return yc
discount_factor = Curve.__forward_zero_price
@@ -307,24 +310,25 @@ cdef class YieldCurve(Curve):
cdef double df
for k in range(yc._ninstr):
yc._dates[k] = self._dates[i]
- df = JpmcdsForwardZeroPrice(self._thisptr, forward_date_c, self._dates[i])
+ df = self._thisptr.get().ForwardZeroPrice(forward_date_c, self._dates[i])
JpmcdsDiscountToRateYearFrac(
df, <double>(self._dates[i] - forward_date_c)/365.,
<double>1, &rates[k])
i += 1
- yc._thisptr = JpmcdsMakeTCurve(forward_date_c, yc._dates, rates, yc._ninstr,
- <double>1, self._thisptr.fDayCountConv)
+ yc._thisptr = make_shared[CurveObject](
+ JpmcdsMakeTCurve(forward_date_c, yc._dates, rates, yc._ninstr,
+ <double>1, self._thisptr.get().data().fDayCountConv))
return yc
@cython.cdivision(True)
-cdef inline void tweak_curve(TCurve* sc, TCurve* sc_tweaked, double epsilon,
- double* h, double* T, bint* mask, int n):
+cdef void tweak_curve(TCurve* sc, TCurve* sc_tweaked, double epsilon,
+ double* h, const vector[double]& T, bint* mask):
## We want to tweak in the forward space, so we convert the hazard rates
## into forward rates and then back
cdef double h1, h2, t1, t2
h1 = t1 = 0
cdef size_t i
- for i in range(n):
+ for i in range(T.size()):
h2 = sc.fArray[i].fRate
t2 = T[i]
h[i] = (h2 * t2 - h1 * t1) / (t2 - t1)
@@ -335,7 +339,7 @@ cdef inline void tweak_curve(TCurve* sc, TCurve* sc_tweaked, double epsilon,
t1 = 0
cdef double c = 0
- for i in range(n):
+ for i in range(T.size()):
c += (T[i] - t1) * h[i]
sc_tweaked.fArray[i].fRate = c / T[i]
t1 = T[i]
@@ -373,7 +377,7 @@ cdef class SpreadCurve(Curve):
cdef TDate* end_dates_c = <TDate*>malloc(n_dates * sizeof(TDate))
cdef TCurve* curve = NULL
cdef size_t i
- if cash_settle_date_c < yc._thisptr.fBaseDate:
+ if cash_settle_date_c < yc._thisptr.get().BaseDate():
raise ValueError("cash_settle_date: {0} is anterior to yc's base_date: {1}".
format(cash_settle_date, yc.base_date))
for i, d in enumerate(end_dates):
@@ -386,7 +390,7 @@ cdef class SpreadCurve(Curve):
with nogil:
JpmcdsStringToDayCountConv('ACT/360', &dc)
curve = JpmcdsCleanSpreadCurve(today_c,
- yc._thisptr,
+ yc._thisptr.get().data(),
start_date_c,
step_in_date_c,
cash_settle_date_c,
@@ -406,7 +410,7 @@ cdef class SpreadCurve(Curve):
if curve == NULL:
raise ValueError("Didn't init the survival curve properly")
else:
- self._thisptr = curve
+ self._thisptr = make_shared[CurveObject](curve)
survival_probability = Curve.__forward_zero_price
@@ -432,8 +436,9 @@ cdef class SpreadCurve(Curve):
cdef SpreadCurve sc = cls.__new__(cls)
cdef TDate max_date = 200000 # can go higher but this should be more than enough
- sc._thisptr = JpmcdsMakeTCurve(base_date_c, &max_date, &rate, 1,
- <double>basis, dcc(day_count_conv))
+ sc._thisptr = make_shared[CurveObject](
+ JpmcdsMakeTCurve(base_date_c, &max_date, &rate, 1,
+ <double>basis, dcc(day_count_conv)))
return sc
@cython.boundscheck(False)
@@ -455,32 +460,31 @@ cdef class SpreadCurve(Curve):
cdef:
TCurve* curve_tweaked
SpreadCurve sc
- int num_items = self._thisptr.fNumItems
+ int num_items = self._thisptr.get().size()
double *h
- double *T
+ vector[double] T
size_t i
bint* mask_ptr
if not inplace:
sc = SpreadCurve.__new__(SpreadCurve)
- curve_tweaked = JpmcdsCopyCurve(self._thisptr)
- sc._thisptr = curve_tweaked
+ curve_tweaked = JpmcdsCopyCurve(self._thisptr.get().data())
+ sc._thisptr = make_shared[CurveObject](curve_tweaked)
else:
sc = self
- curve_tweaked = self._thisptr
+ curve_tweaked = self._thisptr.get().data()
h = <double*>malloc(num_items * sizeof(double))
- T = <double*>malloc(num_items * sizeof(double))
+ T = vector[double](num_items)
for i in range(num_items):
T[i] = (curve_tweaked.fArray[i].fDate - curve_tweaked.fBaseDate) / 365.
if mask is not None:
- if mask.shape[0] != self._thisptr.fNumItems:
+ if mask.shape[0] != self._thisptr.get().size():
raise ValueError("mask size need to be the same as the number of Items")
mask_ptr = &mask[0]
else:
mask_ptr = NULL
- tweak_curve(self._thisptr, curve_tweaked, epsilon, h, T, mask_ptr, num_items)
+ tweak_curve(self._thisptr.get().data(), curve_tweaked, epsilon, h, T, mask_ptr)
free(h)
- free(T)
return sc
diff --git a/pyisda/flat_hazard.pyx b/pyisda/flat_hazard.pyx
index fc93b1d..4922239 100644
--- a/pyisda/flat_hazard.pyx
+++ b/pyisda/flat_hazard.pyx
@@ -52,7 +52,7 @@ def strike_vec(double[:] spreads, YieldCurve yc, trade_date, value_date,
cdef double zero_upfront = 0
for i in range(spreads.shape[0]):
sc = JpmcdsCleanSpreadCurve(trade_date_c,
- yc._thisptr,
+ yc._thisptr.get().data(),
start_date_c,
step_in_date_c,
value_date_c,
@@ -69,11 +69,11 @@ def strike_vec(double[:] spreads, YieldCurve yc, trade_date, value_date,
<long>'M',
b'NONE')
if JpmcdsContingentLegPV(default_leg, trade_date_c, value_date_c,
- step_in_date_c, yc._thisptr, sc,
+ step_in_date_c, yc._thisptr.get().data(), sc,
recovery_rate, &default_leg_pv[i]) != 0:
raise ValueError("Something went wrong")
if JpmcdsFeeLegPV(fee_leg, trade_date_c, step_in_date_c, value_date_c,
- yc._thisptr, sc, True, &coupon_leg_pv[i]) != 0:
+ yc._thisptr.get().data(), sc, True, &coupon_leg_pv[i]) != 0:
raise ValueError("Something went wrong")
JpmcdsFeeLegFree(fee_leg)
free(default_leg)
@@ -159,7 +159,7 @@ def pv_vec(double[:] spreads, YieldCurve yc, trade_date, value_date,
params = <cds_bootstrap_ctx*>malloc(sizeof(cds_bootstrap_ctx))
params.stepinDate = step_in_date_c
params.cashSettleDate = value_date_c
- params.discountCurve = yc._thisptr
+ params.discountCurve = yc._thisptr.get().data()
params.cdsCurve = sc
params.recoveryRate = recovery_rate
params.cl = default_leg
@@ -185,7 +185,7 @@ def pv_vec(double[:] spreads, YieldCurve yc, trade_date, value_date,
break
sc.fArray[0].fRate = h
if JpmcdsFeeLegPV(fee_leg, trade_date_c, step_in_date_c, value_date_c,
- yc._thisptr, sc, True, &coupon_leg_pv) != 0:
+ yc._thisptr.get().data(), sc, True, &coupon_leg_pv) != 0:
printf("Something went wrong\n")
pv[i] = coupon_leg_pv * (spreads[i] - fixed_rate)
free(params)
diff --git a/pyisda/legs.pyx b/pyisda/legs.pyx
index 71e300c..c558816 100644
--- a/pyisda/legs.pyx
+++ b/pyisda/legs.pyx
@@ -59,7 +59,8 @@ cdef class ContingentLeg:
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:
+ yc._thisptr.get().data(), sc._thisptr.get().data(),
+ recovery_rate, &pv) == 0:
return pv
else:
raise ValueError
@@ -164,7 +165,7 @@ cdef class FeeLeg:
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:
+ yc._thisptr.get().data(), sc._thisptr.get().data(), pay_accrued_at_start, &pv) == 0:
return pv
else:
raise ValueError