Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix fx bug and add 2024 calendar #45

Merged
merged 2 commits into from
Dec 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion pythclient/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,22 @@
datetime.datetime(2022, 9, 4, tzinfo=NY_TZ).date(),
datetime.datetime(2023, 11, 23, tzinfo=NY_TZ).date(),
datetime.datetime(2023, 12, 25, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 1, 1, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 1, 15, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 2, 19, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 3, 29, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 5, 27, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 6, 19, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 7, 4, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 9, 2, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 11, 28, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 12, 25, tzinfo=NY_TZ).date(),
]
NYSE_EARLY_HOLIDAYS = [
datetime.datetime(2023, 7, 3, tzinfo=NY_TZ).date(),
datetime.datetime(2023, 11, 24, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 7, 3, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 11, 29, tzinfo=NY_TZ).date(),
]

FX_METAL_OPEN_CLOSE_TIME = datetime.time(17, 0, 0, tzinfo=NY_TZ)
Expand All @@ -35,6 +47,8 @@
FX_METAL_HOLIDAYS = [
datetime.datetime(2023, 1, 1, tzinfo=NY_TZ).date(),
datetime.datetime(2023, 12, 25, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 1, 1, tzinfo=NY_TZ).date(),
datetime.datetime(2024, 12, 25, tzinfo=NY_TZ).date(),
]

RATES_OPEN = datetime.time(8, 0, 0, tzinfo=NY_TZ)
Expand All @@ -60,7 +74,7 @@ def is_market_open(asset_type: str, dt: datetime.datetime) -> bool:
return False

if asset_type in ["fx", "metal"]:
if date in FX_METAL_HOLIDAYS:
if date in FX_METAL_HOLIDAYS and time < FX_METAL_OPEN_CLOSE_TIME:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you double check this?

return False
# On Friday the market is closed after 5pm
if day == 4 and time >= FX_METAL_OPEN_CLOSE_TIME:
Expand All @@ -71,6 +85,13 @@ def is_market_open(asset_type: str, dt: datetime.datetime) -> bool:
# On Sunday the market is closed before 5pm
if day == 6 and time < FX_METAL_OPEN_CLOSE_TIME:
return False
# On Sunday the market is closed after 5pm if the next day is a holiday
if (
day == 6
and time >= FX_METAL_OPEN_CLOSE_TIME
and (date + datetime.timedelta(days=1) in FX_METAL_HOLIDAYS)
):
return False

return True

Expand Down
22 changes: 20 additions & 2 deletions tests/test_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
FX_METAL_OPEN_WED_2023_6_21_23 = datetime.datetime(2023, 6, 21, 23, 0, 0, tzinfo=NY_TZ)
FX_METAL_CLOSE_SUN_2023_6_18_16 = datetime.datetime(2023, 6, 18, 16, 0, 0, tzinfo=NY_TZ)
FX_METAL_HOLIDAY_SUN_2023_1_1 = datetime.datetime(2023, 1, 1, tzinfo=NY_TZ)
FX_METAL_HOLIDAY_SUN_2023_12_24_17 = datetime.datetime(2023, 12, 24, 17, 0, 0, tzinfo=NY_TZ)
FX_METAL_HOLIDAY_SUN_2023_12_31_17 = datetime.datetime(2023, 12, 31, 17, 0, 0, tzinfo=NY_TZ)

# Define constants for rates market
RATES_OPEN_WED_2023_6_21_12 = datetime.datetime(2023, 6, 21, 8, 0, 0, tzinfo=NY_TZ)
Expand Down Expand Up @@ -75,6 +77,12 @@ def test_is_market_open():
assert is_market_open("fx", FX_METAL_HOLIDAY_SUN_2023_1_1) == False
assert is_market_open("metal", FX_METAL_HOLIDAY_SUN_2023_1_1) == False

# fx & metal out of market hours on Sunday Dec 24 2023 after 10pm UTC
assert is_market_open("fx", FX_METAL_HOLIDAY_SUN_2023_12_24_17) == False

# fx & metal out of market hours on Sunday Dec 31 2023 after 10pm UTC
assert is_market_open("fx", FX_METAL_HOLIDAY_SUN_2023_12_31_17) == False

# rates
# weekday, within rates market hours
assert is_market_open("rates", RATES_OPEN_WED_2023_6_21_12) == True
Expand Down Expand Up @@ -167,14 +175,24 @@ def test_get_next_market_open():
== format_datetime_to_unix_timestamp(datetime.datetime(2023, 6, 18, 17, 0, 0, tzinfo=NY_TZ))
)

# fx & metal out of market hours on Sunday Dec 24 2024 after 10pm UTC
assert (
get_next_market_open("fx", FX_METAL_HOLIDAY_SUN_2023_12_24_17)
== format_datetime_to_unix_timestamp(datetime.datetime(2023, 12, 25, 17, 0, 0, tzinfo=NY_TZ))
)
assert (
get_next_market_open("metal", FX_METAL_HOLIDAY_SUN_2023_12_24_17)
== format_datetime_to_unix_timestamp(datetime.datetime(2023, 12, 25, 17, 0, 0, tzinfo=NY_TZ))
)

# fx & metal holiday
assert (
get_next_market_open("fx", FX_METAL_HOLIDAY_SUN_2023_1_1)
== format_datetime_to_unix_timestamp(datetime.datetime(2023, 1, 2, 17, 0, 0, tzinfo=NY_TZ))
== format_datetime_to_unix_timestamp(datetime.datetime(2023, 1, 1, 17, 0, 0, tzinfo=NY_TZ))
)
assert (
get_next_market_open("metal", FX_METAL_HOLIDAY_SUN_2023_1_1)
== format_datetime_to_unix_timestamp(datetime.datetime(2023, 1, 2, 17, 0, 0, tzinfo=NY_TZ))
== format_datetime_to_unix_timestamp(datetime.datetime(2023, 1, 1, 17, 0, 0, tzinfo=NY_TZ))
)

# rates within market hours
Expand Down