Converting Pandas Datetimes to QuantLib Dates
Summary
The document addresses a Python interoperability issue when converting pandas timestamps into QuantLib dates for financial calculations. The original example extracts year, month, and day into a dataframe and constructs QuantLib dates row by row. That construction fails in a function unless the components are explicitly cast to integers, even though a similar dataframe apply expression appeared to work outside the function.
The accepted answer recommends using QuantLib’s conversion method from a Python date object, applying it directly to the pandas date series. The example then uses the resulting QuantLib dates with an Actual/365 Fixed day counter, while noting that QuantLib is useful for conventions such as 30/360. The response offers a practical conversion route but does not explain the differing inferred scalar types behind the original behavior or discuss vectorization and performance.
Key ideas
- QuantLib date construction may reject dataframe values that are not passed as native integers.
- QuantLib provides a conversion method from Python dates that can simplify timestamp handling.
- Converted dates can be used with QuantLib day-count conventions.
- The answer demonstrates a practical workaround but does not diagnose the original type inconsistency.
Tags
Full text
# I create a dataframe with
# Converting pandas datetime to QuantLib dates: why do the inputs need to be converted to int only some times? It seems random
I am trying to use the QuantLib library with Python.
In the example below, I create a pandas dataframe with some dates and some cashflows, convert the dates from pandas' format to QuantLib's, and use QuantLib to calculate the daycount (which is banal for act/365, but QuantLib comes in handy for other cases like 30/360). There is probably room to make it more efficient (vectorise it somehow?) but it works.
I then tried to make a function that converts pandas datetime to QuantLib's dates, but it doesn't work, even if the code is the very same!
```
TypeError: Wrong number or type of arguments for overloaded function 'new_Date'.
```
It's the same dataframe apply statement. If, however, I pass `int(x['day'])` instead of just `x['day']` , then it works.
Why would this be? pd.DatetimeIndex returns an integer, not a float. Why does the apply statement not require conversion of the inputs to integer if run outside of a function, but requires it if run within a function? I don't get it!
```
import QuantLib as ql
import pandas as pd
from datetime import date
import numpy as np
# I create a dataframe with
# investment in which we pay 100 in the first month, then get 2 each month for the next 59 months
d0 = pd.to_datetime(date(2010,1,1))
df = pd.DataFrame()
df['month #'] = np.arange(0,60)
df['dates'] = df.apply( lambda x: d0 + pd.DateOffset(months = x['month #']) , axis = 1 )
df['cf'] = 0
df.iloc[0,2] = -100
df.iloc[1:,2] = 2
df['year'] = pd.DatetimeIndex(df['dates']).year
df['month'] = pd.DatetimeIndex(df['dates']).month
df['day'] = pd.DatetimeIndex(df['dates']).day
# Now I use pandas apply to add a column which contains the same dates, but in qlib format
df['qldate'] = df.apply( lambda x: ql.Date(x['day'], x['month'], x['year'] ) , axis = 1)
#now I use qlib to calculate the day count
# NB: actual 365 is easy to calculate manually, but qlib comes in handy for other daycount conventions
# so we don't reinvent the wheel
df['dayc act 365'] = df.apply( lambda x: ql.Actual365Fixed().dayCount(df['qldate'][0], x['qldate']) , axis =1 )
def date_pd_to_ql(pdate):
df = pd.DataFrame()
df['year'] = pd.DatetimeIndex(pdate).year
df['month'] = pd.DatetimeIndex(pdate).month
df['day'] = pd.DatetimeIndex(pdate).day
# this works:
out = df.apply( lambda x: ql.Date(int(x['day']), int(x['month']), int(x['year']) ) , axis = 1 )
# but this doesn't:
out = df.apply( lambda x: ql.Date(x['day'], x['month'], x['year'] ) , axis = 1 )
return out
out = date_pd_to_ql(df['dates'])
```
## Answer by David Duarte (score 5, accepted)
https://quant.stackexchange.com/a/60994
You could just use the `ql.Date().from_date` method.
Example:
```
d0 = pd.to_datetime(date(2010,1,1))
df = pd.DataFrame()
df['month #'] = np.arange(0,60)
df['dates'] = df.apply( lambda x: d0 + pd.DateOffset(months = x['month #']) , axis = 1 )
df['cf'] = 0
df.iloc[0,2] = -100
df.iloc[1:,2] = 2
df['qldate'] = df.dates.apply(ql.Date().from_date)
df['dayc act 365'] = df.apply( lambda x: ql.Actual365Fixed().dayCount(df['qldate'][0], x['qldate']) , axis =1 )
df.head()
```Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.