Skip to content

Commit

Permalink
fix get_next_market_open/close (#33)
Browse files Browse the repository at this point in the history
* fix get_next_market_open/close logic

* bump

* crypto return none for next market open

* add unit tests and fix logic

* update python dep to 3.9

* update pytest to 3.9
  • Loading branch information
cctdaniel authored Jun 22, 2023
1 parent 944a24b commit 17005ee
Show file tree
Hide file tree
Showing 4 changed files with 416 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9"]
python-version: ["3.9"]

steps:
- uses: actions/checkout@v2
Expand Down
70 changes: 52 additions & 18 deletions pythclient/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,19 @@ def is_market_open(asset_type: str, dt: datetime.datetime) -> bool:
if (
date in EQUITY_EARLY_HOLIDAYS
and time >= EQUITY_OPEN
and time <= EQUITY_EARLY_CLOSE
and time < EQUITY_EARLY_CLOSE
):
return True
return False
if day < 5 and time >= EQUITY_OPEN and time <= EQUITY_CLOSE:
if day < 5 and time >= EQUITY_OPEN and time < EQUITY_CLOSE:
return True
return False

if asset_type in ["fx", "metal"]:
if date in FX_METAL_HOLIDAYS:
return False
# On Friday the market is closed after 5pm
if day == 4 and time > FX_METAL_OPEN_CLOSE_TIME:
if day == 4 and time >= FX_METAL_OPEN_CLOSE_TIME:
return False
# On Saturday the market is closed all the time
if day == 5:
Expand All @@ -79,9 +79,6 @@ def get_next_market_open(asset_type: str, dt: datetime.datetime) -> str:
dt = dt.astimezone(NY_TZ)
time = dt.time()

if is_market_open(asset_type, dt):
return dt.astimezone(UTC_TZ).strftime("%Y-%m-%dT%H:%M:%S") + "Z"

if asset_type == "equity":
if time < EQUITY_OPEN:
next_market_open = dt.replace(
Expand Down Expand Up @@ -113,30 +110,53 @@ def get_next_market_open(asset_type: str, dt: datetime.datetime) -> str:
second=0,
microsecond=0,
)
next_market_open += datetime.timedelta(days=1)
while is_market_open(asset_type, next_market_open):
next_market_open += datetime.timedelta(days=1)

else:
next_market_open = dt.replace(hour=0, minute=0, second=0, microsecond=0)
next_market_open += datetime.timedelta(days=1)
return None

while not is_market_open(asset_type, next_market_open):
next_market_open += datetime.timedelta(days=1)

return next_market_open.astimezone(UTC_TZ).strftime("%Y-%m-%dT%H:%M:%S") + "Z"


def get_next_market_close(asset_type: str, dt: datetime.datetime) -> str:
# make sure time is in NY timezone
dt = dt.astimezone(NY_TZ)
if not is_market_open(asset_type, dt):
return dt.astimezone(UTC_TZ).strftime("%Y-%m-%dT%H:%M:%S") + "Z"
time = dt.time()

if asset_type == "equity":
if dt.date() in EQUITY_EARLY_HOLIDAYS:

next_market_close = dt.replace(
hour=EQUITY_EARLY_CLOSE.hour,
minute=EQUITY_EARLY_CLOSE.minute,
second=0,
microsecond=0,
if time < EQUITY_EARLY_CLOSE:
next_market_close = dt.replace(
hour=EQUITY_EARLY_CLOSE.hour,
minute=EQUITY_EARLY_CLOSE.minute,
second=0,
microsecond=0,
)
else:
next_market_close = dt.replace(
hour=EQUITY_CLOSE.hour,
minute=EQUITY_CLOSE.minute,
second=0,
microsecond=0,
)
next_market_close += datetime.timedelta(days=1)
elif dt.date() in EQUITY_HOLIDAYS:
next_market_open = get_next_market_open(
asset_type, dt + datetime.timedelta(days=1)
)
next_market_close = (
datetime.datetime.fromisoformat(next_market_open.replace("Z", "+00:00"))
.astimezone(NY_TZ)
.replace(
hour=EQUITY_CLOSE.hour,
minute=EQUITY_CLOSE.minute,
second=0,
microsecond=0,
)
)
else:
next_market_close = dt.replace(
Expand All @@ -145,14 +165,28 @@ def get_next_market_close(asset_type: str, dt: datetime.datetime) -> str:
second=0,
microsecond=0,
)
if time >= EQUITY_CLOSE:
next_market_close += datetime.timedelta(days=1)

# while next_market_close.date() is in EQUITY_HOLIDAYS or weekend, add 1 day
while (
next_market_close.date() in EQUITY_HOLIDAYS
or next_market_close.weekday() >= 5
):
next_market_close += datetime.timedelta(days=1)

elif asset_type in ["fx", "metal"]:
next_market_close = dt.replace(
hour=FX_METAL_OPEN_CLOSE_TIME.hour,
minute=FX_METAL_OPEN_CLOSE_TIME.minute,
second=0,
microsecond=0,
)
else: # crypto markets never close
while not is_market_open(asset_type, next_market_close):
next_market_close += datetime.timedelta(days=1)
while is_market_open(asset_type, next_market_close):
next_market_close += datetime.timedelta(days=1)
else: # crypto markets never close
return None

return next_market_close.astimezone(UTC_TZ).strftime("%Y-%m-%dT%H:%M:%S") + "Z"
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

setup(
name='pythclient',
version='0.1.6',
version='0.1.7',
packages=['pythclient'],
author='Pyth Developers',
author_email='contact@pyth.network',
Expand All @@ -28,5 +28,5 @@
'testing': requirements + ['mock', 'pytest', 'pytest-cov', 'pytest-socket',
'pytest-mock', 'pytest-asyncio'],
},
python_requires='>=3.7.0',
python_requires='>=3.9.0',
)
Loading

0 comments on commit 17005ee

Please sign in to comment.