diff --git a/.github/config_new_release.yml b/.github/config_new_release.yml index eee66e8..3aa9ab0 100644 --- a/.github/config_new_release.yml +++ b/.github/config_new_release.yml @@ -1,8 +1,11 @@ -new_version: '4.1.4' +new_version: '4.3.0' change_log: | - - Updated TASE Holidays 2022-2025 + - Fixed for pandas 2.0 so all tests pass PR #282 + - Move exchange_calendar*.py files to pandas_market_calendar/exchange_calendars/ PR #284 + - Move holidays_*.py to pandas_market_calendar/holidays/ PR #284 + - Major cleanup including unused imports PR #284 release_body: | diff --git a/.gitignore b/.gitignore index 3651205..36c8898 100644 --- a/.gitignore +++ b/.gitignore @@ -82,7 +82,7 @@ celerybeat-schedule .env .venv env/ -venv/ +venv*/ env.bak/ venv.bak/ diff --git a/README.rst b/README.rst index e98e5a4..e325db4 100644 --- a/README.rst +++ b/README.rst @@ -9,6 +9,9 @@ Market calendars to use with pandas for trading applications. :target: http://pandas-market-calendars.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status +.. image:: https://coveralls.io/repos/github/rsheftel/pandas_market_calendars/badge.svg?branch=master + :target: https://coveralls.io/github/rsheftel/pandas_market_calendars?branch=master + Documentation ------------- http://pandas-market-calendars.readthedocs.io/en/latest/ diff --git a/docs/calendars.rst b/docs/calendars.rst index f16514e..a2e3edc 100644 --- a/docs/calendars.rst +++ b/docs/calendars.rst @@ -26,13 +26,14 @@ Exchange BSE BSEExchangeCalendar rakesh1988 Futures Calendars ################# -========== ================ =================================== ============ ============ +========== ================= =================================== ============ ============ Exchange Name Class Unit Tests Creator -========== ================ =================================== ============ ============ +========== ================= =================================== ============ ============ CME CME_Equity CMEEquityExchangeCalendar Yes rsheftel CME CME_Bond CMEBondExchangeCalendar Yes rsheftel -CME CME_Agricultural CMEAgriculturalExchangeCalendar Yes lionelyoung -========== ================ =================================== ============ ============ +CME CME_Agricultural CMEAgriculturalExchangeCalendar Yes lionelyoung +CME CME Globex Crypto CMEGlobexCryptoExchangeCalendar Yes Coinbase Asset Management +========== ================= =================================== ============ ============ Bond Market Calendars ##################### diff --git a/docs/change_log.rst b/docs/change_log.rst index 2a7b630..a484fb5 100644 --- a/docs/change_log.rst +++ b/docs/change_log.rst @@ -3,6 +3,13 @@ Change Log Updates ------- +4.3.0 (09/05/2023) +~~~~~~~~~~~~~~~~~~ +- Fixed for pandas 2.0 so all tests pass PR #282 +- Move exchange_calendar*.py files to pandas_market_calendar/exchange_calendars/ PR #284 +- Move holidays_*.py to pandas_market_calendar/holidays/ PR #284 +- Major cleanup including unused imports PR #284 + 4.2.1 (08/21/2023) ~~~~~~~~~~~~~~~~~~ - Fix the pyproject.toml to properly generate sdist PR #267 diff --git a/examples/usage.ipynb b/examples/usage.ipynb index a423bc9..f4c2d59 100644 --- a/examples/usage.ipynb +++ b/examples/usage.ipynb @@ -1427,7 +1427,7 @@ "# If you want to use the equity options exchange (8:30 - 15:00), including the order acceptance time at 7:30, and\n", "# some special cases when the order acceptance time was different, do this:\n", "\n", - "from pandas_market_calendars.exchange_calendar_cboe import CFEExchangeCalendar \n", + "from pandas_market_calendars.exchange_calendar.cboe import CFEExchangeCalendar \n", "\n", "class DemoOptionsCalendar(CFEExchangeCalendar): # Inherit what doesn't need to change\n", " name = \"Demo_Options\"\n", diff --git a/pandas_market_calendars/calendar_registry.py b/pandas_market_calendars/calendar_registry.py index c2346f1..beab943 100644 --- a/pandas_market_calendars/calendar_registry.py +++ b/pandas_market_calendars/calendar_registry.py @@ -1,31 +1,32 @@ from .market_calendar import MarketCalendar -from .exchange_calendar_asx import ASXExchangeCalendar -from .exchange_calendar_bmf import BMFExchangeCalendar -from .exchange_calendar_cboe import CFEExchangeCalendar -from .exchange_calendar_cme import \ +from .calendars.asx import ASXExchangeCalendar +from .calendars.bmf import BMFExchangeCalendar +from .calendars.bse import BSEExchangeCalendar +from .calendars.cboe import CFEExchangeCalendar +from .calendars.cme import \ CMEEquityExchangeCalendar, \ CMEBondExchangeCalendar -from .exchange_calendar_cme_globex_base import CMEGlobexBaseExchangeCalendar -from .exchange_calendar_cme_globex_agriculture import CMEGlobexAgricultureExchangeCalendar -from .exchange_calendar_cme_globex_fx import CMEGlobexFXExchangeCalendar -from .exchange_calendar_cme_globex_energy_and_metals import CMEGlobexEnergyAndMetalsExchangeCalendar -from .exchange_calendar_cme_globex_equities import CMEGlobexEquitiesExchangeCalendar -from .exchange_calendar_cme_globex_fixed_income import CMEGlobexFixedIncomeCalendar -from .exchange_calendar_eurex import EUREXExchangeCalendar -from .exchange_calendar_hkex import HKEXExchangeCalendar -from .exchange_calendar_ice import ICEExchangeCalendar -from .exchange_calendar_iex import IEXExchangeCalendar -from .exchange_calendar_jpx import JPXExchangeCalendar -from .exchange_calendar_lse import LSEExchangeCalendar -from .exchange_calendar_nyse import NYSEExchangeCalendar -from .exchange_calendar_ose import OSEExchangeCalendar -from .exchange_calendar_sifma import SIFMAUSExchangeCalendar, SIFMAUKExchangeCalendar, SIFMAJPExchangeCalendar -from .exchange_calendar_six import SIXExchangeCalendar -from .exchange_calendar_sse import SSEExchangeCalendar -from .exchange_calendar_tsx import TSXExchangeCalendar -from .exchange_calendar_bse import BSEExchangeCalendar -from .exchange_calendar_tase import TASEExchangeCalendar -from .exchange_calendars_mirror import * +from .calendars.cme_globex_base import CMEGlobexBaseExchangeCalendar +from .calendars.cme_globex_agriculture import CMEGlobexAgricultureExchangeCalendar +from .calendars.cme_globex_crypto import CMEGlobexCryptoExchangeCalendar +from .calendars.cme_globex_energy_and_metals import CMEGlobexEnergyAndMetalsExchangeCalendar +from .calendars.cme_globex_equities import CMEGlobexEquitiesExchangeCalendar +from .calendars.cme_globex_fx import CMEGlobexFXExchangeCalendar +from .calendars.cme_globex_fixed_income import CMEGlobexFixedIncomeCalendar +from .calendars.eurex import EUREXExchangeCalendar +from .calendars.hkex import HKEXExchangeCalendar +from .calendars.ice import ICEExchangeCalendar +from .calendars.iex import IEXExchangeCalendar +from .calendars.jpx import JPXExchangeCalendar +from .calendars.lse import LSEExchangeCalendar +from .calendars.nyse import NYSEExchangeCalendar +from .calendars.ose import OSEExchangeCalendar +from .calendars.sifma import SIFMAUSExchangeCalendar, SIFMAUKExchangeCalendar, SIFMAJPExchangeCalendar +from .calendars.six import SIXExchangeCalendar +from .calendars.sse import SSEExchangeCalendar +from .calendars.tase import TASEExchangeCalendar +from .calendars.tsx import TSXExchangeCalendar +from .calendars.mirror import * def get_calendar(name, open_time=None, close_time=None) -> MarketCalendar: diff --git a/pandas_market_calendars/calendar_utils.py b/pandas_market_calendars/calendar_utils.py index 7104620..aed4291 100644 --- a/pandas_market_calendars/calendar_utils.py +++ b/pandas_market_calendars/calendar_utils.py @@ -14,7 +14,7 @@ def merge_schedules(schedules, how='outer'): CAVEATS: * This does not work for schedules with breaks, the break information will be lost. - * Onlu "market_open" and "market_close" are considered, other market times are not yet supported. + * Only "market_open" and "market_close" are considered, other market times are not yet supported. :param schedules: list of schedules :param how: outer or inner diff --git a/pandas_market_calendars/calendars/__init__.py b/pandas_market_calendars/calendars/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pandas_market_calendars/exchange_calendar_asx.py b/pandas_market_calendars/calendars/asx.py similarity index 92% rename from pandas_market_calendars/exchange_calendar_asx.py rename to pandas_market_calendars/calendars/asx.py index 0ddffd0..3d28ffb 100644 --- a/pandas_market_calendars/exchange_calendar_asx.py +++ b/pandas_market_calendars/calendars/asx.py @@ -3,8 +3,8 @@ from pandas.tseries.holiday import AbstractHolidayCalendar, GoodFriday, EasterMonday from pytz import timezone -from .holidays_oz import * -from .market_calendar import MarketCalendar +from pandas_market_calendars.holidays.oz import * +from pandas_market_calendars.market_calendar import MarketCalendar AbstractHolidayCalendar.start_date = '2011-01-01' diff --git a/pandas_market_calendars/exchange_calendar_bmf.py b/pandas_market_calendars/calendars/bmf.py similarity index 98% rename from pandas_market_calendars/exchange_calendar_bmf.py rename to pandas_market_calendars/calendars/bmf.py index 10b2487..51267ca 100644 --- a/pandas_market_calendars/exchange_calendar_bmf.py +++ b/pandas_market_calendars/calendars/bmf.py @@ -19,7 +19,7 @@ from pandas.tseries.holiday import AbstractHolidayCalendar, Day, Easter, GoodFriday, Holiday from pytz import timezone -from .market_calendar import (FRIDAY, MarketCalendar) +from pandas_market_calendars.market_calendar import (FRIDAY, MarketCalendar) # Universal Confraternization (new years day) ConfUniversal = Holiday( diff --git a/pandas_market_calendars/exchange_calendar_bse.py b/pandas_market_calendars/calendars/bse.py similarity index 99% rename from pandas_market_calendars/exchange_calendar_bse.py rename to pandas_market_calendars/calendars/bse.py index 60fe515..59f0b56 100644 --- a/pandas_market_calendars/exchange_calendar_bse.py +++ b/pandas_market_calendars/calendars/bse.py @@ -5,7 +5,7 @@ from pandas import Timestamp from pytz import timezone from datetime import time -from .market_calendar import MarketCalendar +from pandas_market_calendars.market_calendar import MarketCalendar BSEClosedDay = [ diff --git a/pandas_market_calendars/exchange_calendar_cboe.py b/pandas_market_calendars/calendars/cboe.py similarity index 69% rename from pandas_market_calendars/exchange_calendar_cboe.py rename to pandas_market_calendars/calendars/cboe.py index 7f12086..471e712 100644 --- a/pandas_market_calendars/exchange_calendar_cboe.py +++ b/pandas_market_calendars/calendars/cboe.py @@ -6,28 +6,29 @@ from itertools import chain import pandas as pd -from .holidays_us import (Christmas, USBlackFridayInOrAfter1993, USIndependenceDay, USMartinLutherKingJrAfter1998, - USMemorialDay, USNewYearsDay, HurricaneSandyClosings, USNationalDaysofMourning) -from .market_calendar import MarketCalendar +from pandas_market_calendars.holidays.us import (Christmas, USBlackFridayInOrAfter1993, USIndependenceDay, USMartinLutherKingJrAfter1998, + USMemorialDay, USNewYearsDay, HurricaneSandyClosings, USNationalDaysofMourning, + USJuneteenthAfter2022) +from pandas_market_calendars.market_calendar import MarketCalendar -# TODO: In pandas 2.0.3 this no longer works as the dt passed in is the entire matrix and not a single date def good_friday_unless_christmas_nye_friday(dt): """ Good Friday is a valid trading day if Christmas Day or New Years Day fall on a Friday. """ + if isinstance(dt, pd.DatetimeIndex): + # Pandas < 2.1.0 will call with an index and fall-back to element by element + # Pandas == 2.1.0 will only call element by element + raise NotImplementedError() + year = dt.year - christmas_weekday = Christmas.observance( - pd.Timestamp(year, 12, 25) - ).weekday() - nyd_weekday = USNewYearsDay.observance( - pd.Timestamp(year, 1, 1) - ).weekday() + christmas_weekday = Christmas.observance(pd.Timestamp(year=year, month=12, day=25)).weekday() + nyd_weekday = USNewYearsDay.observance(pd.Timestamp(year=year, month=1, day=1)).weekday() if christmas_weekday != 4 and nyd_weekday != 4: - return GoodFriday._apply_rule(dt) + return GoodFriday.dates(pd.Timestamp(year=year, month=1, day=1), pd.Timestamp(year=year, month=12, day=31))[0] else: - # compatibility for pandas 0.18.1 + # Not a holiday so use NaT to ensure it gets removed return pd.NaT @@ -70,8 +71,8 @@ def regular_holidays(self): USNewYearsDay, USMartinLutherKingJrAfter1998, USPresidentsDay, - # GoodFridayUnlessChristmasNYEFriday, #TODO: When this is fixed can return to using it - GoodFriday, + GoodFridayUnlessChristmasNYEFriday, + USJuneteenthAfter2022, USIndependenceDay, USMemorialDay, USLaborDay, @@ -112,5 +113,3 @@ class CBOEIndexOptionsExchangeCalendar(CFEExchangeCalendar): "market_open": ((None, time(8, 30)),), "market_close": ((None, time(15, 15)),) } - - diff --git a/pandas_market_calendars/exchange_calendar_cme.py b/pandas_market_calendars/calendars/cme.py similarity index 95% rename from pandas_market_calendars/exchange_calendar_cme.py rename to pandas_market_calendars/calendars/cme.py index 6848595..bf38cab 100644 --- a/pandas_market_calendars/exchange_calendar_cme.py +++ b/pandas_market_calendars/calendars/cme.py @@ -20,10 +20,10 @@ from pandas.tseries.holiday import AbstractHolidayCalendar, GoodFriday, USLaborDay, USPresidentsDay, USThanksgivingDay from pytz import timezone -from .holidays_us import (Christmas, ChristmasEveBefore1993, ChristmasEveInOrAfter1993, USBlackFridayInOrAfter1993, - USIndependenceDay, USMartinLutherKingJrAfter1998, USMemorialDay, USNationalDaysofMourning, - USNewYearsDay) -from .market_calendar import MarketCalendar +from pandas_market_calendars.holidays.us import (Christmas, ChristmasEveBefore1993, ChristmasEveInOrAfter1993, USBlackFridayInOrAfter1993, + USIndependenceDay, USMartinLutherKingJrAfter1998, USMemorialDay, USNationalDaysofMourning, + USNewYearsDay) +from pandas_market_calendars.market_calendar import MarketCalendar # Useful resources for making changes to this file: http://www.cmegroup.com/tools-information/holiday-calendar.html diff --git a/pandas_market_calendars/exchange_calendar_cme_globex_agriculture.py b/pandas_market_calendars/calendars/cme_globex_agriculture.py similarity index 83% rename from pandas_market_calendars/exchange_calendar_cme_globex_agriculture.py rename to pandas_market_calendars/calendars/cme_globex_agriculture.py index 7e4ca9d..4462b26 100644 --- a/pandas_market_calendars/exchange_calendar_cme_globex_agriculture.py +++ b/pandas_market_calendars/calendars/cme_globex_agriculture.py @@ -13,22 +13,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -from abc import ABC, abstractmethod -from .exchange_calendar_cme_globex_base import CMEGlobexBaseExchangeCalendar +from abc import abstractmethod +from .cme_globex_base import CMEGlobexBaseExchangeCalendar from datetime import time -from itertools import chain -from pandas import Timestamp from pandas.tseries.holiday import AbstractHolidayCalendar, GoodFriday, USLaborDay, USPresidentsDay, USThanksgivingDay -from pytz import timezone - -from .holidays_us import (Christmas, ChristmasEveBefore1993, ChristmasEveInOrAfter1993, USBlackFridayInOrAfter1993, - USIndependenceDay, USMartinLutherKingJrAfter1998, USMemorialDay, USJuneteenthAfter2022, - USNationalDaysofMourning, USNewYearsDay) -from .market_calendar import MarketCalendar - +from pandas_market_calendars.holidays.us import (Christmas, ChristmasEveBefore1993, ChristmasEveInOrAfter1993, USBlackFridayInOrAfter1993, + USIndependenceDay, USMartinLutherKingJrAfter1998, USMemorialDay, + USNewYearsDay) class CMEGlobexAgricultureExchangeCalendar(CMEGlobexBaseExchangeCalendar): diff --git a/pandas_market_calendars/exchange_calendar_cme_globex_base.py b/pandas_market_calendars/calendars/cme_globex_base.py similarity index 85% rename from pandas_market_calendars/exchange_calendar_cme_globex_base.py rename to pandas_market_calendars/calendars/cme_globex_base.py index 55339f8..1301699 100644 --- a/pandas_market_calendars/exchange_calendar_cme_globex_base.py +++ b/pandas_market_calendars/calendars/cme_globex_base.py @@ -15,17 +15,13 @@ from abc import ABC, abstractmethod -from datetime import time -from itertools import chain - -from pandas import Timestamp from pandas.tseries.holiday import AbstractHolidayCalendar, GoodFriday, USLaborDay, USPresidentsDay, USThanksgivingDay from pytz import timezone -from .holidays_us import (Christmas, ChristmasEveBefore1993, ChristmasEveInOrAfter1993, USBlackFridayInOrAfter1993, - USIndependenceDay, USMartinLutherKingJrAfter1998, USMemorialDay, USJuneteenthAfter2022, - USNationalDaysofMourning, USNewYearsDay) -from .market_calendar import MarketCalendar +from pandas_market_calendars.holidays.us import (Christmas, ChristmasEveBefore1993, ChristmasEveInOrAfter1993, USBlackFridayInOrAfter1993, + USIndependenceDay, USMartinLutherKingJrAfter1998, USMemorialDay, USJuneteenthAfter2022, + USNewYearsDay) +from pandas_market_calendars.market_calendar import MarketCalendar class CMEGlobexBaseExchangeCalendar(MarketCalendar, ABC): @@ -34,6 +30,7 @@ class CMEGlobexBaseExchangeCalendar(MarketCalendar, ABC): CME Markets: https://www.cmegroup.com/markets/agriculture.html#overview - Agriculture + - Crypto - Energy - Equity Index - FX diff --git a/pandas_market_calendars/calendars/cme_globex_crypto.py b/pandas_market_calendars/calendars/cme_globex_crypto.py new file mode 100644 index 0000000..96d1978 --- /dev/null +++ b/pandas_market_calendars/calendars/cme_globex_crypto.py @@ -0,0 +1,147 @@ +import datetime as dt + +from pandas.tseries.holiday import AbstractHolidayCalendar +import pytz + +from .cme_globex_base import CMEGlobexBaseExchangeCalendar +from pandas_market_calendars.holidays.cme import ( + GoodFriday2021, + GoodFridayAfter2021, + GoodFridayBefore2021, + USIndependenceDayBefore2022PreviousDay, +) +from pandas_market_calendars.holidays.cme_globex import ( + ChristmasCME, + USMartinLutherKingJrFrom2022, + USMartinLutherKingJrPre2022, + USPresidentsDayFrom2022, + USPresidentsDayPre2022, + USMemorialDayFrom2022, + USMemorialDayPre2022, + USJuneteenthFrom2022, + USIndependenceDayFrom2022, + USIndependenceDayPre2022, + USLaborDayFrom2022, + USLaborDayPre2022, + USThanksgivingDayFrom2022, + USThanksgivingDayPre2022, + USThanksgivingFridayFrom2021, + USThanksgivingFridayPre2021, +) +from pandas_market_calendars.holidays.us import ( + ChristmasEveInOrAfter1993, + USNewYearsDay, +) + + +# https://github.com/rsheftel/pandas_market_calendars/blob/master/docs/new_market.rst +class CMEGlobexCryptoExchangeCalendar(CMEGlobexBaseExchangeCalendar): + # The label you fetch the exchange with in mcal.get_calendar('CME Globex ...') + aliases = ["CME Globex Cryptocurrencies", "CME Globex Crypto"] + + # https://www.cmegroup.com/markets/cryptocurrencies/bitcoin/bitcoin.contractSpecs.html + regular_market_times = { + # Tuple[Tuple[first date used, time, offset], ...] + # -1 offset indicates that the open is on the previous day + # None for first date used marks the start, subsequent market times must have an actual timestamp + "market_open": ( + (None, dt.time(17, tzinfo=pytz.timezone("America/Chicago")), -1), + ), + "market_close": ( + ( + None, + dt.time(16, tzinfo=pytz.timezone("America/Chicago")), + ), + ), + "break_start": ( + ( + None, + dt.time(16, tzinfo=pytz.timezone("America/Chicago")), + ), + ), + "break_end": ( + ( + None, + dt.time(17, tzinfo=pytz.timezone("America/Chicago")), + ), + ), + } + + @property + def tz(self): + # Central Time + return pytz.timezone("America/Chicago") + + @property + def name(self): + return "CME Globex Crypto" + + # Check the .zip files at the bottom of this page + # https://www.cmegroup.com/tools-information/holiday-calendar.html?redirect=/tools-information/holiday-calendar/#cmeGlobex + # Note: many of the holiday objects (ie. GoodFridayBefore2021) were originally made for equities and other markets + # and hence have a start_date starting before crypto is actually available + + @property + def regular_holidays(self): + # Days where the market is fully closed + return AbstractHolidayCalendar( + rules=[ + GoodFridayBefore2021, + GoodFridayAfter2021, + ChristmasCME, + USNewYearsDay, + ] + ) + + @property + def special_closes(self): + # Days where the market closes early + # list[Tuple[time, AbstractHolidayCalendar]] + return [ + ( + dt.time(8, 15, tzinfo=pytz.timezone("America/Chicago")), + AbstractHolidayCalendar(rules=[GoodFriday2021]), + ), + ( + dt.time(12, tzinfo=pytz.timezone("America/Chicago")), + AbstractHolidayCalendar( + rules=[ + USMartinLutherKingJrPre2022, + USPresidentsDayPre2022, + USMemorialDayPre2022, + USIndependenceDayPre2022, + USLaborDayPre2022, + USThanksgivingDayPre2022, + ] + ), + ), + ( + dt.time(12, 15, tzinfo=pytz.timezone("America/Chicago")), + AbstractHolidayCalendar( + rules=[ + ChristmasEveInOrAfter1993, + USIndependenceDayBefore2022PreviousDay, + USThanksgivingFridayPre2021, + ] + ), + ), + ( + dt.time(12, 45, tzinfo=pytz.timezone("America/Chicago")), + AbstractHolidayCalendar(rules=[USThanksgivingFridayFrom2021]), + ), + # TODO: this market already closes at 1600 normally, do we need these holidays? + ( + dt.time(16, tzinfo=pytz.timezone("America/Chicago")), + AbstractHolidayCalendar( + rules=[ + USMartinLutherKingJrFrom2022, + USPresidentsDayFrom2022, + USMemorialDayFrom2022, + USJuneteenthFrom2022, + USIndependenceDayFrom2022, + USLaborDayFrom2022, + USThanksgivingDayFrom2022, + ] + ), + ), + ] diff --git a/pandas_market_calendars/exchange_calendar_cme_globex_energy_and_metals.py b/pandas_market_calendars/calendars/cme_globex_energy_and_metals.py similarity index 84% rename from pandas_market_calendars/exchange_calendar_cme_globex_energy_and_metals.py rename to pandas_market_calendars/calendars/cme_globex_energy_and_metals.py index bd769df..fff1c3f 100644 --- a/pandas_market_calendars/exchange_calendar_cme_globex_energy_and_metals.py +++ b/pandas_market_calendars/calendars/cme_globex_energy_and_metals.py @@ -13,14 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from abc import ABC, abstractmethod -from .exchange_calendar_cme_globex_base import CMEGlobexBaseExchangeCalendar +from .cme_globex_base import CMEGlobexBaseExchangeCalendar from datetime import time -from itertools import chain -import pandas as pd -from pandas import Timestamp from pandas.tseries.holiday import AbstractHolidayCalendar #, GoodFriday, USLaborDay, USPresidentsDay, USThanksgivingDay from pytz import timezone @@ -28,19 +24,15 @@ # USIndependenceDay, USMartinLutherKingJrAfter1998, USMemorialDay, USJuneteenthAfter2022, # USNationalDaysofMourning, USNewYearsDay) -from .holidays_cme_globex import ( USNewYearsDay, - USMartinLutherKingJrFrom2022, USMartinLutherKingJrPre2022, USNewYearsDay, - USPresidentsDayFrom2022, USPresidentsDayPre2022, - GoodFriday, - USMemorialDayFrom2022, USMemorialDayPre2022, - USJuneteenthFrom2022, - USIndependenceDayFrom2022, USIndependenceDayPre2022, - USLaborDay, - USThanksgivingDayFrom2022, USThanksgivingDayPre2022, FridayAfterThanksgiving, - ChristmasCME) -from .market_calendar import MarketCalendar - - +from pandas_market_calendars.holidays.cme_globex import (USMartinLutherKingJrFrom2022, USMartinLutherKingJrPre2022, USNewYearsDay, + USPresidentsDayFrom2022, USPresidentsDayPre2022, + GoodFriday, + USMemorialDayFrom2022, USMemorialDayPre2022, + USJuneteenthFrom2022, + USIndependenceDayFrom2022, USIndependenceDayPre2022, + USLaborDay, + USThanksgivingDayFrom2022, USThanksgivingDayPre2022, FridayAfterThanksgiving, + ChristmasCME) class CMEGlobexEnergyAndMetalsExchangeCalendar(CMEGlobexBaseExchangeCalendar): diff --git a/pandas_market_calendars/exchange_calendar_cme_globex_equities.py b/pandas_market_calendars/calendars/cme_globex_equities.py similarity index 94% rename from pandas_market_calendars/exchange_calendar_cme_globex_equities.py rename to pandas_market_calendars/calendars/cme_globex_equities.py index 4326cb2..9fe9324 100644 --- a/pandas_market_calendars/exchange_calendar_cme_globex_equities.py +++ b/pandas_market_calendars/calendars/cme_globex_equities.py @@ -1,10 +1,10 @@ -from .exchange_calendar_cme_globex_base import CMEGlobexBaseExchangeCalendar +from .cme_globex_base import CMEGlobexBaseExchangeCalendar from datetime import time from pandas.tseries.holiday import AbstractHolidayCalendar from pytz import timezone -from pandas_market_calendars.holidays_cme import ( +from pandas_market_calendars.holidays.cme import ( USMartinLutherKingJrAfter1998Before2015, USMartinLutherKingJrAfter2015, USPresidentsDayBefore2015, @@ -26,7 +26,7 @@ USThanksgivingAfter2014, USThanksgivingFriday, ) -from pandas_market_calendars.holidays_us import ( +from pandas_market_calendars.holidays.us import ( USNewYearsDay, ChristmasEveInOrAfter1993, Christmas, diff --git a/pandas_market_calendars/exchange_calendar_cme_globex_fixed_income.py b/pandas_market_calendars/calendars/cme_globex_fixed_income.py similarity index 94% rename from pandas_market_calendars/exchange_calendar_cme_globex_fixed_income.py rename to pandas_market_calendars/calendars/cme_globex_fixed_income.py index 3d32b63..50ea57d 100644 --- a/pandas_market_calendars/exchange_calendar_cme_globex_fixed_income.py +++ b/pandas_market_calendars/calendars/cme_globex_fixed_income.py @@ -1,10 +1,9 @@ -from .exchange_calendar_cme_globex_base import CMEGlobexBaseExchangeCalendar +from .cme_globex_base import CMEGlobexBaseExchangeCalendar from datetime import time from pandas.tseries.holiday import AbstractHolidayCalendar -from pytz import timezone -from pandas_market_calendars.holidays_cme import ( +from pandas_market_calendars.holidays.cme import ( USMartinLutherKingJrAfter1998Before2015, USMartinLutherKingJrAfter1998Before2016FridayBefore, USMartinLutherKingJrAfter2015, @@ -30,7 +29,7 @@ USThanksgivingAfter2014, USThanksgivingFriday, ) -from pandas_market_calendars.holidays_us import ( +from pandas_market_calendars.holidays.us import ( USNewYearsDay, ChristmasEveInOrAfter1993, Christmas, diff --git a/pandas_market_calendars/exchange_calendar_cme_globex_fx.py b/pandas_market_calendars/calendars/cme_globex_fx.py similarity index 92% rename from pandas_market_calendars/exchange_calendar_cme_globex_fx.py rename to pandas_market_calendars/calendars/cme_globex_fx.py index b5f9f83..43adbe3 100644 --- a/pandas_market_calendars/exchange_calendar_cme_globex_fx.py +++ b/pandas_market_calendars/calendars/cme_globex_fx.py @@ -2,8 +2,8 @@ from pandas.tseries.holiday import AbstractHolidayCalendar -from pandas_market_calendars.exchange_calendar_cme_globex_base import CMEGlobexBaseExchangeCalendar -from pandas_market_calendars.holidays_cme import ( +from pandas_market_calendars.calendars.cme_globex_base import CMEGlobexBaseExchangeCalendar +from pandas_market_calendars.holidays.cme import ( USMartinLutherKingJrAfter1998Before2022, USPresidentsDayBefore2022, GoodFridayBefore2021, @@ -15,7 +15,7 @@ USThanksgivingBefore2022, USThanksgivingFriday, ) -from pandas_market_calendars.holidays_us import ( +from pandas_market_calendars.holidays.us import ( USNewYearsDay, ChristmasEveInOrAfter1993, Christmas, diff --git a/pandas_market_calendars/exchange_calendar_eurex.py b/pandas_market_calendars/calendars/eurex.py similarity index 95% rename from pandas_market_calendars/exchange_calendar_eurex.py rename to pandas_market_calendars/calendars/eurex.py index 71b1d3c..efd2e05 100644 --- a/pandas_market_calendars/exchange_calendar_eurex.py +++ b/pandas_market_calendars/calendars/eurex.py @@ -7,7 +7,7 @@ from pandas.tseries.holiday import AbstractHolidayCalendar, EasterMonday, GoodFriday, Holiday, previous_friday from pytz import timezone -from .market_calendar import (FRIDAY, MONDAY, MarketCalendar, THURSDAY, TUESDAY, WEDNESDAY) +from pandas_market_calendars.market_calendar import (FRIDAY, MONDAY, MarketCalendar, THURSDAY, TUESDAY, WEDNESDAY) # New Year's Eve EUREXNewYearsEve = Holiday( diff --git a/pandas_market_calendars/exchange_calendar_hkex.py b/pandas_market_calendars/calendars/hkex.py similarity index 98% rename from pandas_market_calendars/exchange_calendar_hkex.py rename to pandas_market_calendars/calendars/hkex.py index 610cf01..63c77b5 100644 --- a/pandas_market_calendars/exchange_calendar_hkex.py +++ b/pandas_market_calendars/calendars/hkex.py @@ -6,9 +6,9 @@ from pandas.tseries.offsets import LastWeekOfMonth, WeekOfMonth from pytz import timezone -from pandas_market_calendars.holidays_us import USNewYearsDay -from .holidays_cn import bsd_mapping, dbf_mapping, dnf_mapping, maf_mapping, sf_mapping, tsd_mapping -from .market_calendar import MarketCalendar +from pandas_market_calendars.holidays.us import USNewYearsDay +from pandas_market_calendars.holidays.cn import bsd_mapping, dbf_mapping, dnf_mapping, maf_mapping, sf_mapping, tsd_mapping +from pandas_market_calendars.market_calendar import MarketCalendar def process_date(dt, mapping=None, func=None, delta=None, offset=None): diff --git a/pandas_market_calendars/exchange_calendar_ice.py b/pandas_market_calendars/calendars/ice.py similarity index 85% rename from pandas_market_calendars/exchange_calendar_ice.py rename to pandas_market_calendars/calendars/ice.py index 365ab5e..8f7cbb5 100644 --- a/pandas_market_calendars/exchange_calendar_ice.py +++ b/pandas_market_calendars/calendars/ice.py @@ -5,9 +5,9 @@ from pandas.tseries.holiday import AbstractHolidayCalendar, GoodFriday, USLaborDay, USPresidentsDay, USThanksgivingDay from pytz import timezone -from .holidays_us import (Christmas, USIndependenceDay, USMartinLutherKingJrAfter1998, USMemorialDay, - USNationalDaysofMourning, USNewYearsDay) -from .market_calendar import MarketCalendar +from pandas_market_calendars.holidays.us import (Christmas, USIndependenceDay, USMartinLutherKingJrAfter1998, USMemorialDay, + USNationalDaysofMourning, USNewYearsDay) +from pandas_market_calendars.market_calendar import MarketCalendar class ICEExchangeCalendar(MarketCalendar): diff --git a/pandas_market_calendars/exchange_calendar_iex.py b/pandas_market_calendars/calendars/iex.py similarity index 96% rename from pandas_market_calendars/exchange_calendar_iex.py rename to pandas_market_calendars/calendars/iex.py index cdbff94..ac92bdd 100644 --- a/pandas_market_calendars/exchange_calendar_iex.py +++ b/pandas_market_calendars/calendars/iex.py @@ -1,10 +1,10 @@ from datetime import time from itertools import chain -from .exchange_calendar_nyse import NYSEExchangeCalendar +from .nyse import NYSEExchangeCalendar from pandas.tseries.holiday import AbstractHolidayCalendar from pytz import timezone -from pandas_market_calendars.holidays_nyse import ( +from pandas_market_calendars.holidays.nyse import ( USPresidentsDay, GoodFriday, USMemorialDay, diff --git a/pandas_market_calendars/exchange_calendar_jpx.py b/pandas_market_calendars/calendars/jpx.py similarity index 94% rename from pandas_market_calendars/exchange_calendar_jpx.py rename to pandas_market_calendars/calendars/jpx.py index 7060a71..3197a1b 100644 --- a/pandas_market_calendars/exchange_calendar_jpx.py +++ b/pandas_market_calendars/calendars/jpx.py @@ -4,9 +4,9 @@ from pandas.tseries.holiday import AbstractHolidayCalendar from pytz import timezone -from pandas_market_calendars.holidays_jp import * -from pandas_market_calendars.holidays_us import USNewYearsDay -from .market_calendar import MarketCalendar +from pandas_market_calendars.holidays.jp import * +from pandas_market_calendars.holidays.us import USNewYearsDay +from pandas_market_calendars.market_calendar import MarketCalendar # TODO: diff --git a/pandas_market_calendars/exchange_calendar_lse.py b/pandas_market_calendars/calendars/lse.py similarity index 95% rename from pandas_market_calendars/exchange_calendar_lse.py rename to pandas_market_calendars/calendars/lse.py index c23d4f9..59a4fc3 100644 --- a/pandas_market_calendars/exchange_calendar_lse.py +++ b/pandas_market_calendars/calendars/lse.py @@ -18,13 +18,13 @@ from pandas.tseries.holiday import AbstractHolidayCalendar, EasterMonday, GoodFriday from pytz import timezone -from .holidays_uk import ( +from pandas_market_calendars.holidays.uk import ( BoxingDay, Christmas, ChristmasEve, LSENewYearsDay, LSENewYearsEve, MayBank_pre_1995, MayBank_post_1995_pre_2020, MayBank_post_2020, SpringBank_pre_2002, SpringBank_post_2002_pre_2012, SpringBank_post_2012_pre_2022, SpringBank_post_2022, SummerBank, WeekendBoxingDay, WeekendChristmas, UniqueCloses, ) -from .market_calendar import MarketCalendar +from pandas_market_calendars.market_calendar import MarketCalendar class LSEExchangeCalendar(MarketCalendar): diff --git a/pandas_market_calendars/exchange_calendars_mirror.py b/pandas_market_calendars/calendars/mirror.py similarity index 96% rename from pandas_market_calendars/exchange_calendars_mirror.py rename to pandas_market_calendars/calendars/mirror.py index 6df0bf6..277bd62 100644 --- a/pandas_market_calendars/exchange_calendars_mirror.py +++ b/pandas_market_calendars/calendars/mirror.py @@ -4,7 +4,7 @@ GitHub: https://github.com/gerrymanoim/exchange_calendars """ -from .market_calendar import MarketCalendar +from pandas_market_calendars.market_calendar import MarketCalendar import exchange_calendars @@ -106,7 +106,7 @@ def special_closes_adhoc(self): cal = type(exchange, (TradingCalendar,), {'_ec_class': calendars[exchange], 'alias': [exchange], 'regular_market_times': regular_market_times}) - locals()[exchange + 'ExchangeCalendar'] = cal + locals()[f'{exchange}ExchangeCalendar'] = cal diff --git a/pandas_market_calendars/exchange_calendar_nyse.py b/pandas_market_calendars/calendars/nyse.py similarity index 99% rename from pandas_market_calendars/exchange_calendar_nyse.py rename to pandas_market_calendars/calendars/nyse.py index 7fb3e26..c48b7c5 100644 --- a/pandas_market_calendars/exchange_calendar_nyse.py +++ b/pandas_market_calendars/calendars/nyse.py @@ -20,7 +20,7 @@ from pandas.tseries.holiday import AbstractHolidayCalendar from pytz import timezone -from pandas_market_calendars.holidays_nyse import ( +from pandas_market_calendars.holidays.nyse import ( # Always Celebrated Holidays USNewYearsDayNYSEpost1952, USNewYearsDayNYSEpre1952, SatBeforeNewYearsAdhoc, @@ -244,7 +244,7 @@ # 2018 GeorgeHWBushDeath2018 ) -from .market_calendar import MarketCalendar +from pandas_market_calendars.market_calendar import MarketCalendar # Useful resources for making changes to this file: # http://www.nyse.com/pdfs/closings.pdf diff --git a/pandas_market_calendars/exchange_calendar_ose.py b/pandas_market_calendars/calendars/ose.py similarity index 97% rename from pandas_market_calendars/exchange_calendar_ose.py rename to pandas_market_calendars/calendars/ose.py index 2a95dc2..af87e1f 100644 --- a/pandas_market_calendars/exchange_calendar_ose.py +++ b/pandas_market_calendars/calendars/ose.py @@ -4,7 +4,7 @@ from pandas.tseries.offsets import Day, Easter from pytz import timezone -from .market_calendar import MarketCalendar +from pandas_market_calendars.market_calendar import MarketCalendar OSENewYearsDay = Holiday( "New Year's Day", diff --git a/pandas_market_calendars/exchange_calendar_sifma.py b/pandas_market_calendars/calendars/sifma.py similarity index 91% rename from pandas_market_calendars/exchange_calendar_sifma.py rename to pandas_market_calendars/calendars/sifma.py index 89c486a..c7bdac6 100644 --- a/pandas_market_calendars/exchange_calendar_sifma.py +++ b/pandas_market_calendars/calendars/sifma.py @@ -3,8 +3,6 @@ from pandas.tseries.holiday import AbstractHolidayCalendar from pytz import timezone from itertools import chain -import pandas as pd - ######################################################################################################################## # SIFMA Financial Markets Calendar for US, UK, JP @@ -22,9 +20,8 @@ ######################################################################################################################## -from pandas_market_calendars.holidays_sifma import( +from pandas_market_calendars.holidays.sifma import( # US Holidays - UKWeekendBoxingDay, USNewYearsDay, # Not observed if a Saturday USNewYearsEve2pmEarlyClose, @@ -71,7 +68,7 @@ UKPlatinumJubilee2022, ) -from .market_calendar import MarketCalendar +from pandas_market_calendars.market_calendar import MarketCalendar #AbstractHolidayCalendar.start_date = '1998-01-01' @@ -214,11 +211,11 @@ def adhoc_holidays(self): ############################################################ # Japan ############################################################ -from .holidays_jp import (JapanComingOfAgeDay, JapanNationalFoundationDay,JapanEmperorsBirthday, JapanVernalEquinox,JapanShowaDay, - JapanConstitutionMemorialDay, JapanGreeneryDay, JapanChildrensDay, JapanMarineDay, JapanMountainDay, - JapanRespectForTheAgedDay, JapanAutumnalEquinox, - JapanHealthAndSportsDay2000To2019, JapanSportsDay2020, JapanSportsDay, - JapanCultureDay, JapanLaborThanksgivingDay) +from pandas_market_calendars.holidays.jp import (JapanComingOfAgeDay, JapanNationalFoundationDay, JapanEmperorsBirthday, JapanVernalEquinox, JapanShowaDay, + JapanConstitutionMemorialDay, JapanGreeneryDay, JapanChildrensDay, JapanMarineDay, JapanMountainDay, + JapanRespectForTheAgedDay, JapanAutumnalEquinox, + JapanHealthAndSportsDay2000To2019, JapanSportsDay2020, JapanSportsDay, + JapanCultureDay, JapanLaborThanksgivingDay) class SIFMAJPExchangeCalendar(MarketCalendar): """ diff --git a/pandas_market_calendars/exchange_calendar_six.py b/pandas_market_calendars/calendars/six.py similarity index 95% rename from pandas_market_calendars/exchange_calendar_six.py rename to pandas_market_calendars/calendars/six.py index 492ccb5..35dfec2 100644 --- a/pandas_market_calendars/exchange_calendar_six.py +++ b/pandas_market_calendars/calendars/six.py @@ -4,7 +4,7 @@ previous_friday) from pytz import timezone -from .market_calendar import (FRIDAY, MONDAY, MarketCalendar, THURSDAY, TUESDAY, WEDNESDAY) +from pandas_market_calendars.market_calendar import (FRIDAY, MONDAY, MarketCalendar, THURSDAY, TUESDAY, WEDNESDAY) # New Year's Eve NewYearsEve = Holiday( diff --git a/pandas_market_calendars/exchange_calendar_sse.py b/pandas_market_calendars/calendars/sse.py similarity index 98% rename from pandas_market_calendars/exchange_calendar_sse.py rename to pandas_market_calendars/calendars/sse.py index 3591f09..92040fa 100644 --- a/pandas_market_calendars/exchange_calendar_sse.py +++ b/pandas_market_calendars/calendars/sse.py @@ -4,8 +4,8 @@ from pandas.tseries.holiday import AbstractHolidayCalendar, Holiday, next_monday from pytz import timezone -from .holidays_cn import * -from .market_calendar import MarketCalendar +from pandas_market_calendars.holidays.cn import * +from pandas_market_calendars.market_calendar import MarketCalendar class SSEExchangeCalendar(MarketCalendar): diff --git a/pandas_market_calendars/exchange_calendar_tase.py b/pandas_market_calendars/calendars/tase.py similarity index 99% rename from pandas_market_calendars/exchange_calendar_tase.py rename to pandas_market_calendars/calendars/tase.py index b209280..13bf5ad 100644 --- a/pandas_market_calendars/exchange_calendar_tase.py +++ b/pandas_market_calendars/calendars/tase.py @@ -1,7 +1,7 @@ from datetime import time from pandas import Timestamp from pytz import timezone -from .market_calendar import MarketCalendar +from pandas_market_calendars.market_calendar import MarketCalendar TASEClosedDay = [ # 2019 diff --git a/pandas_market_calendars/exchange_calendar_tsx.py b/pandas_market_calendars/calendars/tsx.py similarity index 94% rename from pandas_market_calendars/exchange_calendar_tsx.py rename to pandas_market_calendars/calendars/tsx.py index 6705497..07a9da1 100644 --- a/pandas_market_calendars/exchange_calendar_tsx.py +++ b/pandas_market_calendars/calendars/tsx.py @@ -5,8 +5,8 @@ from pytz import timezone from itertools import chain -from .holidays_uk import BoxingDay, WeekendBoxingDay, WeekendChristmas -from .market_calendar import MarketCalendar, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY +from pandas_market_calendars.holidays.uk import BoxingDay, WeekendBoxingDay, WeekendChristmas +from pandas_market_calendars.market_calendar import MarketCalendar, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY # New Year's Day TSXNewYearsDay = Holiday( diff --git a/pandas_market_calendars/holidays/__init__.py b/pandas_market_calendars/holidays/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pandas_market_calendars/holidays_cme.py b/pandas_market_calendars/holidays/cme.py similarity index 98% rename from pandas_market_calendars/holidays_cme.py rename to pandas_market_calendars/holidays/cme.py index 0e3a6b1..d0d8086 100644 --- a/pandas_market_calendars/holidays_cme.py +++ b/pandas_market_calendars/holidays/cme.py @@ -1,7 +1,6 @@ import datetime -from dateutil.relativedelta import (MO, FR) -from dateutil.relativedelta import (TH) +from dateutil.relativedelta import (MO, TH, FR) from pandas import (DateOffset, Timestamp) from pandas.tseries.holiday import (Holiday, Easter) from pandas.tseries.holiday import (nearest_workday) @@ -213,11 +212,11 @@ def not_0815_close(dt): start_date=Timestamp('2014-01-01'), observance=nearest_workday,) -# Necessary for equities +# Necessary for equities and crypto def previous_workday_if_july_4th_is_tue_to_fri(dt): july4th = datetime.datetime(dt.year, 7, 4) if july4th.weekday() in (1, 2, 3, 4): - return july4th - datetime.timedelta(days= 1) + return july4th - datetime.timedelta(days=1) # else None USIndependenceDayBefore2022PreviousDay = Holiday( diff --git a/pandas_market_calendars/holidays_cme_globex.py b/pandas_market_calendars/holidays/cme_globex.py similarity index 81% rename from pandas_market_calendars/holidays_cme_globex.py rename to pandas_market_calendars/holidays/cme_globex.py index ffd48da..dc0111f 100644 --- a/pandas_market_calendars/holidays_cme_globex.py +++ b/pandas_market_calendars/holidays/cme_globex.py @@ -26,7 +26,7 @@ # Martin Luther King Jr. # Starting 1998 ########################################################################## -USMartinLutherKingJrFrom2022 = Holiday( # Early Close 1:30pm +USMartinLutherKingJrFrom2022 = Holiday( 'Dr. Martin Luther King Jr. Day', month=1, day=1, @@ -35,7 +35,7 @@ offset=DateOffset(weekday=MO(3)), ) -USMartinLutherKingJrPre2022 = Holiday( # Early Close 12:00pm +USMartinLutherKingJrPre2022 = Holiday( 'Dr. Martin Luther King Jr. Day', month=1, day=1, @@ -48,12 +48,12 @@ ######################################################################### # US Presidents Day Feb ########################################################################## -USPresidentsDayFrom2022 = Holiday('President''s Day', # 1:30pm Early Close +USPresidentsDayFrom2022 = Holiday('President''s Day', start_date=Timestamp('2022-01-01'), month=2, day=1, offset=DateOffset(weekday=MO(3))) -USPresidentsDayPre2022 = Holiday('President''s Day', # 12:00pm Early Close +USPresidentsDayPre2022 = Holiday('President''s Day', end_date=Timestamp('2021-12-31'), month=2, day=1, offset=DateOffset(weekday=MO(3))) @@ -74,7 +74,7 @@ ################################################## # US Memorial Day (Decoration Day) May 30 ################################################## -USMemorialDayFrom2022 = Holiday( # 1:30pm early close +USMemorialDayFrom2022 = Holiday( 'Memorial Day', month=5, day=25, @@ -82,7 +82,7 @@ offset=DateOffset(weekday=MO(1)), ) -USMemorialDayPre2022 = Holiday( # 12:00pm early close +USMemorialDayPre2022 = Holiday( 'Memorial Day', month=5, day=25, @@ -122,6 +122,20 @@ ################################################# # US Labor Day Starting 1887 ################################################# +USLaborDayFrom2022 = Holiday( + 'Labor Day', + month=9, + day=1, + start_date=Timestamp('2022-01-01'), + offset=DateOffset(weekday=MO(1)), +) +USLaborDayPre2022 = Holiday( + 'Labor Day', + month=9, + day=1, + end_date=Timestamp('2021-12-31'), + offset=DateOffset(weekday=MO(1)), +) USLaborDay = Holiday( "Labor Day", month=9, @@ -155,6 +169,21 @@ offset=[DateOffset(weekday=TH(4)), Day(1)], ) +USThanksgivingFridayFrom2021 = Holiday( + 'Thanksgiving Friday', + month=11, + day=1, + offset=[DateOffset(weekday=TH(4)), Day(1)], + start_date=Timestamp('2021-01-01'), +) + +USThanksgivingFridayPre2021 = Holiday( + 'Thanksgiving Friday', + month=11, + day=1, + offset=[DateOffset(weekday=TH(4)), Day(1)], + end_date=Timestamp('2020-12-31'), +) ################################ # Christmas Dec 25 diff --git a/pandas_market_calendars/holidays_cn.py b/pandas_market_calendars/holidays/cn.py similarity index 100% rename from pandas_market_calendars/holidays_cn.py rename to pandas_market_calendars/holidays/cn.py diff --git a/pandas_market_calendars/holidays_jp.py b/pandas_market_calendars/holidays/jp.py similarity index 98% rename from pandas_market_calendars/holidays_jp.py rename to pandas_market_calendars/holidays/jp.py index 363f7d1..74f1a42 100644 --- a/pandas_market_calendars/holidays_jp.py +++ b/pandas_market_calendars/holidays/jp.py @@ -2,7 +2,7 @@ from pandas import DateOffset, Timestamp from pandas.tseries.holiday import Holiday, sunday_to_monday -from pandas_market_calendars.jpx_equinox import autumnal_citizen_dates, autumnal_equinox, vernal_equinox +from pandas_market_calendars.holidays.jpx_equinox import autumnal_citizen_dates, autumnal_equinox, vernal_equinox AscensionDays = [ Timestamp('2019-04-30', tz='UTC'), # National Holiday diff --git a/pandas_market_calendars/jpx_equinox.py b/pandas_market_calendars/holidays/jpx_equinox.py similarity index 100% rename from pandas_market_calendars/jpx_equinox.py rename to pandas_market_calendars/holidays/jpx_equinox.py diff --git a/pandas_market_calendars/holidays_nyse.py b/pandas_market_calendars/holidays/nyse.py similarity index 99% rename from pandas_market_calendars/holidays_nyse.py rename to pandas_market_calendars/holidays/nyse.py index e02771b..467b13d 100644 --- a/pandas_market_calendars/holidays_nyse.py +++ b/pandas_market_calendars/holidays/nyse.py @@ -1,3 +1,4 @@ +import pandas as pd from dateutil.relativedelta import (MO, TH, TU) from pandas import (DateOffset, Timestamp, date_range) from datetime import timedelta @@ -10,7 +11,7 @@ # main reference: # https://github.com/rsheftel/pandas_market_calendars/files/6827110/Stocks.NYSE-Closings.pdf # -# See exchange_calendar_nyse.py for details +# See nyse.py for details ################################################################################################# def previous_saturday(dt): @@ -302,9 +303,6 @@ def next_saturday(dt): start_date=Timestamp("1995-01-01"), ) -def july_5th_holiday_observance(datetime_index): - return datetime_index[datetime_index.year < 2013] - FridayAfterIndependenceDayNYSEpre2013 = Holiday( # When July 4th is a Thursday, the next day is a half day prior to 2013. # Since 2013 the early close is on Wednesday and Friday is a full day @@ -312,8 +310,8 @@ def july_5th_holiday_observance(datetime_index): month=7, day=5, days_of_week=(FRIDAY,), - observance=july_5th_holiday_observance, start_date=Timestamp("1996-01-01"), + end_date=Timestamp("2012-12-31"), ) WednesdayBeforeIndependenceDayPost2013 = Holiday( diff --git a/pandas_market_calendars/holidays_oz.py b/pandas_market_calendars/holidays/oz.py similarity index 100% rename from pandas_market_calendars/holidays_oz.py rename to pandas_market_calendars/holidays/oz.py diff --git a/pandas_market_calendars/holidays_sifma.py b/pandas_market_calendars/holidays/sifma.py similarity index 100% rename from pandas_market_calendars/holidays_sifma.py rename to pandas_market_calendars/holidays/sifma.py diff --git a/pandas_market_calendars/holidays_uk.py b/pandas_market_calendars/holidays/uk.py similarity index 100% rename from pandas_market_calendars/holidays_uk.py rename to pandas_market_calendars/holidays/uk.py diff --git a/pandas_market_calendars/holidays_us.py b/pandas_market_calendars/holidays/us.py similarity index 98% rename from pandas_market_calendars/holidays_us.py rename to pandas_market_calendars/holidays/us.py index 74f6855..00a9e40 100644 --- a/pandas_market_calendars/holidays_us.py +++ b/pandas_market_calendars/holidays/us.py @@ -10,10 +10,6 @@ # NYSE closed at 2:00 PM on Christmas Eve until 1993. -def july_5th_holiday_observance(datetime_index): - return datetime_index[datetime_index.year < 2013] - - def following_tuesday_every_four_years_observance(dt): return dt + DateOffset(years=(4 - (dt.year % 4)) % 4, weekday=TU(1)) @@ -201,8 +197,8 @@ def following_tuesday_every_four_years_observance(dt): month=7, day=5, days_of_week=(FRIDAY,), - observance=july_5th_holiday_observance, start_date=Timestamp("1995-01-01"), + end_date=Timestamp("2012-12-31"), ) WednesdayBeforeIndependenceDayPost2013 = Holiday( # When July 4th is a Thursday, the next day is a half day prior to 2013. diff --git a/pandas_market_calendars/market_calendar.py b/pandas_market_calendars/market_calendar.py index 72cee58..ce52033 100644 --- a/pandas_market_calendars/market_calendar.py +++ b/pandas_market_calendars/market_calendar.py @@ -421,17 +421,41 @@ def interruptions(self): """ return [] - def _convert(self, col): + def _convert(self, col: pd.Series): + """ + col is a series indexed by dates at which interruptions occurred. The values are either the start or end times + of an interruption, represented by either a timedelta or a tuple with a timedelta and day offset of the form + (timedelta, offset). _convert produces a new series where the values are replaced by datetimes equal to the + index of the original series plus the offset if present, at the timedelta. + + E.g.: + >>> self._convert( + pd.Series( + [datetime.time(11, 2), (datetime.time(11, 1), 1), datetime.time(10, 0), None], + index=pd.DatetimeIndex(['2002-02-03', '2010-01-11', '2010-01-13', '2011-01-10']) + ) + ) + 2002-02-03 2002-02-03 11:02:00+00:00 + 2010-01-11 2010-01-12 11:01:00+00:00 + 2010-01-13 2010-01-13 10:00:00+00:00 + 2011-01-10 NaT + dtype: datetime64[ns, UTC] + """ + col = col.dropna() # Python 3.8, pandas 2.0.3 cannot create time deltas from NaT try: times = col.str[0] except AttributeError: # no tuples, only offset 0 - return (pd.to_timedelta(col.astype("string"), errors="coerce") + col.index + return (pd.to_timedelta(col.astype("string").fillna(""), errors="coerce") + col.index ).dt.tz_localize(self.tz).dt.tz_convert("UTC") - return (pd.to_timedelta(times.fillna(col).astype("string"), errors="coerce" + return (pd.to_timedelta(times.fillna(col).astype("string").fillna(""), errors="coerce" ) + pd.to_timedelta(col.str[1].fillna(0), unit="D" ) + col.index ).dt.tz_localize(self.tz).dt.tz_convert("UTC") + @staticmethod + def _col_name(n: int): + return f"interruption_start_{n // 2 + 1}" if n % 2 == 1 else f"interruption_end_{n // 2}" + @property def interruptions_df(self): """ @@ -441,12 +465,7 @@ def interruptions_df(self): intr = pd.DataFrame(self.interruptions) intr.index = pd.to_datetime(intr.pop(0)) - columns = [] - for i in range(1, intr.shape[1] // 2 + 1): - i = str(i) - columns.append("interruption_start_" + i) - columns.append("interruption_end_" + i) - intr.columns = columns + intr.columns = map(self._col_name, intr.columns) intr.index.name = None return intr.apply(self._convert).sort_index() diff --git a/pyproject.toml b/pyproject.toml index ec38103..24ce55f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "pandas_market_calendars" -version = "4.2.1" +version = "4.3.0" authors = [ { name="Ryan Sheftel", email="rsheftel@alumni.upenn.edu" }, ] diff --git a/tests/test_asx_calendar.py b/tests/test_asx_calendar.py index 626d942..21a4bdc 100644 --- a/tests/test_asx_calendar.py +++ b/tests/test_asx_calendar.py @@ -3,7 +3,7 @@ import pytz import pandas as pd -from pandas_market_calendars.exchange_calendar_asx import ASXExchangeCalendar +from pandas_market_calendars.calendars.asx import ASXExchangeCalendar def test_time_zone(): diff --git a/tests/test_bmf_calendar.py b/tests/test_bmf_calendar.py index 6a5a2d9..520cce1 100644 --- a/tests/test_bmf_calendar.py +++ b/tests/test_bmf_calendar.py @@ -3,7 +3,7 @@ import pandas as pd import pytz -from pandas_market_calendars.exchange_calendar_bmf import BMFExchangeCalendar +from pandas_market_calendars.calendars.bmf import BMFExchangeCalendar def test_time_zone(): assert BMFExchangeCalendar().tz == pytz.timezone("America/Sao_Paulo") diff --git a/tests/test_bse_calendar.py b/tests/test_bse_calendar.py index d4b8087..809779b 100644 --- a/tests/test_bse_calendar.py +++ b/tests/test_bse_calendar.py @@ -3,7 +3,7 @@ import pandas as pd import pytz -from pandas_market_calendars.exchange_calendar_bse import BSEExchangeCalendar, BSEClosedDay +from pandas_market_calendars.calendars.bse import BSEExchangeCalendar, BSEClosedDay def test_time_zone(): diff --git a/tests/test_cboe_calendars.py b/tests/test_cboe_calendars.py index 1af08be..3889b65 100644 --- a/tests/test_cboe_calendars.py +++ b/tests/test_cboe_calendars.py @@ -1,7 +1,6 @@ import pandas as pd -from pandas_market_calendars.exchange_calendar_cboe import (CFEExchangeCalendar, - CBOEEquityOptionsExchangeCalendar) +from pandas_market_calendars.calendars.cboe import (CFEExchangeCalendar, CBOEEquityOptionsExchangeCalendar) calendars = (CFEExchangeCalendar, CBOEEquityOptionsExchangeCalendar) @@ -43,7 +42,6 @@ def test_2016_holidays(): def test_good_friday_rule(): # Good friday is a holiday unless Christmas Day or New Years Day is on a Friday for calendar in calendars: - cal = calendar() valid_days = cal.valid_days('2015-04-01', '2016-04-01') for day in ["2015-04-03", "2016-03-25"]: diff --git a/tests/test_cme_agriculture_calendar.py b/tests/test_cme_agriculture_calendar.py index fffefac..6998a14 100644 --- a/tests/test_cme_agriculture_calendar.py +++ b/tests/test_cme_agriculture_calendar.py @@ -1,7 +1,7 @@ import pandas as pd import pytz -from pandas_market_calendars.exchange_calendar_cme import CMEAgricultureExchangeCalendar +from pandas_market_calendars.calendars.cme import CMEAgricultureExchangeCalendar def test_time_zone(): diff --git a/tests/test_cme_bond_calendar.py b/tests/test_cme_bond_calendar.py index cb4b66a..4d41fc9 100644 --- a/tests/test_cme_bond_calendar.py +++ b/tests/test_cme_bond_calendar.py @@ -1,7 +1,7 @@ import pandas as pd import pytz -from pandas_market_calendars.exchange_calendar_cme import CMEBondExchangeCalendar +from pandas_market_calendars.calendars.cme import CMEBondExchangeCalendar def test_time_zone(): diff --git a/tests/test_cme_equity_calendar.py b/tests/test_cme_equity_calendar.py index 9ac0a22..140995e 100644 --- a/tests/test_cme_equity_calendar.py +++ b/tests/test_cme_equity_calendar.py @@ -1,7 +1,7 @@ import pandas as pd import pytz -from pandas_market_calendars.exchange_calendar_cme import CMEEquityExchangeCalendar +from pandas_market_calendars.calendars.cme import CMEEquityExchangeCalendar def test_time_zone(): diff --git a/tests/test_eurex_calendar.py b/tests/test_eurex_calendar.py index 19616fc..4c73a7d 100644 --- a/tests/test_eurex_calendar.py +++ b/tests/test_eurex_calendar.py @@ -1,7 +1,7 @@ import pandas as pd import pytz -from pandas_market_calendars.exchange_calendar_eurex import EUREXExchangeCalendar +from pandas_market_calendars.calendars.eurex import EUREXExchangeCalendar def test_time_zone(): diff --git a/tests/test_exchange_calendar_cme_globex_crypto.py b/tests/test_exchange_calendar_cme_globex_crypto.py new file mode 100644 index 0000000..cecfcc4 --- /dev/null +++ b/tests/test_exchange_calendar_cme_globex_crypto.py @@ -0,0 +1,286 @@ +import datetime as dt +import pandas as pd +import pytest +from pandas.tseries.offsets import Day, Hour, Minute + +from pandas_market_calendars.calendars.cme_globex_crypto import ( + CMEGlobexCryptoExchangeCalendar, +) + +TZ = "America/Chicago" + + +def test_is_different(): + cal = CMEGlobexCryptoExchangeCalendar() + sched = cal.schedule("2020-01-15", "2020-02-01") + + early = cal.early_closes(sched).index + assert early.shape == (1,) and early[0] == pd.Timestamp("2020-01-20") + + late = cal.late_opens(sched).index + assert late.empty + + sched.loc["2020-01-20", "market_open"] += pd.Timedelta("3H") + late = cal.late_opens(sched).index + assert late.shape == (1,) and late[0] == pd.Timestamp("2020-01-20") + + cal.change_time( + "market_open", ((None, dt.time(17), -1), ("2020-01-25", dt.time(9))) + ) + + different = cal.is_different(sched.market_open) + different = different[different].index + assert ( + different.shape == (6,) + and ( + different + == pd.DatetimeIndex( + [ + "2020-01-20", + "2020-01-27", + "2020-01-28", + "2020-01-29", + "2020-01-30", + "2020-01-31", + ], + dtype="datetime64[ns]", + freq=None, + ) + ).all() + ) + + +@pytest.mark.parametrize( + "day_status", + [ + # 2017 + # 2017 Christmas (25th = Monday) + ("2017-12-22", "open"), + ("2017-12-25", "closed"), + ("2017-12-26", "open"), + # 2017/18 New Year's (Dec 31 = Sunday) + ("2017-12-29", "open"), + ("2018-01-01", "closed"), + ("2018-01-02", "open"), + # 2018 + # 2018 Martin Luther King Day (15th = Monday) + ("2018-01-12", "open"), + ("2018-01-15", "1200"), + ("2018-01-16", "open"), + # 2018 Presidents Day (19th = Monday) + ("2018-02-16", "open"), + ("2018-02-19", "1200"), + ("2018-02-20", "open"), + # 2018 Good Friday (3/30th = Friday) + ("2018-03-29", "open"), + ("2018-03-30", "closed"), + ("2018-04-02", "open"), + # 2018 Memorial Day (May 28 = Monday) + ("2018-05-25", "open"), + ("2018-05-28", "1200"), + ("2018-05-29", "open"), + # 2018 Independence Day (4th = Wednesday) + ("2018-07-02", "open"), + ("2018-07-03", "1215"), + ("2018-07-04", "1200"), + ("2018-07-05", "open"), + # 2018 Labor Day (3rd = Monday) + ("2018-08-31", "open"), + ("2018-09-03", "1200"), + ("2018-09-04", "open"), + # 2018 Thanksgiving (22nd = Thursday) + ("2018-11-21", "open"), + ("2018-11-22", "1200"), + ("2018-11-23", "1215"), + ("2018-11-26", "open"), + # 2018 Christmas (25th = Friday) + ("2018-12-21", "open"), + ("2018-12-24", "1215"), + ("2018-12-25", "closed"), + ("2018-12-26", "open"), + # 2018/19 New Year's (Dec 31 = Thur) + ("2018-12-31", "open"), + ("2019-01-01", "closed"), + ("2019-01-02", "open"), + # 2019 + # 2019 Martin Luther King Day (21st = Monday) + ("2019-01-18", "open"), + ("2019-01-21", "1200"), + ("2019-01-22", "open"), + # 2019 Presidents Day (18th = Monday) + ("2019-02-15", "open"), + ("2019-02-18", "1200"), + ("2019-02-19", "open"), + # 2019 Good Friday (19th = Friday) + ("2019-04-18", "open"), + ("2019-04-19", "closed"), + ("2019-04-22", "open"), + # 2019 Memorial Day (May 27 = Monday) + ("2019-05-24", "open"), + ("2019-05-27", "1200"), + ("2019-05-28", "open"), + # 2019 Independence Day (4th = Thursday) + ("2019-07-02", "open"), + ("2019-07-03", "1215"), + ("2019-07-04", "1200"), + ("2019-07-05", "open"), + # 2019 Labor Day (2nd = Monday) + ("2019-08-30", "open"), + ("2019-09-02", "1200"), + ("2019-09-03", "open"), + # 2019 Thanksgiving (28 = Thursday) + ("2019-11-27", "open"), + ("2019-11-28", "1200"), + ("2019-11-29", "1215"), + ("2019-12-02", "open"), + # 2019 Christmas (25th = Wednesday) + ("2019-12-23", "open"), + ("2019-12-24", "1215"), + ("2019-12-25", "closed"), + ("2019-12-26", "open"), + # 2019/20 New Year's (Dec 31 = Thur) + ("2019-12-31", "open"), + ("2020-01-01", "closed"), + ("2020-01-02", "open"), + # 2020 + # 2020 Martin Luther King Day (20th = Monday) + ("2020-01-17", "open"), + ("2020-01-20", "1200"), + ("2020-01-21", "open"), + # 2020 Presidents Day (17th = Monday) + ("2020-02-14", "open"), + ("2020-02-17", "1200"), + ("2020-02-18", "open"), + # 2020 Good Friday (10th = Friday) + ("2020-04-09", "open"), + ("2020-04-10", "closed"), + ("2020-04-13", "open"), + # 2020 Memorial Day (May 25 = Monday) + ("2020-05-22", "open"), + ("2020-05-25", "1200"), + ("2020-05-26", "open"), + # 2020 Independence Day (4th = Saturday) + ("2020-07-02", "open"), + ("2020-07-03", "1200"), + ("2020-07-06", "open"), + # 2020 Labor Day (4th = Monday) + ("2020-09-04", "open"), + ("2020-09-07", "1200"), + ("2020-09-08", "open"), + # 2020 Thanksgiving (26th = Thursday) + ("2020-11-25", "open"), + ("2020-11-26", "1200"), + ("2020-11-27", "1215"), + ("2020-11-30", "open"), + # 2020 Christmas (25th = Friday) + ("2020-12-23", "open"), + ("2020-12-24", "1215"), + ("2020-12-25", "closed"), + ("2020-12-28", "open"), + # 2020/21 New Year's (Dec 31 = Thur) + ("2020-12-31", "open"), + ("2021-01-01", "closed"), + ("2021-01-04", "open"), + # 2021 + # 2021 Martin Luther King Day (18th = Monday) + ("2021-01-15", "open"), + ("2021-01-18", "1200"), + ("2021-01-19", "open"), + # 2021 Presidents Day (15th = Monday) + ("2021-02-12", "open"), + ("2021-02-15", "1200"), + ("2021-02-16", "open"), + # 2021 Good Friday (2nd = Friday) + ("2021-04-01", "open"), + ("2021-04-02", "0815"), + ("2021-04-05", "open"), + # 2021 Memorial Day (May 31 = Monday) + ("2021-05-28", "open"), + ("2021-05-31", "1200"), + ("2021-06-01", "open"), + # 2021 Independence Day (4th = Sunday) + ("2021-07-02", "open"), + ("2021-07-05", "1200"), + ("2021-07-06", "open"), + # 2021 Labor Day (6th = Monday) + ("2021-09-03", "open"), + ("2021-09-06", "1200"), + ("2021-09-07", "open"), + # 2021 Thanksgiving (25th = Thursday) + ("2021-11-24", "open"), + ("2021-11-25", "1200"), + ("2021-11-26", "1245"), + # 2021 Christmas (25th = Saturday) + ("2021-12-23", "open"), + ("2021-12-24", "closed"), + ("2021-12-27", "open"), + # 2021/22 New Year's (Dec 31 = Friday) + ("2021-12-31", "open"), + ("2022-01-03", "open"), + ("2022-01-03", "open"), + # 2022 + # 2022 Martin Luther King Day (17th = Monday) + ("2022-01-14", "open"), + ("2022-01-17", "1600"), + ("2022-01-18", "open"), + # 2022 President's Day (21st = Monday) + ("2022-02-18", "open"), + ("2022-02-21", "1600"), + ("2022-02-22", "open"), + # 2022 Good Friday (15 = Friday) + ("2022-04-14", "open"), + ("2022-04-15", "closed"), + ("2022-04-18", "open"), + # 2022 Memorial Day (30th = Monday) + ("2022-05-27", "open"), + ("2022-05-30", "1600"), + ("2022-05-31", "open"), + # 2022 Juneteenth (20th = Monday) + ("2022-06-17", "open"), + ("2022-06-20", "1600"), + ("2022-06-21", "open"), + # 2022 Independence Day (4th = Monday) + ("2022-07-01", "open"), + ("2022-07-04", "1600"), + ("2022-07-05", "open"), + # 2022 Labor Day (5th = Monday) + ("2022-09-02", "open"), + ("2022-09-05", "1600"), + ("2022-09-06", "open"), + # 2022 Thanksgiving (24th = Thursday) + ("2022-11-23", "open"), + ("2022-11-24", "1600"), + ("2022-11-25", "1245"), + ("2022-11-28", "open"), + # 2022 Christmas (25 = Sunday) + ("2022-12-23", "open"), + ("2022-12-26", "closed"), + ("2022-12-27", "open"), + # 2022/23 New Years (Jan 1 = Sunday) + ("2022-12-30", "open"), + ("2023-01-02", "closed"), + ("2023-01-03", "open"), + ], + ids=lambda x: f"{x[0]} {x[1]}", +) +def test_2020_through_2022_and_prior_holidays(day_status): + day_str = day_status[0] + day_ts = pd.Timestamp(day_str, tz=TZ) + expected_status = day_status[1] + + year = int(day_str.split("-")[0]) + under_test = CMEGlobexCryptoExchangeCalendar() + schedule = under_test.schedule(f"{year}-01-01", f"{year+1}-01-01", tz=TZ) + + if expected_status == "open": + s = schedule.loc[day_str] + assert s["market_open"] == day_ts + Day(-1) + Hour(17) + Minute(0) + assert s["market_close"] == day_ts + Day(0) + Hour(16) + Minute(0) + elif expected_status == "closed": + assert day_ts.tz_localize(None) not in schedule.index + else: # expected_status contains a special close time like 1215 + s = schedule.loc[day_str] + hour = int(expected_status[0:2]) + minute = int(expected_status[2:4]) + assert s["market_open"] == day_ts + Day(-1) + Hour(17) + assert s["market_close"] == day_ts + Day(0) + Hour(hour) + Minute(minute) diff --git a/tests/test_exchange_calendar_cme_globex_energy_and_metals.py b/tests/test_exchange_calendar_cme_globex_energy_and_metals.py index 5524f21..1b09606 100644 --- a/tests/test_exchange_calendar_cme_globex_energy_and_metals.py +++ b/tests/test_exchange_calendar_cme_globex_energy_and_metals.py @@ -4,7 +4,7 @@ from pandas.testing import assert_index_equal from pandas.tseries.offsets import CustomBusinessDay -from pandas_market_calendars.exchange_calendar_cme_globex_energy_and_metals import CMEGlobexEnergyAndMetalsExchangeCalendar +from pandas_market_calendars.calendars.cme_globex_energy_and_metals import CMEGlobexEnergyAndMetalsExchangeCalendar diff --git a/tests/test_exchange_calendar_cme_globex_equities.py b/tests/test_exchange_calendar_cme_globex_equities.py index f501981..7274aa7 100644 --- a/tests/test_exchange_calendar_cme_globex_equities.py +++ b/tests/test_exchange_calendar_cme_globex_equities.py @@ -1,10 +1,9 @@ import datetime as dt import pandas as pd import pytest -import pytz from pandas.tseries.offsets import Day, Hour, Minute -from pandas_market_calendars.exchange_calendar_cme_globex_equities import CMEGlobexEquitiesExchangeCalendar +from pandas_market_calendars.calendars.cme_globex_equities import CMEGlobexEquitiesExchangeCalendar TZ = 'America/Chicago' diff --git a/tests/test_exchange_calendar_cme_globex_fixed_income.py b/tests/test_exchange_calendar_cme_globex_fixed_income.py index 023f68e..c8fbab4 100644 --- a/tests/test_exchange_calendar_cme_globex_fixed_income.py +++ b/tests/test_exchange_calendar_cme_globex_fixed_income.py @@ -3,7 +3,7 @@ import pytz from pandas.tseries.offsets import Day, Hour, Minute -from pandas_market_calendars.exchange_calendar_cme_globex_fixed_income import CMEGlobexFixedIncomeCalendar +from pandas_market_calendars.calendars.cme_globex_fixed_income import CMEGlobexFixedIncomeCalendar TZ = 'America/Chicago' diff --git a/tests/test_exchange_calendar_cme_globex_fx.py b/tests/test_exchange_calendar_cme_globex_fx.py index 19e2605..43777fb 100644 --- a/tests/test_exchange_calendar_cme_globex_fx.py +++ b/tests/test_exchange_calendar_cme_globex_fx.py @@ -3,7 +3,7 @@ import pytz from pandas.tseries.offsets import Day, Hour, Minute -from pandas_market_calendars.exchange_calendar_cme_globex_fx import CMEGlobexFXExchangeCalendar +from pandas_market_calendars.calendars.cme_globex_fx import CMEGlobexFXExchangeCalendar TZ = 'America/Chicago' diff --git a/tests/test_hkex_calendar.py b/tests/test_hkex_calendar.py index b64b928..1204c5a 100644 --- a/tests/test_hkex_calendar.py +++ b/tests/test_hkex_calendar.py @@ -3,7 +3,7 @@ import pandas as pd import pytz -from pandas_market_calendars.exchange_calendar_hkex import HKEXExchangeCalendar +from pandas_market_calendars.calendars.hkex import HKEXExchangeCalendar def test_time_zone(): diff --git a/tests/test_ice_calendar.py b/tests/test_ice_calendar.py index 22719ed..315f76c 100644 --- a/tests/test_ice_calendar.py +++ b/tests/test_ice_calendar.py @@ -1,6 +1,6 @@ import pandas as pd -from pandas_market_calendars.exchange_calendar_ice import ICEExchangeCalendar +from pandas_market_calendars.calendars.ice import ICEExchangeCalendar def test_test_name(): diff --git a/tests/test_iex_calendar.py b/tests/test_iex_calendar.py index 0752050..18d9e0e 100644 --- a/tests/test_iex_calendar.py +++ b/tests/test_iex_calendar.py @@ -2,7 +2,7 @@ import numpy as np from datetime import time from pytz import timezone -from pandas_market_calendars.exchange_calendar_iex import IEXExchangeCalendar +from pandas_market_calendars.calendars.iex import IEXExchangeCalendar from pandas_market_calendars.class_registry import ProtectedDict iex = IEXExchangeCalendar() diff --git a/tests/test_jpx_calendar.py b/tests/test_jpx_calendar.py index 11da106..ff496c2 100644 --- a/tests/test_jpx_calendar.py +++ b/tests/test_jpx_calendar.py @@ -5,7 +5,7 @@ import pytz from pandas.testing import assert_index_equal -from pandas_market_calendars.exchange_calendar_jpx import JPXExchangeCalendar +from pandas_market_calendars.calendars.jpx import JPXExchangeCalendar def test_time_zone(): diff --git a/tests/test_lse_calendar.py b/tests/test_lse_calendar.py index eff1246..9c902d5 100644 --- a/tests/test_lse_calendar.py +++ b/tests/test_lse_calendar.py @@ -3,7 +3,7 @@ import pandas as pd import pytz -from pandas_market_calendars.exchange_calendar_lse import LSEExchangeCalendar +from pandas_market_calendars.calendars.lse import LSEExchangeCalendar def test_time_zone(): diff --git a/tests/test_market_calendar.py b/tests/test_market_calendar.py index 14c184e..311b4fc 100644 --- a/tests/test_market_calendar.py +++ b/tests/test_market_calendar.py @@ -25,12 +25,12 @@ from pandas.tseries.holiday import AbstractHolidayCalendar from pandas_market_calendars import get_calendar, get_calendar_names -from pandas_market_calendars.holidays_us import (Christmas, HurricaneSandyClosings, MonTuesThursBeforeIndependenceDay, +from pandas_market_calendars.holidays.us import (Christmas, HurricaneSandyClosings, MonTuesThursBeforeIndependenceDay, USNationalDaysofMourning, USNewYearsDay) -from pandas_market_calendars.holidays_nyse import Sept11Anniversary12pmLateOpen2002 +from pandas_market_calendars.holidays.nyse import Sept11Anniversary12pmLateOpen2002 from pandas_market_calendars.market_calendar import MarketCalendar #, clean_dates, days_at_time -from pandas_market_calendars.exchange_calendars_mirror import TradingCalendar -from pandas_market_calendars.exchange_calendar_nyse import NYSEExchangeCalendar +from pandas_market_calendars.calendars.mirror import TradingCalendar +from pandas_market_calendars.calendars.nyse import NYSEExchangeCalendar import exchange_calendars as ecal @@ -295,7 +295,7 @@ def test_add_change_remove_time_w_open_close_map(): assert not "newtime" in cal.open_close_map and "newtime" in cal.regular_market_times cal.remove_time("newtime") - assert not "newtime" in cal.regular_market_times + assert "newtime" not in cal.regular_market_times cal.add_time("newtime", time(10), opens= None) assert not "newtime" in cal.open_close_map and "newtime" in cal.regular_market_times @@ -544,10 +544,13 @@ def test_schedule(): assert_series_equal(results.iloc[-1], expected) # one day schedule - expected = pd.DataFrame({'market_open': pd.Timestamp('2016-12-01 03:13:00+0000', tz='UTC'), - 'market_close': pd.Timestamp('2016-12-01 03:49:00+0000', tz='UTC')}, - index=pd.DatetimeIndex([pd.Timestamp('2016-12-01')], freq='C'), - columns=['market_open', 'market_close']) + expected = pd.DataFrame( + {'market_open': pd.Timestamp('2016-12-01 03:13:00+0000', tz='UTC'), + 'market_close': pd.Timestamp('2016-12-01 03:49:00+0000', tz='UTC')}, + index=pd.DatetimeIndex([pd.Timestamp('2016-12-01')], freq='C'), + columns=['market_open', 'market_close'], + dtype="datetime64[ns, UTC]" + ) actual = cal.schedule('2016-12-01', '2016-12-01') if pd.__version__ < '1.1.0': assert_frame_equal(actual, expected) @@ -557,12 +560,15 @@ def test_schedule(): # start date after end date with pytest.raises(ValueError): cal.schedule('2016-02-02', '2016-01-01') - + # using a different time zone - expected = pd.DataFrame({'market_open': pd.Timestamp('2016-11-30 22:13:00-05:00', tz='US/Eastern'), - 'market_close': pd.Timestamp('2016-11-30 22:49:00-05:00', tz='US/Eastern')}, - index=pd.DatetimeIndex([pd.Timestamp('2016-12-01')]), - columns=['market_open', 'market_close']) + expected = pd.DataFrame( + {'market_open': pd.Timestamp('2016-11-30 22:13:00-05:00', tz='US/Eastern'), + 'market_close': pd.Timestamp('2016-11-30 22:49:00-05:00', tz='US/Eastern')}, + index=pd.DatetimeIndex([pd.Timestamp('2016-12-01')]), + columns=['market_open', 'market_close'], + dtype="datetime64[ns, US/Eastern]" + ) actual = cal.schedule('2016-12-01', '2016-12-01', tz='US/Eastern') if pd.__version__ < '1.1.0': @@ -704,12 +710,15 @@ def test_schedule_w_breaks(): assert_series_equal(results.iloc[-1], expected) # using a different time zone - expected = pd.DataFrame({'market_open': pd.Timestamp('2016-12-28 09:30:00-05:00', tz='America/New_York'), - 'market_close': pd.Timestamp('2016-12-28 12:00:00-05:00', tz='America/New_York'), - 'break_start': pd.Timestamp('2016-12-28 10:00:00-05:00', tz='America/New_York'), - 'break_end': pd.Timestamp('2016-12-28 11:00:00-05:00', tz='America/New_York')}, - index=pd.DatetimeIndex([pd.Timestamp('2016-12-28')]), - columns=['market_open', 'break_start', 'break_end', 'market_close']) + expected = pd.DataFrame( + {'market_open': pd.Timestamp('2016-12-28 09:30:00-05:00', tz='America/New_York'), + 'market_close': pd.Timestamp('2016-12-28 12:00:00-05:00', tz='America/New_York'), + 'break_start': pd.Timestamp('2016-12-28 10:00:00-05:00', tz='America/New_York'), + 'break_end': pd.Timestamp('2016-12-28 11:00:00-05:00', tz='America/New_York')}, + index=pd.DatetimeIndex([pd.Timestamp('2016-12-28')]), + columns=['market_open', 'break_start', 'break_end', 'market_close'], + dtype="datetime64[ns, America/New_York]" + ) actual = cal.schedule('2016-12-28', '2016-12-28', tz='America/New_York') if pd.__version__ < '1.1.0': diff --git a/tests/test_nyse_calendar.py b/tests/test_nyse_calendar.py index e215994..cfbb9a7 100644 --- a/tests/test_nyse_calendar.py +++ b/tests/test_nyse_calendar.py @@ -5,7 +5,7 @@ import pytz from pandas.testing import assert_index_equal, assert_series_equal -from pandas_market_calendars.exchange_calendar_nyse import NYSEExchangeCalendar +from pandas_market_calendars.calendars.nyse import NYSEExchangeCalendar def test_custom_open_close(): @@ -347,7 +347,7 @@ def test_all_full_day_holidays_since_1928(request): assert_index_equal(expected, actual) # using the holidays method - actual = pd.DatetimeIndex(nyse.holidays().holidays).unique().astype('datetime64[ns]') + actual = pd.DatetimeIndex(nyse.holidays().holidays, dtype='datetime64[ns]').unique() slice_locs = actual.slice_locs(expected[0], expected[-1]) actual = actual[slice_locs[0]:slice_locs[1]] assert_index_equal(expected, actual) diff --git a/tests/test_nyse_calendar_early_years.py b/tests/test_nyse_calendar_early_years.py index 68eb3c5..e70e496 100644 --- a/tests/test_nyse_calendar_early_years.py +++ b/tests/test_nyse_calendar_early_years.py @@ -4,7 +4,7 @@ from pandas.testing import assert_index_equal from pandas.tseries.offsets import CustomBusinessDay -from pandas_market_calendars.exchange_calendar_nyse import NYSEExchangeCalendar +from pandas_market_calendars.calendars.nyse import NYSEExchangeCalendar nyse = NYSEExchangeCalendar() diff --git a/tests/test_ose_calendar.py b/tests/test_ose_calendar.py index c558bd4..4df63c7 100644 --- a/tests/test_ose_calendar.py +++ b/tests/test_ose_calendar.py @@ -11,7 +11,7 @@ import pytest import pytz -from pandas_market_calendars.exchange_calendar_ose import OSEExchangeCalendar +from pandas_market_calendars.calendars.ose import OSEExchangeCalendar TIMEZONE = pytz.timezone("Europe/Oslo") diff --git a/tests/test_sifma_calendars.py b/tests/test_sifma_calendars.py index da3d4e6..d990dd2 100644 --- a/tests/test_sifma_calendars.py +++ b/tests/test_sifma_calendars.py @@ -4,9 +4,9 @@ from pandas.testing import assert_index_equal -from pandas_market_calendars.exchange_calendar_sifma import (SIFMAUSExchangeCalendar, - SIFMAUKExchangeCalendar, - SIFMAJPExchangeCalendar) +from pandas_market_calendars.calendars.sifma import (SIFMAUSExchangeCalendar, + SIFMAUKExchangeCalendar, + SIFMAJPExchangeCalendar) ######################################################################### diff --git a/tests/test_six_calendar.py b/tests/test_six_calendar.py index 15901e5..d159a88 100644 --- a/tests/test_six_calendar.py +++ b/tests/test_six_calendar.py @@ -1,7 +1,7 @@ import pandas as pd import pytz -from pandas_market_calendars.exchange_calendar_six import SIXExchangeCalendar +from pandas_market_calendars.calendars.six import SIXExchangeCalendar def test_time_zone(): diff --git a/tests/test_sse_calendar.py b/tests/test_sse_calendar.py index 6c16d82..11ec301 100644 --- a/tests/test_sse_calendar.py +++ b/tests/test_sse_calendar.py @@ -3,8 +3,8 @@ import pandas as pd import pytz -from pandas_market_calendars.exchange_calendar_sse import SSEExchangeCalendar -from pandas_market_calendars.holidays_cn import all_holidays +from pandas_market_calendars.calendars.sse import SSEExchangeCalendar +from pandas_market_calendars.holidays.cn import all_holidays all_holidays = pd.DatetimeIndex(all_holidays) diff --git a/tests/test_tsx_calendar.py b/tests/test_tsx_calendar.py index 00eb589..dc57c51 100644 --- a/tests/test_tsx_calendar.py +++ b/tests/test_tsx_calendar.py @@ -2,7 +2,7 @@ import pytz from pandas.testing import assert_index_equal -from pandas_market_calendars.exchange_calendar_tsx import TSXExchangeCalendar, VictoriaDay +from pandas_market_calendars.calendars.tsx import TSXExchangeCalendar, VictoriaDay def test_time_zone(): diff --git a/tests/test_utils.py b/tests/test_utils.py index 65592b5..1be603a 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -5,7 +5,7 @@ from pandas.testing import assert_frame_equal, assert_index_equal import pandas_market_calendars as mcal -from pandas_market_calendars.exchange_calendar_nyse import NYSEExchangeCalendar +from pandas_market_calendars.calendars.nyse import NYSEExchangeCalendar from tests.test_market_calendar import FakeCalendar, FakeBreakCalendar