Home

Awesome

exchange_calendars

PyPI Python Support PyPI Downloads Code style: black

A Python library for defining and querying calendars for security exchanges.

Calendars for more than 50 exchanges available out-the-box! If you still can't find the calendar you're looking for, create a new one!

Installation

$ pip install exchange_calendars

Quick Start

import exchange_calendars as xcals

Get a list of available calendars:

>>> xcals.get_calendar_names(include_aliases=False)[5:10]
['CMES', 'IEPA', 'XAMS', 'XASX', 'XBKK']

Get a calendar:

>>> xnys = xcals.get_calendar("XNYS")  # New York Stock Exchange
>>> xhkg = xcals.get_calendar("XHKG")  # Hong Kong Stock Exchange

Query the schedule:

>>> xhkg.schedule.loc["2021-12-29":"2022-01-04"]
<!-- base of output from `xhkg.schedule.loc["2021-12-29":"2022-01-04"].to_html()` --> <table border="1" class="dataframe" style="width: 100%"> <colgroup> <col span="1" style="width: 20%;"> <col span="1" style="width: 20%;"> <col span="1" style="width: 20%;"> <col span="1" style="width: 20%;"> <col span="1" style="width: 20%;"> </colgroup> <thead> <tr style="text-align: right; font-size: 13px"> <th></th> <th>open</th> <th>break_start</th> <th>break_end</th> <th>close</th> </tr> </thead> <tbody style="text-align: right; font-size: 11px"> <tr> <th>2021-12-29</th> <td>2021-12-29 01:30:00+00:00</td> <td>2021-12-29 04:00:00+00:00</td> <td>2021-12-29 05:00:00+00:00</td> <td>2021-12-29 08:00:00+00:00</td> </tr> <tr> <th>2021-12-30</th> <td>2021-12-30 01:30:00+00:00</td> <td>2021-12-30 04:00:00+00:00</td> <td>2021-12-30 05:00:00+00:00</td> <td>2021-12-30 08:00:00+00:00</td> </tr> <tr> <th>2021-12-31</th> <td>2021-12-31 01:30:00+00:00</td> <td>NaT</td> <td>NaT</td> <td>2021-12-31 04:00:00+00:00</td> </tr> <tr> <th>2022-01-03</th> <td>2022-01-03 01:30:00+00:00</td> <td>2022-01-03 04:00:00+00:00</td> <td>2022-01-03 05:00:00+00:00</td> <td>2022-01-03 08:00:00+00:00</td> </tr> <tr> <th>2022-01-04</th> <td>2022-01-04 01:30:00+00:00</td> <td>2022-01-04 04:00:00+00:00</td> <td>2022-01-04 05:00:00+00:00</td> <td>2022-01-04 08:00:00+00:00</td> </tr> </tbody> </table>

Working with sessions

>>> xnys.is_session("2022-01-01")
False

>>> xnys.sessions_in_range("2022-01-01", "2022-01-11")
DatetimeIndex(['2022-01-03', '2022-01-04', '2022-01-05', '2022-01-06',
               '2022-01-07', '2022-01-10', '2022-01-11'],
              dtype='datetime64[ns]', freq='C')

>>> xnys.sessions_window("2022-01-03", 7)
DatetimeIndex(['2022-01-03', '2022-01-04', '2022-01-05', '2022-01-06',
               '2022-01-07', '2022-01-10', '2022-01-11'],
              dtype='datetime64[ns]', freq='C')

>>> xnys.date_to_session("2022-01-01", direction="next")
Timestamp('2022-01-03 00:00:00', freq='C')

>>> xnys.previous_session("2022-01-11")
Timestamp('2022-01-10 00:00:00', freq='C')

>>> xhkg.trading_index(
...     "2021-12-30", "2021-12-31", period="90min", force=True
... )
IntervalIndex([[2021-12-30 01:30:00, 2021-12-30 03:00:00), [2021-12-30 03:00:00, 2021-12-30 04:00:00), [2021-12-30 05:00:00, 2021-12-30 06:30:00), [2021-12-30 06:30:00, 2021-12-30 08:00:00), [2021-12-31 01:30:00, 2021-12-31 03:00:00), [2021-12-31 03:00:00, 2021-12-31 04:00:00)], dtype='interval[datetime64[ns, UTC], left]')

See the sessions tutorial for a deeper dive into sessions.

Working with minutes

>>> xhkg.session_minutes("2022-01-03")
DatetimeIndex(['2022-01-03 01:30:00+00:00', '2022-01-03 01:31:00+00:00',
               '2022-01-03 01:32:00+00:00', '2022-01-03 01:33:00+00:00',
               '2022-01-03 01:34:00+00:00', '2022-01-03 01:35:00+00:00',
               '2022-01-03 01:36:00+00:00', '2022-01-03 01:37:00+00:00',
               '2022-01-03 01:38:00+00:00', '2022-01-03 01:39:00+00:00',
               ...
               '2022-01-03 07:50:00+00:00', '2022-01-03 07:51:00+00:00',
               '2022-01-03 07:52:00+00:00', '2022-01-03 07:53:00+00:00',
               '2022-01-03 07:54:00+00:00', '2022-01-03 07:55:00+00:00',
               '2022-01-03 07:56:00+00:00', '2022-01-03 07:57:00+00:00',
               '2022-01-03 07:58:00+00:00', '2022-01-03 07:59:00+00:00'],
              dtype='datetime64[ns, UTC]', length=330, freq=None)

>>> mins = [ "2022-01-03 " + tm for tm in ["01:29", "01:30", "04:20", "07:59", "08:00"] ]
>>> [ xhkg.is_trading_minute(minute) for minute in mins ]
[False, True, False, True, False]  # by default minutes are closed on the left side

>>> xhkg.is_break_minute("2022-01-03 04:20")
True

>>> xhkg.previous_close("2022-01-03 08:10")
Timestamp('2022-01-03 08:00:00+0000', tz='UTC')

>>> xhkg.previous_minute("2022-01-03 08:10")
Timestamp('2022-01-03 07:59:00+0000', tz='UTC')

Check out the minutes tutorial for a deeper dive that includes an explanation of the concept of 'minutes' and how the "side" option determines which minutes are treated as trading minutes.

Tutorials

Hopefully you'll find that exchange_calendars has the method you need to get the information you want. If it doesn't, either PR it or raise an issue and let us know!

Command Line Usage

Print a unix-cal like calendar straight from the command line (holidays are indicated by brackets)...

ecal XNYS 2020
                                        2020
        January                        February                        March
Su  Mo  Tu  We  Th  Fr  Sa     Su  Mo  Tu  We  Th  Fr  Sa     Su  Mo  Tu  We  Th  Fr  Sa
            [ 1]  2   3 [ 4]                           [ 1]
[ 5]  6   7   8   9  10 [11]   [ 2]  3   4   5   6   7 [ 8]   [ 1]  2   3   4   5   6 [ 7]
[12] 13  14  15  16  17 [18]   [ 9] 10  11  12  13  14 [15]   [ 8]  9  10  11  12  13 [14]
[19][20] 21  22  23  24 [25]   [16][17] 18  19  20  21 [22]   [15] 16  17  18  19  20 [21]
[26] 27  28  29  30  31        [23] 24  25  26  27  28 [29]   [22] 23  24  25  26  27 [28]
                                                              [29] 30  31

        April                           May                            June
Su  Mo  Tu  We  Th  Fr  Sa     Su  Mo  Tu  We  Th  Fr  Sa     Su  Mo  Tu  We  Th  Fr  Sa
              1   2   3 [ 4]                         1 [ 2]         1   2   3   4   5 [ 6]
[ 5]  6   7   8   9 [10][11]   [ 3]  4   5   6   7   8 [ 9]   [ 7]  8   9  10  11  12 [13]
[12] 13  14  15  16  17 [18]   [10] 11  12  13  14  15 [16]   [14] 15  16  17  18  19 [20]
[19] 20  21  22  23  24 [25]   [17] 18  19  20  21  22 [23]   [21] 22  23  24  25  26 [27]
[26] 27  28  29  30            [24][25] 26  27  28  29 [30]   [28] 29  30
                               [31]

            July                          August                       September
Su  Mo  Tu  We  Th  Fr  Sa     Su  Mo  Tu  We  Th  Fr  Sa     Su  Mo  Tu  We  Th  Fr  Sa
              1   2 [ 3][ 4]                           [ 1]             1   2   3   4 [ 5]
[ 5]  6   7   8   9  10 [11]   [ 2]  3   4   5   6   7 [ 8]   [ 6][ 7]  8   9  10  11 [12]
[12] 13  14  15  16  17 [18]   [ 9] 10  11  12  13  14 [15]   [13] 14  15  16  17  18 [19]
[19] 20  21  22  23  24 [25]   [16] 17  18  19  20  21 [22]   [20] 21  22  23  24  25 [26]
[26] 27  28  29  30  31        [23] 24  25  26  27  28 [29]   [27] 28  29  30
                               [30] 31

        October                        November                       December
Su  Mo  Tu  We  Th  Fr  Sa     Su  Mo  Tu  We  Th  Fr  Sa     Su  Mo  Tu  We  Th  Fr  Sa
                  1   2 [ 3]                                            1   2   3   4 [ 5]
[ 4]  5   6   7   8   9 [10]   [ 1]  2   3   4   5   6 [ 7]   [ 6]  7   8   9  10  11 [12]
[11] 12  13  14  15  16 [17]   [ 8]  9  10  11  12  13 [14]   [13] 14  15  16  17  18 [19]
[18] 19  20  21  22  23 [24]   [15] 16  17  18  19  20 [21]   [20] 21  22  23  24 [25][26]
[25] 26  27  28  29  30 [31]   [22] 23  24  25 [26] 27 [28]   [27] 28  29  30  31
                               [29] 30
ecal XNYS 1 2020
        January 2020
Su  Mo  Tu  We  Th  Fr  Sa
            [ 1]  2   3 [ 4]
[ 5]  6   7   8   9  10 [11]
[12] 13  14  15  16  17 [18]
[19][20] 21  22  23  24 [25]
[26] 27  28  29  30  31

Frequently Asked Questions

How can I create a new calendar?

First off, make sure the calendar you're after hasn't already been defined; exchange calendars comes with over 50 pre-defined calendars, including major security exchanges.

If you can't find what you're after, a custom calendar can be created as a subclass of ExchangeCalendar. This workflow describes the process to add a new calendar to exchange_calendars. Just follow the relevant parts.

To access the new calendar via get_calendar call either xcals.register_calendar or xcals.register_calendar_type to register, respectively, a specific calendar instance or a calendar factory (i.e. the subclass).

Can I contribute a new calendar to exchange calendars?

Yes please! The workflow can be found here.

<calendar> is missing a holiday, has a wrong time, should have a break etc...

All of the exchange calendars are maintained by user contributions. If a calendar you care about needs revising, please open a PR - that's how this thing works! (Never contributed to a project before and it all seems a bit daunting? Check this out and don't look back!)

You'll find the workflow to modify an existing calendar here.

What times are considered open and closed?

exchange_calendars attempts to be broadly useful by considering an exchange to be open only during periods of regular trading. During any pre-trading, post-trading or auction period the exchange is treated as closed. An exchange is also treated as closed during any observed lunch break.

See the minutes tutorial for a detailed explanation of which minutes an exchange is considered open over. If you previously used trading_calendars, or exchange_calendars prior to release 3.4, then this is the place to look for answers to questions of how the definition of trading minutes has changed over time (and is now stable and flexible!).

Calendars

ExchangeISO CodeCountryVersion AddedExchange Website (English)
New York Stock ExchangeXNYSUSA1.0https://www.nyse.com/index
CBOE FuturesXCBFUSA1.0https://markets.cboe.com/us/futures/overview/
Chicago Mercantile ExchangeCMESUSA1.0https://www.cmegroup.com/
ICE USIEPAUSA1.0https://www.theice.com/index
Toronto Stock ExchangeXTSECanada1.0https://www.tsx.com/
BMF BovespaBVMFBrazil1.0http://www.b3.com.br/en_us/
London Stock ExchangeXLONEngland1.0https://www.londonstockexchange.com/
Euronext AmsterdamXAMSNetherlands1.2https://www.euronext.com/en/regulation/amsterdam
Euronext BrusselsXBRUBelgium1.2https://www.euronext.com/en/regulation/brussels
Euronext LisbonXLISPortugal1.2https://www.euronext.com/en/regulation/lisbon
Euronext ParisXPARFrance1.2https://www.euronext.com/en/regulation/paris
Frankfurt Stock ExchangeXFRAGermany1.2http://en.boerse-frankfurt.de/
SIX Swiss ExchangeXSWXSwitzerland1.2https://www.six-group.com/en/home.html
Tokyo Stock ExchangeXTKSJapan1.2https://www.jpx.co.jp/english/
Australian Securities ExchangeXASXAustralia1.3https://www.asx.com.au/
Bolsa de MadridXMADSpain1.3https://www.bolsamadrid.es
Borsa ItalianaXMILItaly1.3https://www.borsaitaliana.it
New Zealand ExchangeXNZENew Zealand1.3https://www.nzx.com/
Wiener BorseXWBOAustria1.3https://www.wienerborse.at/en/
Hong Kong Stock ExchangeXHKGHong Kong1.3https://www.hkex.com.hk/?sc_lang=en
Copenhagen Stock ExchangeXCSEDenmark1.4http://www.nasdaqomxnordic.com/
Helsinki Stock ExchangeXHELFinland1.4http://www.nasdaqomxnordic.com/
Stockholm Stock ExchangeXSTOSweden1.4http://www.nasdaqomxnordic.com/
Oslo Stock ExchangeXOSLNorway1.4https://www.oslobors.no/ob_eng/
Irish Stock ExchangeXDUBIreland1.4http://www.ise.ie/
Bombay Stock ExchangeXBOMIndia1.5https://www.bseindia.com
Singapore ExchangeXSESSingapore1.5https://www.sgx.com
Shanghai Stock ExchangeXSHGChina1.5http://english.sse.com.cn
Korea ExchangeXKRXSouth Korea1.6http://global.krx.co.kr
Iceland Stock ExchangeXICEIceland1.7http://www.nasdaqomxnordic.com/
Poland Stock ExchangeXWARPoland1.9http://www.gpw.pl
Santiago Stock ExchangeXSGOChile1.9https://www.bolsadesantiago.com/
Colombia Securities ExchangeXBOGColombia1.9https://www.bvc.com.co/nueva/https://www.bvc.com.co/nueva/
Mexican Stock ExchangeXMEXMexico1.9https://www.bmv.com.mx
Lima Stock ExchangeXLIMPeru1.9https://www.bvl.com.pe
Prague Stock ExchangeXPRACzech Republic1.9https://www.pse.cz/en/
Budapest Stock ExchangeXBUDHungary1.10https://bse.hu/
Athens Stock ExchangeASEXGreece1.10http://www.helex.gr/
Istanbul Stock ExchangeXISTTurkey1.10https://www.borsaistanbul.com/en/
Johannesburg Stock ExchangeXJSESouth Africa1.10https://www.jse.co.za/z
Malaysia Stock ExchangeXKLSMalaysia1.11http://www.bursamalaysia.com/market/
Moscow ExchangeXMOSRussia1.11https://www.moex.com/en/
Philippine Stock ExchangeXPHSPhilippines1.11https://www.pse.com.ph/
Stock Exchange of ThailandXBKKThailand1.11https://www.set.or.th/set/mainpage.do?language=en&country=US
Indonesia Stock ExchangeXIDXIndonesia1.11https://www.idx.co.id/
Taiwan Stock Exchange Corp.XTAITaiwan1.11https://www.twse.com.tw/en/
Buenos Aires Stock ExchangeXBUEArgentina1.11https://www.bcba.sba.com.ar/
Pakistan Stock ExchangeXKARPakistan1.11https://www.psx.com.pk/
XetraXETRGermany2.1https://www.xetra.com/
Tel Aviv Stock ExchangeXTAEIsrael2.1https://www.tase.co.il/
Astana International ExchangeAIXKKazakhstan3.2https://www.aix.kz/
Bucharest Stock ExchangeXBSERomania3.2https://www.bvb.ro/
Saudi Stock ExchangeXSAUSaudi Arabia4.2https://www.saudiexchange.sa/
European Energy Exchange AGXEEEGermany4.5.5https://www.eex.com
Hamburg Stock ExchangeXHAMGermany4.5.5https://www.boerse-hamburg.de
Duesseldorf Stock ExchangeXDUSGermany4.5.5https://www.boerse-duesseldorf.de

Note that exchange calendars are defined by their ISO-10383 market identifier code.

market-prices

Much of the post v3 development of exchange_calendars has been driven by the market_prices library. Check it out if you like the idea of using exchange_calendars to create meaningful OHLCV datasets. It works out-the-box with freely available data!

Deprecations and Renaming

Methods renamed in version 4.0.3 and removed in 4.3

Previous nameNew name
bound_startbound_min
bound_endbound_max

Methods deprecated in 4.0 and removed in 4.3

Deprecated methodReason
sessions_closesuse .closes[start:end]
sessions_opensuse .opens[start:end]

Methods with a parameter renamed in 4.0

Method
is_session
is_open_on_minute
minutes_in_range
minutes_window
next_close
next_minute
next_open
previous_close
previous_minute
previous_open
session_break_end
session_break_start
session_close
session_open
sessions_in_range
sessions_window

Methods renamed in version 3.4 and removed in 4.0

Previous nameNew name
all_minutesminutes
all_minutes_nanosminutes_nanos
all_sessionssessions
break_start_and_end_for_sessionsession_break_start_end
date_to_session_labeldate_to_session
first_trading_minutefirst_minute
first_trading_sessionfirst_session
has_breakssessions_has_break
last_trading_minutelast_minute
last_trading_sessionlast_session
next_session_labelnext_session
open_and_close_for_sessionsession_open_close
previous_session_labelprevious_session
market_break_ends_nanosbreak_ends_nanos
market_break_starts_nanosbreak_starts_nanos
market_closes_nanoscloses_nanos
market_opens_nanosopens_nanos
minute_index_to_session_labelsminutes_to_sessions
minute_to_session_labelminute_to_session
minutes_count_for_sessions_in_rangesessions_minutes_count
minutes_for_sessionsession_minutes
minutes_for_sessions_in_rangesessions_minutes
session_closes_in_rangesessions_closes
session_distancesessions_distance
session_opens_in_rangesessions_opens

Other methods deprecated in 3.4 and removed in 4.0

Removed Method
execution_minute_for_session
execution_minute_for_sessions_in_range
execution_time_from_close
execution_time_from_open