summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuillaume Horel <guillaume.horel@gmail.com>2017-09-22 11:27:49 -0400
committerGuillaume Horel <guillaume.horel@gmail.com>2017-09-22 11:27:49 -0400
commitff038af022cbc1c31d800753aeb22ba41445dfb6 (patch)
treed42cf22d7f0f7e3ed5b265b1e34e47858ab9a75d
parentd1199cfd6346a5790051ca8a80c5a8f01df3baea (diff)
downloadpyisda-ff038af022cbc1c31d800753aeb22ba41445dfb6.tar.gz
fix memory issues
-rw-r--r--pyisda/credit_index.pxd3
-rw-r--r--pyisda/credit_index.pyx125
2 files changed, 72 insertions, 56 deletions
diff --git a/pyisda/credit_index.pxd b/pyisda/credit_index.pxd
index e4b2d37..f3e61b8 100644
--- a/pyisda/credit_index.pxd
+++ b/pyisda/credit_index.pxd
@@ -9,7 +9,8 @@ cdef class CurveList:
cdef TDate base_date
cdef public vector[double] weights
cdef vector[double] T
- cdef unordered_map[string, shared_ptr[TCurve]] curves
+ cdef vector[shared_ptr[TCurve]] curves
+ cdef unordered_map[string, size_t] tickers
cdef class CreditIndex(CurveList):
cdef TDate start_date
diff --git a/pyisda/credit_index.pyx b/pyisda/credit_index.pyx
index a3f617d..db65b6f 100644
--- a/pyisda/credit_index.pyx
+++ b/pyisda/credit_index.pyx
@@ -1,3 +1,4 @@
+#cython: cdivision=True, boundscheck=False
from libc.stdlib cimport malloc, free
from libc.math cimport nan
from libcpp.pair cimport pair
@@ -17,12 +18,12 @@ np.import_array()
import pandas as pd
cdef class CurveList:
- @cython.cdivision(True)
- @cython.boundscheck(False)
def __init__(self, list curves, double[:] weights=None):
cdef:
SpreadCurve sc
size_t i
+ unordered_map[string, size_t].iterator it
+ size_t n = len(curves)
if isinstance(curves[0], SpreadCurve):
sc = <SpreadCurve>curves[0]
@@ -34,27 +35,36 @@ cdef class CurveList:
for i in range(self.T.size()):
self.T[i] = (sc._thisptr.get().fArray[i].fDate - self.base_date) / 365.
+ i = 0
for sc in curves:
- self.curves[sc.ticker] = sc._thisptr
+ it = self.tickers.find(sc.ticker)
+ if it == self.tickers.end():
+ self.tickers[sc.ticker] = i
+ self.curves.push_back(sc._thisptr)
+ self.weights.push_back(1.)
+ i += 1
+ else:
+ self.weights[deref(it).second] += 1
if weights is not None:
for i in range(weights.shape[0]):
- self.weights.push_back(weights[i])
+ self.weights[i] = weights[i]
else:
- self.weights = vector[double](self.curves.size(), 1./self.curves.size())
+ for i in range(self.curves.size()):
+ self.weights[i] /= n
def __getitem__(self, str ticker):
cdef:
string ticker_cpp = ticker.encode()
- unordered_map[string, shared_ptr[TCurve]].iterator got = \
- self.curves.find(ticker_cpp)
+ unordered_map[string, size_t].iterator got = \
+ self.tickers.find(ticker_cpp)
SpreadCurve sc
- if got == self.curves.end():
+ if got == self.tickers.end():
raise KeyError(ticker)
else:
sc = SpreadCurve.__new__(SpreadCurve)
- sc._thisptr = deref(got).second
+ sc._thisptr = self.curves[deref(got).second]
sc.ticker = ticker_cpp
return sc
@@ -62,13 +72,13 @@ cdef class CurveList:
## would need to use a shared pointer to avoid a copy
cdef:
SpreadCurve sc
- pair[string, shared_ptr[TCurve]] p
+ pair[string, size_t] p
- for p in self.curves:
+ for p in self.tickers:
sc = SpreadCurve.__new__(SpreadCurve)
- sc._thisptr = p.second
+ sc._thisptr = self.curves[p.second]
sc.ticker = p.first
- yield (sc.ticker.decode(), sc)
+ yield (sc.ticker.decode(), self.weights[p.second], sc)
@property
def curves(self):
@@ -78,11 +88,11 @@ cdef class CurveList:
cdef:
list r = []
SpreadCurve sc
- pair[string, shared_ptr[TCurve]] p
+ pair[string, size_t] p
- for p in self.curves:
+ for p in self.tickers:
sc = SpreadCurve.__new__(SpreadCurve)
- sc._thisptr = p.second
+ sc._thisptr = self.curves[p.second]
sc.ticker = p.first
r.append(sc)
return r
@@ -92,20 +102,32 @@ cdef class CurveList:
cdef:
size_t len_l = len(l)
size_t i
- SpreadCurve c
+ SpreadCurve sc
+ unordered_map[string, size_t].iterator it
- if len_l != self.curves.size():
- self.curves.clear()
+ self.curves.clear()
+ self.tickers.clear()
- c = l[0]
- self.T.resize(c._thisptr.get().fNumItems)
- self.base_date = c._thisptr.get().fBaseDate
+ sc = l[0]
+ self.T.resize(sc._thisptr.get().fNumItems)
+ self.base_date = sc._thisptr.get().fBaseDate
for i in range(self.T.size()):
- self.T[i] = (c._thisptr.get().fArray[i].fDate - self.base_date) / 365.
+ self.T[i] = (sc._thisptr.get().fArray[i].fDate - self.base_date) / 365.
+
+ i = 0
+ for sc in l:
+ it = self.tickers.find(sc.ticker)
+ if it == self.tickers.end():
+ self.tickers[sc.ticker] = i
+ self.curves.push_back(sc._thisptr)
+ self.weights.push_back(1.)
+ i += 1
+ else:
+ self.weights[deref(it).second] += 1
- for i, c in enumerate(l):
- self.curves[c.ticker] = c._thisptr
+ for i in range(self.curves.size()):
+ self.weights[i] /= len_l
cdef class CreditIndex(CurveList):
def __init__(self, start_date, maturities, list curves, double[:] weights=None):
@@ -149,7 +171,6 @@ cdef class CreditIndex(CurveList):
JpmcdsFeeLegFree(self.fee_legs[i])
#@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)
@@ -162,15 +183,15 @@ cdef class CreditIndex(CurveList):
np.ndarray[np.int64_t,ndim=1] d = np.PyArray_EMPTY(1, &n[1], np.NPY_INT64, 0)
TDate maturity
TCurve* sc
- pair[string,shared_ptr[TCurve]] p
+ pair[string, size_t] p
for maturity in self.maturities:
d[j] = maturity - 134774
j += 1
j = 0
- for p in self.curves:
- sc = p.second.get()
+ for p in self.tickers:
+ sc = self.curves[p.second].get()
tickers.append(p.first.decode())
for j in range(self.maturities.size()):
JpmcdsContingentLegPV(self.contingent_legs[j],
@@ -204,7 +225,6 @@ cdef class CreditIndex(CurveList):
FeeLegAI(self.fee_legs[0], self.base_date, &accrued)
return accrued
- @cython.boundscheck(False)
def pv(self, step_in_date, value_date, maturity, YieldCurve yc not None,
double recovery_rate, double fixed_rate, double epsilon=0.):
@@ -221,7 +241,7 @@ cdef class CreditIndex(CurveList):
self.maturities)
if epsilon != 0.:
- mask = fill_mask(maturity_c, self.maturities, deref(self.curves.begin()).second)
+ mask = fill_mask(maturity_c, self.maturities, self.curves[0])
if mask == 0:
raise ValueError("maturity is not correct")
h = vector[double](self.T.size())
@@ -265,7 +285,6 @@ cdef class CreditIndex(CurveList):
yc._thisptr.get(), legs, recovery_rate, fixed_rate,
self.weights, 0., h, self.T, 0) + fixed_rate
- @cython.boundscheck(False)
def duration(self, step_in_date, value_date, maturity, YieldCurve yc not None):
cdef:
@@ -284,16 +303,16 @@ cdef class CreditIndex(CurveList):
cdef:
double fl_pv, r = 0
- pair[string,shared_ptr[TCurve]] p
+ shared_ptr[TCurve] sc
i = 0
- for p in self.curves:
+ for sc in self.curves:
JpmcdsFeeLegPV(fl,
self.base_date,
step_in_date_c,
value_date_c,
yc._thisptr.get(),
- p.second.get(),
+ sc.get(),
True,
&fl_pv)
r += self.weights[i] * fl_pv
@@ -313,31 +332,25 @@ cdef class CreditIndex(CurveList):
def tweak_portfolio(self, double epsilon, maturity, bint inplace=True):
cdef:
TDate maturity_c = pydate_to_TDate(maturity)
- unsigned long mask = fill_mask(maturity_c, self.maturities,
- deref(self.curves.begin()).second)
+ unsigned long mask = fill_mask(maturity_c, self.maturities, self.curves[0])
vector[double] h = vector[double](self.T.size())
- TCurve* sc
- pair[string, shared_ptr[TCurve]] p
+ shared_ptr[TCurve] sc
- for p in self.curves:
- sc = p.second.get()
- tweak_curve(sc, sc, epsilon, h, self.T, mask)
+ for sc in self.curves:
+ tweak_curve(sc.get(), sc.get(), epsilon, h, self.T, mask)
- @cython.boundscheck(False)
def survival_matrix(self, TDate[:] schedule, d1=None):
cdef:
- pair[string, shared_ptr[TCurve]] p
- TCurve* sc
+ shared_ptr[TCurve] sc
TDate start_date
size_t i, j
np.npy_intp[2] n = [self.curves.size(), schedule.shape[0]]
np.ndarray[np.float64_t,ndim=2] sp = np.PyArray_EMPTY(2, n, np.NPY_DOUBLE, 0)
j = 0
- for p in self.curves:
- sc = p.second.get()
- start_date = sc.fBaseDate
+ for sc in self.curves:
+ start_date = sc.get().fBaseDate
for i in range(n[1]):
- sp[j,i] = JpmcdsForwardZeroPrice(sc, start_date, schedule[i])
+ sp[j,i] = JpmcdsForwardZeroPrice(sc.get(), start_date, schedule[i])
j += 1
return sp
@@ -403,7 +416,7 @@ cdef pair[TContingentLeg,TFeeLeg] get_legs(TDate maturity,
r.second = deref(fee_legs[i])
return r
-cdef double pv(unordered_map[string,shared_ptr[TCurve]]& curves,
+cdef double pv(vector[shared_ptr[TCurve]]& curves,
TDate base_date,
TDate step_in_date,
TDate value_date,
@@ -419,19 +432,19 @@ cdef double pv(unordered_map[string,shared_ptr[TCurve]]& curves,
cdef:
double fl_pv, cl_pv, r = 0
TCurve* tweaked_curve
- pair[string, shared_ptr[TCurve]] p
+ shared_ptr[TCurve] c
size_t i = 0
TFeeLeg* fl
TContingentLeg* cl
if epsilon != 0.:
- tweaked_curve = JpmcdsCopyCurve(deref(curves.begin()).second.get())
+ tweaked_curve = JpmcdsCopyCurve(curves[0].get())
- for p in curves:
+ for c in curves:
if epsilon != 0.:
- tweak_curve(p.second.get(), tweaked_curve, epsilon, h, T, mask)
+ tweak_curve(c.get(), tweaked_curve, epsilon, h, T, mask)
else:
- tweaked_curve = p.second.get()
+ tweaked_curve = c.get()
JpmcdsContingentLegPV(&legs.first,
base_date,
value_date,
@@ -440,6 +453,7 @@ cdef double pv(unordered_map[string,shared_ptr[TCurve]]& curves,
tweaked_curve,
recovery_rate,
&cl_pv)
+
JpmcdsFeeLegPV(&legs.second,
base_date,
step_in_date,
@@ -448,6 +462,7 @@ cdef double pv(unordered_map[string,shared_ptr[TCurve]]& curves,
tweaked_curve,
True,
&fl_pv)
+
r += weights[i] * (cl_pv - fl_pv * fixed_rate)
i += 1
return r