P2SAMAPA
Update utils.py
bfc2e24 unverified
"""
Utility functions for date handling, NYSE calendar, and time management
"""
from datetime import datetime, timedelta
import pytz
try:
import pandas_market_calendars as mcal
NYSE_CALENDAR_AVAILABLE = True
except ImportError:
NYSE_CALENDAR_AVAILABLE = False
def get_next_trading_day(current_date):
"""
Get the next valid NYSE trading day for signal display.
Logic:
- If today IS a trading day AND the market has NOT yet opened (before 9:30am EST),
return TODAY (the signal is for today's session).
- Otherwise return the NEXT trading day after today.
NOTE: current_date (last date in test set) is used only as a lower bound;
we always anchor to today's actual date.
"""
now_est = get_est_time()
today = now_est.date()
market_open_hour = 9
market_open_minute = 30
# Market has not opened yet if before 9:30 AM EST
market_not_yet_open = (
now_est.hour < market_open_hour or
(now_est.hour == market_open_hour and now_est.minute < market_open_minute)
)
if NYSE_CALENDAR_AVAILABLE:
try:
nyse = mcal.get_calendar('NYSE')
# Check a window starting from today
schedule = nyse.schedule(
start_date=today,
end_date=today + timedelta(days=10)
)
if len(schedule) > 0:
first_trading_day = schedule.index[0].date()
# If today is a trading day and market hasn't opened → return today
if first_trading_day == today and market_not_yet_open:
return today
# Otherwise return the next trading day after today
for ts in schedule.index:
d = ts.date()
if d > today:
return d
# Fallback: last date in schedule
return schedule.index[-1].date()
except Exception as e:
print(f"NYSE calendar error: {e}")
# Fallback: simple weekend skip
candidate = today if market_not_yet_open else today + timedelta(days=1)
while candidate.weekday() >= 5: # 5=Sat, 6=Sun
candidate += timedelta(days=1)
return candidate
def get_est_time():
"""Get current time in US Eastern timezone"""
return datetime.now(pytz.timezone('US/Eastern'))
def is_sync_window():
"""Check if current time is within sync windows (7-8am or 7-8pm EST)"""
now_est = get_est_time()
return (7 <= now_est.hour < 8) or (19 <= now_est.hour < 20)
def filter_to_trading_days(dates, data_arrays):
"""
Filter dates and corresponding data arrays to only NYSE trading days
Args:
dates: pandas DatetimeIndex
data_arrays: list of numpy arrays to filter (same length as dates)
Returns:
filtered_dates, filtered_arrays (list)
"""
if not NYSE_CALENDAR_AVAILABLE:
return dates, data_arrays
try:
import pandas as pd
import numpy as np
nyse = mcal.get_calendar('NYSE')
trading_schedule = nyse.schedule(
start_date=dates[0].strftime('%Y-%m-%d'),
end_date=dates[-1].strftime('%Y-%m-%d')
)
valid_trading_days = trading_schedule.index.normalize()
if valid_trading_days.tz is not None:
valid_trading_days = valid_trading_days.tz_localize(None)
trading_day_mask = dates.isin(valid_trading_days)
filtered_dates = dates[trading_day_mask]
# Convert mask properly
if isinstance(trading_day_mask, pd.Series):
mask_array = trading_day_mask.values
elif hasattr(trading_day_mask, 'to_numpy'):
mask_array = trading_day_mask.to_numpy()
else:
mask_array = np.array(trading_day_mask)
# Apply mask to all data arrays
filtered_arrays = [arr[mask_array] for arr in data_arrays]
return filtered_dates, filtered_arrays
except Exception as e:
print(f"Warning: NYSE calendar filter failed: {e}")
return dates, data_arrays