You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

50 lines
1.7 KiB
Python

"""Compute the reaction date for a filing based on its time bucket."""
from __future__ import annotations
import datetime as dt
from libs.common.time_utils import is_trading_day
def _advance_to_next_trading_day(date: dt.date) -> dt.date:
"""Return the next calendar day that is a trading day (starting from date+1)."""
check = date + dt.timedelta(days=1)
for _ in range(30): # guard against infinite loop
if is_trading_day(check):
return check
check += dt.timedelta(days=1)
raise RuntimeError(f"Could not find trading day within 30 days of {date}")
def _to_trading_day_on_or_after(date: dt.date) -> dt.date:
"""Return date itself if a trading day, else the next trading day."""
for _ in range(30):
if is_trading_day(date):
return date
date += dt.timedelta(days=1)
raise RuntimeError("Could not find trading day within 30 days")
def compute_reaction_date(
event_date: dt.date,
filing_time_bucket: str,
) -> dt.date:
"""Return the first trading day on which the market can react to the filing.
Rules:
- pre_market / regular_hours → same day if it is a trading day, else next.
- post_market / unknown → next trading day after event_date.
Args:
event_date: The calendar date of the filing.
filing_time_bucket: One of pre_market, regular_hours, post_market, unknown.
Returns:
The reaction date (a trading day).
"""
if filing_time_bucket in ("pre_market", "regular_hours"):
return _to_trading_day_on_or_after(event_date)
else:
# post_market or unknown: market reacts next trading day
return _advance_to_next_trading_day(event_date)