time_rules.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. from __future__ import annotations
  2. from zoneinfo import ZoneInfo
  3. import pandas as pd
  4. NY = ZoneInfo("America/New_York")
  5. BJ = ZoneInfo("Asia/Shanghai")
  6. def utc_timestamp(ts: int) -> pd.Timestamp:
  7. return pd.to_datetime(ts, unit="ms", utc=True)
  8. def ny_minutes(ts: int) -> tuple[int, int]:
  9. dt = utc_timestamp(ts).to_pydatetime().astimezone(NY)
  10. return dt.weekday(), dt.hour * 60 + dt.minute
  11. def is_ny_weekend(ts: int) -> bool:
  12. weekday, _ = ny_minutes(ts)
  13. return weekday >= 5
  14. def is_us_open_window(ts: int) -> bool:
  15. weekday, minute = ny_minutes(ts)
  16. return weekday < 5 and 9 * 60 + 30 <= minute < 10 * 60 + 30
  17. def is_us_open_extended(ts: int) -> bool:
  18. weekday, minute = ny_minutes(ts)
  19. return weekday < 5 and 9 * 60 <= minute < 11 * 60
  20. def entry_allowed(ts: int, mode: str) -> bool:
  21. weekday, minute = ny_minutes(ts)
  22. if mode == "all":
  23. return True
  24. if mode == "weekday":
  25. return not is_ny_weekend(ts)
  26. if mode == "no_weekend":
  27. return not is_ny_weekend(ts)
  28. if mode == "weekend":
  29. return is_ny_weekend(ts)
  30. if mode == "no_us_open":
  31. return not is_us_open_extended(ts)
  32. if mode == "us_open_only":
  33. return is_us_open_extended(ts)
  34. if mode == "asia_bj":
  35. hour = utc_timestamp(ts).to_pydatetime().astimezone(BJ).hour
  36. return 8 <= hour < 16
  37. if mode == "us_regular":
  38. return weekday < 5 and 9 * 60 + 30 <= minute < 16 * 60
  39. raise ValueError("entry_time_filter is invalid")
  40. def time_bucket(ts: int) -> str:
  41. if is_ny_weekend(ts):
  42. return "weekend"
  43. _, minute = ny_minutes(ts)
  44. if 4 * 60 <= minute < 9 * 60:
  45. return "us_premarket"
  46. if 9 * 60 <= minute < 9 * 60 + 30:
  47. return "us_preopen"
  48. if 9 * 60 + 30 <= minute < 10 * 60 + 30:
  49. return "us_open_1h"
  50. if 10 * 60 + 30 <= minute < 16 * 60:
  51. return "us_regular_late"
  52. if 16 * 60 <= minute < 20 * 60:
  53. return "us_afterhours"
  54. return "overnight"