exchange_calendars

repository·master·Indexed 20 days ago

https://github.com/gerrymanoim/exchange_calendars

A Python library for defining and querying calendars for securities exchanges. It provides tools to manage trading sessions, breaks, and minute-level granularity using ISO-10383 market identifier codes (MIC). The library includes over 50 pre-defined calendars and supports the creation of custom calendars by subclassing ExchangeCalendar. It also features the ecal command line tool for printing Unix-style calendars in the terminal.

Tokens
41.4K
Snippets
127
Records
186
Agent score
70%

What's inside exchange_calendars

  1. Understand exchange open and closed times

    master

    The library defines an exchange as being open only during periods of regular trading.

    An exchange is considered closed during:

    • Pre-trading periods
    • Post-trading periods
    • Auction periods
    • Observed lunch breaks

    For a detailed explanation of how trading minutes are defined and how this logic has evolved (especially for users migrating from trading_calendars or versions prior to 3.4), refer to the minutes tutorial.

  2. Work with trading minutes

    master

    Minutes represent the granular time increments within a session. Use these methods to check minute-level status:

    • session_minutes(date): Returns a DatetimeIndex of all minutes in a session.
    • is_trading_minute(minute): Returns True if the specific minute is a trading minute (defaults to closed on the left side).
    • is_break_minute(minute): Returns True if the minute falls within a scheduled break.
    • previous_close(minute): Returns the timestamp of the most recent close.
    • previous_minute(minute): Returns the timestamp of the immediately preceding minute.
    import exchange_calendars as xcals
    
    xhkg = xcals.get_calendar("XHKG")
    
    # Get all minutes for a session
    print(xhkg.session_minutes("2022-01-03"))
    
    # Check if specific minutes are trading minutes
    mins = [ "2022-01-03 " + tm for tm in ["01:29", "01:30", "04:20", "07:59", "08:00"] ]
    print([ xhkg.is_trading_minute(m) for m in mins ])
    
    # Check if a minute is a break
    print(xhkg.is_break_minute("2022-01-03 04:20"))
    
    # Get previous close and minute
    print(xhkg.previous_close("2022-01-03 08:10"))
    print(xhkg.previous_minute("2022-01-03 08:10"))
  3. Work with exchange sessions

    master

    Sessions represent the full trading days. Use the following methods to interrogate sessions:

    • is_session(date): Returns True if the date is a trading session.
    • sessions_in_range(start, end): Returns a DatetimeIndex of all sessions within a range.
    • sessions_window(start, n): Returns a DatetimeIndex of the next n sessions starting from start.
    • date_to_session(date, direction="next"): Finds the nearest session in the specified direction.
    • previous_session(date): Returns the timestamp of the most recent previous session.
    • trading_index(start, end, period, force=False): Returns an IntervalIndex of trading periods (e.g., 90-minute intervals).
    import exchange_calendars as xcals
    import pandas as pd
    
    xnys = xcals.get_calendar("XNYS")
    
    # Check if a date is a session
    print(xnys.is_session("2022-01-01"))
    
    # Get sessions in a range
    print(xnys.sessions_in_range("2022-01-01", "2022-01-11"))
    
    # Get a window of sessions
    print(xnys.sessions_window("2022-01-03", 7))
    
    # Find next session
    print(xnys.date_to_session("2022-01-01", direction="next"))
    
    # Get previous session
    print(xnys.previous_session("2022-01-11"))
    
    # Get trading intervals
    xhkg = xcals.get_calendar("XHKG")
    print(xhkg.trading_index("2021-12-30", "2021-12-31", period="90min", force=True))
  4. Understand the calendar 'side' parameter

    master

    The side parameter determines how boundary minutes (open, close, break-start, and break-end) are treated regarding whether they are considered 'trading minutes'.

    In version 4.0.1+, the default side for all calendars is "left". This change impacts the selection of trading minutes when using window-based methods.

  5. Identify exchange calendars by ISO Code

    master

    Exchange calendars in this library are identified using their ISO-10383 market identifier code (MIC). When accessing or requesting a specific calendar, use the corresponding ISO Code.

    Examples of common ISO Codes include:

    • XNYS: New York Stock Exchange
    • XLON: London Stock Exchange
    • XTKS: Tokyo Stock Exchange
    • XETR: Xetra
    • XEUR: Eurex
  6. Update dependencies using uv

    master

    To update the project's dependencies and ensure the local environment is synchronized, follow these steps using uv:

    1. Create and switch to a new local deps branch.
    2. Upgrade the uv.lock file and sync your local environment:
      uv lock --upgrade
      uv sync
    3. Verify that all tests pass with the updated dependencies.
    4. Export the updated uv.lock to a requirements.txt file to maintain compatibility for non-uv clients:
      uv export --format requirements-txt --no-emit-project --no-hashes --no-dev -o requirements.txt
    5. Commit the changes and open a Pull Request to the main branch.
    uv lock --upgrade
    uv sync
    uv export --format requirements-txt --no-emit-project --no-hashes --no-dev -o requirements.txt
  7. Create a custom calendar

    master

    If a required exchange is not among the 50+ pre-defined calendars, you can create a custom calendar by subclassing ExchangeCalendar (found in exchange_calendars/exchange_calendar.py).

    To use your custom calendar within the library, you must register it using one of the following methods:

    • xcals.register_calendar: To register a specific calendar instance.
    • xcals.register_calendar_type: To register a calendar factory (the subclass itself).

    Once registered, you can access it via the standard get_calendar call.

    # Conceptual usage pattern
    import exchange_calendars as xcals
    
    class MyCustomCalendar(xcals.ExchangeCalendar):
        # Implement custom logic
        pass
    
    # Register the subclass as a factory
    xcals.register_calendar_type(MyCustomCalendar, 'MY_CUSTOM_EXCHANGE')
    
    # Access it via get_calendar
    cal = xcals.get_calendar('MY_CUSTOM_EXCHANGE')
  8. Migrate to exchange_calendars v4

    master

    When upgrading to version 4.0.1 or later, be aware of the following breaking changes and interface updates:

    • Timezone Handling: Sessions are now timezone-naive (previously UTC). Schedule columns now have the timezone set as UTC.
    • Column Renaming: The following schedule columns have been renamed:
      • market_open $\rightarrow$ open
      • market_close $\rightarrow$ close
    • Default Side: The default calendar side is now "left" (previously "right" for 24-hour calendars and "both" for others). This affects which minutes are considered trading minutes by default.
    • Window Methods: The count parameter in sessions_window and minutes_window now reflects the window length (previously it was window length + 1).
    • Deprecated Methods:
      • Use .opens[start:end] instead of sessions_opens.
      • Use .closes[start:end] instead of sessions_closes.
    • Python Version: The minimum supported Python version is 3.8.
  9. Contribute or fix an existing calendar

    master

    All exchange calendars in this project are maintained via user contributions. If you notice a missing holiday, incorrect trading times, or an incorrect lunch break, you should submit a Pull Request (PR) to the repository.

  10. Migration guide for method renames and deprecations

    master

    If you are upgrading from older versions of exchange_calendars, be aware of the following breaking changes and renames to ensure your code remains compatible with version 4.3 and later.

    Renames in version 4.0.3 (Removed in 4.3)

    • Use bound_min instead of bound_start.
    • Use bound_max instead of bound_end.

    Deprecations in version 4.0 (Removed in 4.3)

    • Instead of sessions_closes, use slicing on the .closes attribute: .closes[start:end].
    • Instead of sessions_opens, use slicing on the .opens attribute: .opens[start:end].

    Renames in version 3.4 (Removed in 4.0)

    Many methods were renamed to be more concise or consistent. Key changes include:

    • all_minutes $\rightarrow$ minutes
    • all_sessions $\rightarrow$ sessions
    • first_trading_minute $\rightarrow$ first_minute
    • last_trading_session $\rightarrow$ last_session
    • minute_to_session_label $\rightarrow$ minute_to_session
    • session_closes_in_range $\rightarrow$ sessions_closes
    • session_opens_in_range $\rightarrow$ sessions_opens
    • market_opens_nanos $\rightarrow$ opens_nanos
    • market_closes_nanos $\rightarrow$ closes_nanos

    Removed methods (Version 4.0)

    The following methods were removed in version 4.0:

    • execution_minute_for_session
    • execution_minute_for_sessions_in_range
    • execution_time_from_close
    • execution_time_from_open
  11. Get available calendars and retrieve a specific calendar

    master

    You can list all available exchange calendar names using xcals.get_calendar_names(). To work with a specific exchange, use xcals.get_calendar(name) with the exchange's identifier (e.g., 'XNYS' for New York Stock Exchange).

    import exchange_calendars as xcals
    
    # Get a list of available calendar names
    names = xcals.get_calendar_names(include_aliases=False)
    print(names[5:10])
    
    # Get a specific calendar
    xnys = xcals.get_calendar("XNYS")  # New York Stock Exchange
    xhkg = xcals.get_calendar("XHKG")  # Hong Kong Stock Exchange