diff options
| author | Guillaume Horel <guillaume.horel@gmail.com> | 2018-03-20 11:22:23 -0400 |
|---|---|---|
| committer | Guillaume Horel <guillaume.horel@gmail.com> | 2018-03-20 12:39:39 -0400 |
| commit | 0bf22d5cdd35624345f0dadf78c5e3972ab10c10 (patch) | |
| tree | 75790a93a714bb62f757656b08128ed9898a34be | |
| parent | 81de457dcd815e739eaa8d36cd2c218aa68b7aa0 (diff) | |
| download | pyisda-0bf22d5cdd35624345f0dadf78c5e3972ab10c10.tar.gz | |
move to date file and fixes
| -rw-r--r-- | pyisda/curve.pyx | 112 | ||||
| -rw-r--r-- | pyisda/date.pxd | 3 | ||||
| -rw-r--r-- | pyisda/date.pyx | 113 |
3 files changed, 129 insertions, 99 deletions
diff --git a/pyisda/curve.pyx b/pyisda/curve.pyx index d4a34c1..0d35aa5 100644 --- a/pyisda/curve.pyx +++ b/pyisda/curve.pyx @@ -1,12 +1,9 @@ -from libc.math cimport log1p, log, nearbyint -from libc.stdio cimport printf - +from libc.math cimport log1p, log from date cimport (JpmcdsStringToDateInterval, pydate_to_TDate, dcc, TMonthDayYear, JpmcdsDateIntervalToFreq, JpmcdsDateFwdThenAdjust, TDate_to_pydate, - JpmcdsDateFromBusDaysOffset, JpmcdsStringToDayCountConv, ACT_360, - JpmcdsDateToMDY, JpmcdsMDYToDate, JpmcdsMakeDateInterval, - JpmcdsDtFwdAny, JpmcdsFormatDate, JpmcdsFormatDateInterval) + JpmcdsDateFromBusDaysOffset, JpmcdsStringToDayCountConv, ACT_360) from date import dcc_tostring +from date cimport _previous_twentieth, _roll_date from cdsone cimport JpmcdsStringToStubMethod, TStubMethod from legs cimport (JpmcdsCdsContingentLegMake, JpmcdsCdsFeeLegMake, JpmcdsContingentLegPV, JpmcdsFeeLegPV, FeeLegAI, JpmcdsFeeLegFree) @@ -17,7 +14,6 @@ import numpy as np np.import_array() import pandas as pd from cpython cimport Py_buffer -from numpy cimport npy_intp cdef extern from "Python.h": int PyMemoryView_Check(object) @@ -28,7 +24,7 @@ cdef extern from "numpy/arrayobject.h": int PyArray_CheckExact(object) void* PyArray_DATA(object) int PyArray_TYPE(object) - npy_intp PyArray_Size(object) + np.npy_intp PyArray_Size(object) cdef int SUCCESS = 0 @@ -44,87 +40,6 @@ cdef inline shared_ptr[TCurve] make_shared(TCurve* ptr) nogil: cdef inline void double_free(double* ptr) nogil: free(ptr) -cdef TDate previous_twentieth(TDate d) nogil: - cdef TMonthDayYear mdy - if JpmcdsDateToMDY(d, &mdy) != SUCCESS: - return -1 - if mdy.day < 20: - if mdy.month == 1: - mdy.month = 12 - mdy.year -= 1 - else: - mdy.month -= 1 - mdy.day = 20 - cdef int mod = mdy.month % 3 - if mod != 0: - mdy.month -= mod - if mdy.month <= 0: - mdy.month += 12 - mdy.year -= 1 - cdef TDate r - if JpmcdsMDYToDate(&mdy, &r) != SUCCESS: - return -1 - else: - return r - -cdef TDate next_twentieth(TDate d) nogil: - cdef TMonthDayYear mdy - if JpmcdsDateToMDY(d, &mdy) != SUCCESS: - return -1 - if mdy.day > 20: - if mdy.month == 12: - mdy.month = 1 - mdy.year += 1 - else: - mdy.month += 1 - mdy.day = 20 - cdef int mod = mdy.month % 3 - if mod != 0: - mdy.month += 3 - mod - if mdy.month > 12: - mdy.month -= 12 - mdy.year += 1 - cdef TDate r - if JpmcdsMDYToDate(&mdy, &r) != SUCCESS: - return -1 - else: - return r - -cpdef TDate roll_date(TDate d, double tenor): - cdef TDate cutoff = 151472 - cdef TDateInterval ivl - cdef TDate d_rolled - cdef TMonthDayYear d1 - if tenor < 1: - if JpmcdsMakeDateInterval(<int>nearbyint(tenor * 12), "M", &ivl) != SUCCESS: - return -1 - else: - if JpmcdsMakeDateInterval(<int>nearbyint(tenor), "A", &ivl) != SUCCESS: - return -1 - if JpmcdsDtFwdAny(d, &ivl, &d_rolled) != SUCCESS: - return -1 - if d <= cutoff: - return next_twentieth(d_rolled + 1) - else: - if JpmcdsDateToMDY(d, &d1) != SUCCESS: - return -1 - if ((d1.month > 9) or ((d1.month == 9) and (d1.day >= 20))) or \ - ((d1.month < 3) or ((d1.month == 3) and (d1.day < 20))): - if JpmcdsDateToMDY(d_rolled, &d1) != SUCCESS: - return -1 - if d1.month <= 3: - d1.year -= 1 - d1.month = 12 - d1.day = 20 - else: - if JpmcdsDateToMDY(d_rolled, &d1) != SUCCESS: - return -1 - d1.month = 6 - d1.day = 20 - if JpmcdsMDYToDate(&d1, &d_rolled) != SUCCESS: - return -1 - else: - return d_rolled cdef class Curve(object): @@ -558,7 +473,7 @@ cdef class SpreadCurve(Curve): cdef TDate start_date_c if start_date is None: - start_date_c = previous_twentieth(today_c) + start_date_c = _previous_twentieth(today_c) if start_date_c == -1: raise ValueError("incorrect today's date: " + today) else: @@ -596,20 +511,19 @@ cdef class SpreadCurve(Curve): i += 1 elif PyArray_CheckExact(end_dates): n_dates = PyArray_Size(end_dates) - if PyArray_TYPE(end_dates) == np.NPY_INT: + if PyArray_TYPE(end_dates) == np.NPY_INT64: end_dates_c = <TDate*>PyArray_DATA(end_dates) - for i in range(upfront_rates.shape[0]): - if upfront_rates[i] == upfront_rates[i]: - includes |= 1 << i elif PyArray_TYPE(end_dates) == np.NPY_DOUBLE: end_dates_c = <TDate*>malloc(n_dates * sizeof(TDate)) tenors_c = <double*>PyArray_DATA(end_dates) freeup = True - for i in range(n_dates): - end_dates_c[i] = roll_date(today_c, tenors_c[i]) - if upfront_rates[i] == upfront_rates[i]: - includes |= 1 << i - + _roll_date(today_c, tenors_c, n_dates, end_dates_c) + for i in range(upfront_rates.shape[0]): + if upfront_rates[i] == upfront_rates[i]: + includes |= 1 << i + else: + raise ValueError("end_dates need to be a list of dates, " + "or an array of tenors or TDates") cdef TStubMethod stub_type if JpmcdsStringToStubMethod(b"f/s", &stub_type) != 0: diff --git a/pyisda/date.pxd b/pyisda/date.pxd index 10693fc..b3ed150 100644 --- a/pyisda/date.pxd +++ b/pyisda/date.pxd @@ -50,3 +50,6 @@ cdef extern from "isda/busday.h": cpdef TDate pydate_to_TDate(c_datetime.date d) cpdef c_datetime.date TDate_to_pydate(TDate d) + +cdef void _roll_date(TDate d, double* tenors, int n_dates, TDate* output) nogil +cdef TDate _previous_twentieth(TDate d) nogil diff --git a/pyisda/date.pyx b/pyisda/date.pyx index 50cff66..5cca9d1 100644 --- a/pyisda/date.pyx +++ b/pyisda/date.pyx @@ -1,9 +1,15 @@ import datetime from cpython cimport datetime as c_datetime from cpython.version cimport PY_MAJOR_VERSION +from libc.stdlib cimport malloc, free +cimport cython +cimport numpy as np +np.import_array() c_datetime.import_datetime() +cdef int SUCCESS = 0 + cpdef TDate pydate_to_TDate(c_datetime.date d): return JpmcdsDate(<long>d.year, <long>d.month, <long>d.day) @@ -31,3 +37,110 @@ def dcc_tostring(long day_count): else: s = c_string return s + +cdef TDate _previous_twentieth(TDate d) nogil: + cdef TMonthDayYear mdy + if JpmcdsDateToMDY(d, &mdy) != SUCCESS: + return -1 + if mdy.day < 20: + if mdy.month == 1: + mdy.month = 12 + mdy.year -= 1 + else: + mdy.month -= 1 + mdy.day = 20 + cdef int mod = mdy.month % 3 + if mod != 0: + mdy.month -= mod + if mdy.month <= 0: + mdy.month += 12 + mdy.year -= 1 + cdef TDate r + if JpmcdsMDYToDate(&mdy, &r) != SUCCESS: + return -1 + else: + return r + +def previous_twentieth(d): + cdef TDate date = pydate_to_TDate(d) + return TDate_to_pydate(_previous_twentieth(date)) + +cdef TMonthDayYear next_twentieth(TDate d) nogil: + cdef TMonthDayYear mdy + JpmcdsDateToMDY(d, &mdy) + if mdy.day > 20: + if mdy.month == 12: + mdy.month = 1 + mdy.year += 1 + else: + mdy.month += 1 + mdy.day = 20 + cdef int mod = mdy.month % 3 + if mod != 0: + mdy.month += 3 - mod + if mdy.month > 12: + mdy.month -= 12 + mdy.year += 1 + return mdy + +cdef void _roll_date(TDate d, double* tenors, int n_dates, TDate* output) nogil: + cdef: + TDate cutoff = 151472 # 2015-09-20 + TMonthDayYear d_rolled + TMonthDayYear r + int months + size_t i + + if d <= cutoff: + d_rolled = next_twentieth(d + 1) + else: + JpmcdsDateToMDY(d, &d_rolled) + if ((d_rolled.month > 9) or ((d_rolled.month == 9) and (d_rolled.day >= 20))) or \ + ((d_rolled.month < 3) or ((d_rolled.month == 3) and (d_rolled.day < 20))): + if d_rolled.month <= 3: + d_rolled.year -= 1 + d_rolled.month = 12 + d_rolled.day = 20 + else: + d_rolled.month = 6 + d_rolled.day = 20 + + for i in range(n_dates): + r = d_rolled + if tenors[i] < 1: + months = <int>(tenors[i] * 12) + r.month += months + if r.month > 12: + r.month -= 12 + r.year += 1 + else: + r.year += <int>(tenors[i]) + if JpmcdsMDYToDate(&r, &output[i]) != SUCCESS: + output[i] = -1 + +@cython.boundscheck(False) +def roll_date(d, tenor): + cdef: + TDate date_ = pydate_to_TDate(d) + np.npy_intp n_dates + double* tenors_arr + double tenor_ + object output + long[:] output_view + size_t i + TDate output_date + + if isinstance(tenor, list): + n_dates = len(tenor) + tenors_arr = <double*>malloc(n_dates * sizeof(double)) + output = np.PyArray_EMPTY(1, &n_dates, np.NPY_INT64, 0) + output_view = output + for i in range(n_dates): + tenors_arr[i] = tenor[i] + _roll_date(date_, tenors_arr, n_dates, <TDate*>&output_view[0]) + free(tenors_arr) + return output + elif isinstance(tenor, (int, float)): + tenor_ = <double>tenor + _roll_date(date_, &tenor_, 1, &output_date) + return TDate_to_pydate(output_date) |
