Work with calendars
This guide will show you how to create and use business calendars in Deephaven. It covers the use of Deephaven's Python calendar API, and the use of a Java BusinessCalendar
object from both Python and Deephaven tables.
The Python API is minimal - it allows users to add or remove calendars, as well as get a calendar. The returned calendar is a Java BusinessCalendar
object. This object is easier to use in table operations than a Python object and minimizes Python-Java boundary crossings, which improves performance.
Get a calendar
Getting a calendar is simple. The code block below lists the available calendars and grabs the USNYSE_EXAMPLE
calendar.
from deephaven.calendar import calendar_names, calendar
print(calendar_names())
nyse_cal = calendar("USNYSE_EXAMPLE")
print(type(nyse_cal))
- Log
We can see from the output that nyse_cal
is an io.deephaven.time.calendar.BusinessCalendar
object. It's Deephaven's Java business calendar object. Don't fret at the mention of Java - you don't need to be a Java developer to use it. A BusinessCalendar
has many different methods available that can be useful in queries. The sections below explore those uses.
Business calendar use
Input data types
All of a BusinessCalendar
's methods take either strings or Java date-time data types as input. Java's date-time types include:
Deephaven has built-in functionalities for converting to and from these data types. The methods will be used in examples below.
Create data
Before we can demonstrate the use of business calendars in queries, we'll need to create a table with some data. The following code block creates a month's worth of date-time data spaced 3 hours apart.
from deephaven import empty_table
source = empty_table(8 * 31 + 1).update(
[
"Timestamp = '2024-01-01T00:00:00 ET' + i * 3 * HOUR",
"Value = randomDouble(100.0, 200.0)",
]
)
- source
Business days and business time
The following example calculates the number of business days and non-business days (weekends & holidays) between two timestamps.
result = source.update(
[
"NumBizDays = nyse_cal.numberBusinessDates('2024-01-01T00:00:00 ET', Timestamp)",
"NumNonBizDays = nyse_cal.numberNonBusinessDates('2024-01-01T00:00:00 ET', Timestamp)",
]
)
- result
The following example limits the data to only business days, and then only plots data that takes place during business hours.
The source
table is filtered twice to create two result tables. The first contains only data that takes place during an NYSE business day, while the second contains only data that takes place during NYSE business hours.
result_bizdays = source.where(["nyse_cal.isBusinessDay(Timestamp)"])
result_bizhours = source.where(["nyse_cal.isBusinessTime(Timestamp)"])
- result_bizdays
- result_bizhours
The tables created in the previous code block could be used to plot data occurring only during business days/hours. When plotting this type of data, the recommended practice is to use an axis
to limit the data to business time only. The following code block plots only data that occurs during NYSE business time.
from deephaven.plot.figure import Figure
bizday_plot = (
Figure()
.axis(dim=0, business_time=True, calendar=nyse_cal)
.plot_xy(series_name="Business day data", t=source, x="Timestamp", y="Value")
.show()
)
- bizday_plot
Create a calendar
Deephaven offers three pre-built calendars for use: UTC
, USNYSE_EXAMPLE
, and USBANK_EXAMPLE
.
The calendars that come with Deephaven are meant to serve as examples. They may not be updated. Deephaven recommends users create their own calendars.
The calendar configuration files can be found here. They use XML to define the properties of the calendar, which include:
- Valid date range
- Country and time zone
- Description
- Operating hours
- Holidays
- More
Users can build their own calendar by creating a calendar file using the format described in this Javadoc. This section goes over an example of using a custom-built calendar for a hypothetical business for the year 2024.
This example uses a calendar file found in Deephaven's examples repository. This guide assumes you have the file on your local machine in the /data mount point. This hypothetical business is called "Company Y", and the calendar only covers the year 2024.
The calendar file
A calendar XML file contains top-level information about the calendar itself, business days, business hours, and holidays. While most business calendars have a single business period (e.g., 9am - 5pm), some use two distinct business periods separated by a lunch break. The test calendar file below has two distinct periods: from 8am - 12pm and from 1pm - 5pm. It also specifies a series of holidays over the course of the 2024 calendar year, which includes two half-holidays in which business is open for the first of the two business periods. Calendars typically contain data for more than one year, but this example limits it to 2024 only.
The TestCalendar_2024.calendar
file can be found here. To see its contents, expand the file below. For the examples that use this calendar, it's placed in the folder /data/examples/Calendar/
in the Deephaven Docker container.
Test calendar for 2024
<calendar>
<name>TestCalendar_2024</name>
<timeZone>America/New_York</timeZone>
<language>en</language>
<country>US</country>
<firstValidDate>2024-01-01</firstValidDate>
<lastValidDate>2024-12-31</lastValidDate>
<description>
Test calendar for the year 2024.
This calendar uses two business periods instead of one.
The periods are separated by a one hour lunch break.
This calendar file defines standard business hours, weekends, and holidays.
</description>
<default>
<businessTime><open>08:00</open><close>12:00</close><open>13:00</open><close>17:00</close></businessTime>
<weekend>Saturday</weekend>
<weekend>Sunday</weekend>
</default>
<holiday>
<date>2024-01-01</date>
</holiday>
<holiday>
<date>2024-01-15</date>
</holiday>
<holiday>
<date>2024-02-19</date>
</holiday>
<holiday>
<date>2024-03-29</date>
</holiday>
<holiday>
<date>2024-04-01</date>
<businessTime><open>08:00</open><close>12:00</close></businessTime>
</holiday>
<holiday>
<date>2024-05-27</date>
</holiday>
<holiday>
<date>2024-07-04</date>
</holiday>
<holiday>
<date>2024-09-02</date>
</holiday>
<holiday>
<date>2024-10-31</date>
<businessTime><open>08:00</open><close>12:00</close></businessTime>
</holiday>
<holiday>
<date>2024-11-28</date>
</holiday>
<holiday>
<date>2024-11-29</date>
</holiday>
<holiday>
<date>2024-12-25</date>
</holiday>
<holiday>
<date>2024-12-26</date>
</holiday>
</calendar>
For more information on formatting custom calendars, see the XML Parser Javadoc.
Use the new calendar
Add the calendar to the set of available calendars
There are two ways to add a calendar to the set of available calendars.
The first and simplest way to do so is through the Python calendar API. The following code block shows how it's done using the path to the calendar file just created.
from deephaven.calendar import add_calendar
add_calendar("/data/examples/Calendar/TestCalendar_2024.calendar")
The second way is through the configuration property Calendar.importPath
. This should point to a text file with line-separated locations of any calendar files to load by default. Say your Docker configuration has a /data/Calendar
folder that contains three calendar files: MyCalendar.calendar
, TestCalendar_2024.calendar
, CrazyCalendar.calendar
. The text file, which we'll name calendar_imports.txt
and place in the root of your Deephaven deployment, would look as follows:
/data/Calendar/MyCalendar.calendar
/data/Calendar/TestCalendar_2024.calendar
/data/Calendar/CrazyCalendar.calendar
To make Deephaven load this list of calendars automatically upon startup via docker compose
, you can set the property directly:
services:
deephaven:
image: ghcr.io/deephaven/server:${VERSION:-latest}
ports:
- '${DEEPHAVEN_PORT:-10000}:10000'
volumes:
- ./data:/data
environment:
- START_OPTS=-Xmx4g -DCalendar.importPath="/calendar_imports.txt"
Alternatively, a configuration file could be used to set the property.
Get an instance of the new calendar
from deephaven.calendar import calendar
test_2024_cal = calendar("TestCalendar_2024")
Happy calendar-ing!