| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- from __future__ import annotations
- from zoneinfo import ZoneInfo
- import pandas as pd
- NY = ZoneInfo("America/New_York")
- BJ = ZoneInfo("Asia/Shanghai")
- def utc_timestamp(ts: int) -> pd.Timestamp:
- return pd.to_datetime(ts, unit="ms", utc=True)
- def ny_minutes(ts: int) -> tuple[int, int]:
- dt = utc_timestamp(ts).to_pydatetime().astimezone(NY)
- return dt.weekday(), dt.hour * 60 + dt.minute
- def is_ny_weekend(ts: int) -> bool:
- weekday, _ = ny_minutes(ts)
- return weekday >= 5
- def is_us_open_window(ts: int) -> bool:
- weekday, minute = ny_minutes(ts)
- return weekday < 5 and 9 * 60 + 30 <= minute < 10 * 60 + 30
- def is_us_open_extended(ts: int) -> bool:
- weekday, minute = ny_minutes(ts)
- return weekday < 5 and 9 * 60 <= minute < 11 * 60
- def entry_allowed(ts: int, mode: str) -> bool:
- weekday, minute = ny_minutes(ts)
- if mode == "all":
- return True
- if mode == "weekday":
- return not is_ny_weekend(ts)
- if mode == "no_weekend":
- return not is_ny_weekend(ts)
- if mode == "weekend":
- return is_ny_weekend(ts)
- if mode == "no_us_open":
- return not is_us_open_extended(ts)
- if mode == "us_open_only":
- return is_us_open_extended(ts)
- if mode == "asia_bj":
- hour = utc_timestamp(ts).to_pydatetime().astimezone(BJ).hour
- return 8 <= hour < 16
- if mode == "us_regular":
- return weekday < 5 and 9 * 60 + 30 <= minute < 16 * 60
- raise ValueError("entry_time_filter is invalid")
- def time_bucket(ts: int) -> str:
- if is_ny_weekend(ts):
- return "weekend"
- _, minute = ny_minutes(ts)
- if 4 * 60 <= minute < 9 * 60:
- return "us_premarket"
- if 9 * 60 <= minute < 9 * 60 + 30:
- return "us_preopen"
- if 9 * 60 + 30 <= minute < 10 * 60 + 30:
- return "us_open_1h"
- if 10 * 60 + 30 <= minute < 16 * 60:
- return "us_regular_late"
- if 16 * 60 <= minute < 20 * 60:
- return "us_afterhours"
- return "overnight"
|