Skip to content

Commit 622615a

Browse files
authored
added check if market is open at this moment in utils (#288)
* added check if market is open at this moment * added test * works for half days now.
1 parent 88cf0ae commit 622615a

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed

tastytrade/utils.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,31 @@ def today_in_new_york() -> date:
4040
return now_in_new_york().date()
4141

4242

43+
def is_market_open_now() -> bool:
44+
"""
45+
Check if the market is currently open.
46+
47+
Returns True if:
48+
- The market is open on the current date (not a holiday/weekend)
49+
- The current Eastern Time hour is between [ 9:30 AM, 4:00 PM )
50+
- or on half days between [ 9:30 AM, 1:00 PM )
51+
52+
Returns:
53+
bool: True if market is open now, False otherwise
54+
"""
55+
today = today_in_new_york()
56+
sched = NYSE.schedule(start_date=today, end_date=today)
57+
if sched.empty:
58+
# Closed full day (weekend or holiday)
59+
return False
60+
61+
# Use iloc[0] since schedule has only one row for a single day
62+
market_open = sched.iloc[0]["market_open"]
63+
market_close = sched.iloc[0]["market_close"]
64+
65+
return market_open <= now_in_new_york() < market_close
66+
67+
4368
def is_market_open_on(day: date | None = None) -> bool:
4469
"""
4570
Returns whether the market was/is/will be open at ANY point

tests/test_utils.py

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from datetime import date
1+
from datetime import date, datetime
2+
from unittest.mock import patch
3+
from zoneinfo import ZoneInfo
24

35
from tastytrade.utils import (
46
get_future_fx_monthly,
@@ -9,9 +11,12 @@
911
get_future_treasury_monthly,
1012
get_tasty_monthly,
1113
get_third_friday,
14+
is_market_open_now,
1215
today_in_new_york,
1316
)
1417

18+
TZ = ZoneInfo("US/Eastern")
19+
1520

1621
def test_get_third_friday():
1722
assert get_third_friday(date(2024, 3, 2)) == date(2024, 3, 15)
@@ -158,3 +163,68 @@ def test_get_future_index_monthly():
158163
]
159164
for exp in exps:
160165
assert get_future_index_monthly(exp) == exp
166+
167+
168+
def test_is_market_open_now():
169+
# Use a known Tuesday (March 12, 2024) for weekday tests
170+
tuesday = datetime(2024, 3, 12, 10, 0, 0, tzinfo=TZ)
171+
172+
# Test market open during trading hours (10:00 AM on a weekday)
173+
with patch("tastytrade.utils.datetime") as mock_datetime:
174+
mock_datetime.now.return_value = tuesday
175+
assert is_market_open_now() is True
176+
177+
# Test market closed before opening (8:00 AM on a weekday)
178+
with patch("tastytrade.utils.datetime") as mock_datetime:
179+
mock_datetime.now.return_value = datetime(2024, 3, 12, 8, 0, 0, tzinfo=TZ)
180+
assert is_market_open_now() is False
181+
182+
# Test market closed after closing (5:00 PM on a weekday)
183+
with patch("tastytrade.utils.datetime") as mock_datetime:
184+
mock_datetime.now.return_value = datetime(2024, 3, 12, 17, 0, 0, tzinfo=TZ)
185+
assert is_market_open_now() is False
186+
187+
# Test market closed on weekend (Saturday, March 16, 2024)
188+
with patch("tastytrade.utils.datetime") as mock_datetime:
189+
mock_datetime.now.return_value = datetime(2024, 3, 16, 12, 0, 0, tzinfo=TZ)
190+
assert is_market_open_now() is False
191+
192+
# Test edge case: exactly 9:30 AM (market opens)
193+
with patch("tastytrade.utils.datetime") as mock_datetime:
194+
mock_datetime.now.return_value = datetime(2024, 3, 12, 9, 30, 0, tzinfo=TZ)
195+
assert is_market_open_now() is True
196+
197+
# Test edge case: just before 9:30 AM (9:29 AM)
198+
with patch("tastytrade.utils.datetime") as mock_datetime:
199+
mock_datetime.now.return_value = datetime(2024, 3, 12, 9, 29, 0, tzinfo=TZ)
200+
assert is_market_open_now() is False
201+
202+
# Test edge case: exactly 4:00 PM (market closes, should be False)
203+
with patch("tastytrade.utils.datetime") as mock_datetime:
204+
mock_datetime.now.return_value = datetime(2024, 3, 12, 16, 0, 0, tzinfo=TZ)
205+
assert is_market_open_now() is False
206+
207+
# Test edge case: just before 4:00 PM (3:59 PM)
208+
with patch("tastytrade.utils.datetime") as mock_datetime:
209+
mock_datetime.now.return_value = datetime(2024, 3, 12, 15, 59, 0, tzinfo=TZ)
210+
assert is_market_open_now() is True
211+
212+
# Test edge case: Black Friday just before market open
213+
with patch("tastytrade.utils.datetime") as mock_datetime:
214+
mock_datetime.now.return_value = datetime(2024, 11, 29, 9, 29, 0, tzinfo=TZ)
215+
assert is_market_open_now() is False
216+
217+
# Test edge case: Black Friday just after market open
218+
with patch("tastytrade.utils.datetime") as mock_datetime:
219+
mock_datetime.now.return_value = datetime(2024, 11, 29, 9, 30, 0, tzinfo=TZ)
220+
assert is_market_open_now() is True
221+
222+
# Test edge case: Black Friday just before market close half day
223+
with patch("tastytrade.utils.datetime") as mock_datetime:
224+
mock_datetime.now.return_value = datetime(2024, 11, 29, 12, 59, 0, tzinfo=TZ)
225+
assert is_market_open_now() is True
226+
227+
# Test edge case: Black Friday just after market close half day
228+
with patch("tastytrade.utils.datetime") as mock_datetime:
229+
mock_datetime.now.return_value = datetime(2024, 11, 29, 13, 0, 0, tzinfo=TZ)
230+
assert is_market_open_now() is False

0 commit comments

Comments
 (0)