diff options
| author | Guillaume Horel <guillaume.horel@gmail.com> | 2017-09-22 11:27:49 -0400 |
|---|---|---|
| committer | Guillaume Horel <guillaume.horel@gmail.com> | 2017-09-22 11:27:49 -0400 |
| commit | ff038af022cbc1c31d800753aeb22ba41445dfb6 (patch) | |
| tree | d42cf22d7f0f7e3ed5b265b1e34e47858ab9a75d | |
| parent | d1199cfd6346a5790051ca8a80c5a8f01df3baea (diff) | |
| download | pyisda-ff038af022cbc1c31d800753aeb22ba41445dfb6.tar.gz | |
fix memory issues
| -rw-r--r-- | pyisda/credit_index.pxd | 3 | ||||
| -rw-r--r-- | pyisda/credit_index.pyx | 125 |
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 |
