summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuillaume Horel <guillaume.horel@gmail.com>2018-03-20 11:22:23 -0400
committerGuillaume Horel <guillaume.horel@gmail.com>2018-03-20 12:39:39 -0400
commit0bf22d5cdd35624345f0dadf78c5e3972ab10c10 (patch)
tree75790a93a714bb62f757656b08128ed9898a34be
parent81de457dcd815e739eaa8d36cd2c218aa68b7aa0 (diff)
downloadpyisda-0bf22d5cdd35624345f0dadf78c5e3972ab10c10.tar.gz
move to date file and fixes
-rw-r--r--pyisda/curve.pyx112
-rw-r--r--pyisda/date.pxd3
-rw-r--r--pyisda/date.pyx113
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)