From ea4ca5a28b9bf9c8eec3d727dc35b6863c1f5d01 Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Fri, 22 Feb 2019 17:11:42 -0500 Subject: bugfixes --- c_layer/curve.cpp | 40 +++++++++++++++++++++++++--------------- c_layer/curve.hpp | 24 ++++++++++++++++++------ pyisda/_curve.pxd | 9 +++------ pyisda/credit_index.pyx | 16 +++++++++------- pyisda/curve.pyx | 30 ++++++++++++------------------ pyisda/legs.pyx | 2 +- 6 files changed, 68 insertions(+), 53 deletions(-) diff --git a/c_layer/curve.cpp b/c_layer/curve.cpp index 2f84d01..221f27c 100644 --- a/c_layer/curve.cpp +++ b/c_layer/curve.cpp @@ -64,7 +64,7 @@ namespace pyisda { } } - void Curve::tweak(TCurve* const ptr, double epsilon) { + void Curve::tweak(TCurve* ptr, double epsilon) { double h1, h2, t1, t2, c; h1 = t1 = c = 0; TRatePt cur; @@ -79,18 +79,22 @@ namespace pyisda { } } - void Curve::tweak(TCurve* const ptr, double epsilon, unsigned long mask) { - double h1, h2, t1, t2, c; - h1 = t1 = c = 0; - TRatePt cur; - for(int i = 0;i < ptr->fNumItems; i++) { - cur = ptr->fArray[i]; - h2 = cur.fRate; - t2 = (cur.fDate - ptr->fBaseDate) / 365.; - c += (h2 * t2 - h1 * t1 ) * (1 + epsilon * (( mask >> i) & 1)); - cur.fRate = c / t2; - h1 = h2; - t1 = t2; + void Curve::tweak(TCurve* ptr, double epsilon, unsigned long mask) { + if (mask == 0) { + Curve::tweak(ptr, epsilon); + } else { + double h1, h2, t1, t2, c; + h1 = t1 = c = 0; + TRatePt cur; + for(int i = 0; i < ptr->fNumItems; i++) { + cur = ptr->fArray[i]; + h2 = cur.fRate; + t2 = (cur.fDate - ptr->fBaseDate) / 365.; + c += (h2 * t2 - h1 * t1 ) * (1 + epsilon * (( mask >> i) & 1)); + cur.fRate = c / t2; + h1 = h2; + t1 = t2; + }; } } @@ -117,7 +121,8 @@ namespace pyisda { } size_t SpreadCurve::size() { - return Curve::size() + recovery_rates.size() * sizeof(double) + 8; + return Curve::size() + recovery_rates.size() * sizeof(double) + + 8 + sizeof(TDate) + sizeof(Seniority); } unsigned char* SpreadCurve::serialize(unsigned char* const buf) { @@ -131,7 +136,12 @@ namespace pyisda { } else { ticker.copy((char*)cur, 8, 0); } - return cur + 8; + cur += 8; + memcpy(cur, &event_date, sizeof(TDate)); + cur += sizeof(TDate); + memcpy(cur, &seniority, sizeof(Seniority)); + cur += sizeof(Seniority); + return cur; } } diff --git a/c_layer/curve.hpp b/c_layer/curve.hpp index 5cc796a..39fdce9 100644 --- a/c_layer/curve.hpp +++ b/c_layer/curve.hpp @@ -5,6 +5,7 @@ #include "isda/bastypes.h" #include "isda/cdate.h" #include "isda/tcurve.h" +#include namespace pyisda { class Curve { @@ -17,7 +18,7 @@ namespace pyisda { ~Curve() { JpmcdsFreeTCurve(ptr); } - explicit operator TCurve*() const { return ptr; } + TCurve* get_TCurve() const {return ptr; } unsigned char* serialize(unsigned char* buf); double zeroPrice(const TDate date); double zeroPrice(const TDate date1, const TDate date2); @@ -36,7 +37,7 @@ namespace pyisda { public: YieldCurve(TCurve* const curve, const std::vector& dates) : Curve(curve), - dates(dates) {}; + dates(std::move(dates)) {}; YieldCurve(const YieldCurve &curve2) : Curve(curve2), dates(std::move(curve2.dates)) {}; @@ -47,18 +48,29 @@ namespace pyisda { class SpreadCurve : public Curve { public: + enum Seniority { + Senior, + Subordinated + }; + SpreadCurve(TCurve* const curve, const std::vector& recovery_rates, - const std::string& ticker) : + const std::string& ticker, TDate event_date = -1, + Seniority sen = Senior) : Curve(curve), recovery_rates(recovery_rates), - ticker(ticker) {}; + ticker(ticker), + event_date(event_date), + seniority(sen) {}; SpreadCurve(const SpreadCurve &curve2) : Curve(curve2), recovery_rates(std::move(curve2.recovery_rates)), - ticker(std::move(curve2.ticker)) {}; - + ticker(std::move(curve2.ticker)), + event_date(curve2.event_date), + seniority(curve2.seniority) {}; std::vector recovery_rates; std::string ticker; + TDate event_date; + SpreadCurve::Seniority seniority; size_t size(); unsigned char* serialize(unsigned char* buf); }; diff --git a/pyisda/_curve.pxd b/pyisda/_curve.pxd index 5d5a003..430a4ea 100644 --- a/pyisda/_curve.pxd +++ b/pyisda/_curve.pxd @@ -19,16 +19,13 @@ cdef extern from "curve.hpp" namespace "pyisda" nogil: Curve(TCurve*) Curve(const TCurve&) unsigned char* serialize(unsigned char*) - TCurve* operator() + TCurve* get_TCurve() const double zeroPrice(TDate d) double zeroPrice(TDate d1, TDate d2) - void tweak_mask "tweak" (double epsilon, unsigned long mask) - void tweak(double epsilon) + void tweak(double epsilon, unsigned long mask) @staticmethod - void tweak_mask_ "tweak" (const TCurve*, double epsilon, unsigned long mask) - @staticmethod - void tweak_ "tweak" (const TCurve*, double epsilon) + void tweak_static "tweak" (TCurve*, double epsilon, unsigned long mask) double survivalProb(const TDate, const TDate) double survivalProb(const TDate, const TDate, double eps) size_t size() diff --git a/pyisda/credit_index.pyx b/pyisda/credit_index.pyx index 76c77a1..7e93cd0 100644 --- a/pyisda/credit_index.pyx +++ b/pyisda/credit_index.pyx @@ -1,4 +1,5 @@ #cython: cdivision=True, boundscheck=False, c_string_type=unicode, c_string_encoding=ascii +# distutils: sources = c_layer/curve.cpp from libc.stdlib cimport malloc, free from libc.math cimport nan, isnan from libc.string cimport memcpy, memset @@ -471,7 +472,7 @@ cdef class CreditIndex(CurveList): step_in_date_c, cash_settle_date_c, yc.get_curve(), - deref(sc), + sc.get().get_TCurve(), True, &fl_pv) r += self._weights[i] * fl_pv @@ -498,12 +499,12 @@ cdef class CreditIndex(CurveList): size_t i if inplace: for i in range(self._curves.size()): - self._curves[i].get().tweak_mask(epsilon, mask) + self._curves[i].get().tweak(epsilon, mask) else: for i in range(self._curves.size()): sc_copy = new _curve.SpreadCurve( deref(<_curve.SpreadCurve*>(self._curves[i].get()))) - sc_copy.tweak_mask(epsilon, mask) + sc_copy.tweak(epsilon, mask) self._curves[i].reset(sc_copy) @@ -627,7 +628,7 @@ cdef double pv(const vector[shared_ptr[Curve]]& curves, cash_settle_date, step_in_date, yc, - deref(curve), + curve.get_TCurve(), recovery_rate, &cl_pv) JpmcdsFeeLegPV(legs.second, @@ -635,19 +636,20 @@ cdef double pv(const vector[shared_ptr[Curve]]& curves, step_in_date, cash_settle_date, yc, - deref(curve), + curve.get_TCurve(), True, &fl_pv) r += weights[i] * (cl_pv - fl_pv * fixed_rate) else: with parallel(): - tweaked_curve = JpmcdsCopyCurve(deref(curves[0].get())) + cl_pv = 0. fl_pv = 0. for i in prange(curves.size()): curve = <_curve.SpreadCurve*>(curves[i].get()) + tweaked_curve = JpmcdsCopyCurve(curve.get_TCurve()) recovery_rate = curve.recovery_rates[0] - _curve.Curve.tweak_mask_(tweaked_curve, epsilon, mask) + _curve.Curve.tweak_static(tweaked_curve, epsilon, mask) # FIXME: do something better if isnan(recovery_rate): recovery_rate = curve.recovery_rates[1] diff --git a/pyisda/curve.pyx b/pyisda/curve.pyx index cd12213..40d596d 100644 --- a/pyisda/curve.pyx +++ b/pyisda/curve.pyx @@ -6,7 +6,7 @@ from .date cimport (JpmcdsStringToDateInterval, pydate_to_TDate, dcc, TMonthDayY JpmcdsDateIntervalToFreq, JpmcdsDateFwdThenAdjust, TDate_to_pydate, JpmcdsDateFromBusDaysOffset, JpmcdsStringToDayCountConv, ACT_360, BadDay, FOLLOW, MODIFIED, NONE) -from date import dcc_tostring +from .date import dcc_tostring from .date cimport _previous_twentieth, _roll_date from .cdsone cimport JpmcdsStringToStubMethod, TStubMethod from .legs cimport (JpmcdsCdsContingentLegMake, JpmcdsCdsFeeLegMake, @@ -37,7 +37,7 @@ cdef int SUCCESS = 0 cdef class Curve(object): cdef inline TCurve* get_curve(self) nogil: - return (deref(self._thisptr)) + return self._thisptr.get().get_TCurve() def __getstate__(self): cdef: @@ -89,11 +89,11 @@ cdef class Curve(object): dict contains `base_date`, `basis`, `day_count_counvention` and `data` """ - cdef TCurve* curve = deref(self._thisptr) + cdef TCurve* curve = self.get_curve() return {'base_date': self.base_date, - 'basis': self.get_curve().fBasis, - 'day_count_convention': dcc_tostring(self.get_curve().fDayCountConv), - 'data': fArray_to_list(self.get_curve().fArray, self.get_curve().fNumItems)} + 'basis': curve.fBasis, + 'day_count_convention': dcc_tostring(curve.fDayCountConv), + 'data': fArray_to_list(curve.fArray, curve.fNumItems)} @cython.boundscheck(False) @cython.cdivision(True) @@ -127,10 +127,10 @@ cdef class Curve(object): def __iter__(self): cdef: - TCurve* curve = deref(self._thisptr) + TCurve* curve = self.get_curve() size_t i = 0 - TRatePt* it = self.get_curve().fArray - for i in range(self.get_curve().fNumItems): + TRatePt* it = curve.fArray + for i in range(curve.fNumItems): yield (TDate_to_pydate(it[i].fDate), it[i].fRate) def __len__(self): @@ -346,7 +346,6 @@ cdef class YieldCurve(Curve): cursor = deserialize(cursor, curve) - instance._thisptr = make_shared[_curve.Curve](curve) memcpy(&num_instr, cursor, sizeof(size_t)) cdef vector[TDate] dates = vector[TDate](num_instr) memcpy(dates.data(), cursor, num_instr * sizeof(TDate)) @@ -456,7 +455,6 @@ cdef class SpreadCurve(Curve): cdef TDate step_in_date_c cdef TDate cash_settle_date_c cdef TDate start_date_c - if start_date is None: start_date_c = _previous_twentieth(today_c, True) if start_date_c == -1: @@ -481,7 +479,6 @@ cdef class SpreadCurve(Curve): cdef size_t i cdef bint freeup = False cdef vector[double] recov - if cash_settle_date_c < yc.get_curve().fBaseDate: raise ValueError("cash_settle_date: {0} is anterior to yc's base_date: {1}". format(cash_settle_date, yc.base_date)) @@ -679,10 +676,7 @@ cdef class SpreadCurve(Curve): ) else: sc = self - if mask != 0: - sc._thisptr.get().tweak_mask(epsilon, mask) - else: - sc._thisptr.get().tweak(epsilon) + sc._thisptr.get().tweak(epsilon, mask) return sc @cython.boundscheck(False) @@ -717,8 +711,8 @@ cdef class SpreadCurve(Curve): ACT_360, b'M', b'NONE', - deref(yc._thisptr), - deref(self._thisptr), + yc.get_curve(), + self.get_curve(), &recovery_rates[0], par_spreads) free(end_dates_c) diff --git a/pyisda/legs.pyx b/pyisda/legs.pyx index 39e60e8..cce31ac 100644 --- a/pyisda/legs.pyx +++ b/pyisda/legs.pyx @@ -1,7 +1,7 @@ from cython.operator cimport dereference as deref from libc.stdlib cimport free from .date cimport pydate_to_TDate, TDate_to_pydate, dcc -from date import dcc_tostring +from .date import dcc_tostring from .cdsone cimport JpmcdsStringToStubMethod, TStubMethod from .curve cimport YieldCurve, SpreadCurve -- cgit v1.2.3-70-g09d2