agenda/stock_market.py
Edward Betts ea4980a5d7 Fix European trip return heuristic for weekend location tracking
Adjust European short trip heuristic from >3 days to >1 day to correctly
detect when user has returned home from European trips. This fixes the
April 29-30, 2023 case where the location incorrectly showed "Sankt Georg, Hamburg"
instead of "Bristol" when the user was free (no events scheduled) after
the foss-north trip ended on April 27.

The previous logic required more than 3 days to pass before assuming
return home from European countries, but for short European trips by
rail/ferry, users typically return within 1-2 days.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-16 06:38:37 +02:00

83 lines
2.7 KiB
Python
Executable file

#!/usr/bin/python3
from datetime import date, timedelta, timezone
from time import time
import dateutil.tz
import exchange_calendars # type: ignore
import pandas # type: ignore
from agenda import uk_tz, utils
here = dateutil.tz.tzlocal()
markets = [("XLON", "London"), ("XNYS", "US")]
def open_and_close() -> list[str]:
"""Stock markets open and close times."""
# The trading calendars code is slow, maybe there is a faster way to do this
# Or we could cache the result
now = pandas.Timestamp.now(timezone.utc)
now_local = pandas.Timestamp.now(here)
reply = []
for code, label in markets:
cal = exchange_calendars.get_calendar(code)
if cal.is_open_on_minute(now_local):
next_close = cal.next_close(now).tz_convert(here)
next_close = next_close.replace(minute=round(next_close.minute, -1))
delta_close = utils.timedelta_display(next_close - now_local)
prev_open = cal.previous_open(now).tz_convert(here)
prev_open = prev_open.replace(minute=round(prev_open.minute, -1))
delta_open = utils.timedelta_display(now_local - prev_open)
msg = (
f"{label} market opened {delta_open} ago, "
+ f"closes in {delta_close} ({next_close:%H:%M})"
)
else:
ts = cal.next_open(now)
ts = ts.replace(minute=round(ts.minute, -1))
ts = ts.tz_convert(here)
delta = utils.timedelta_display(ts - now_local)
msg = f"{label} market opens in {delta}" + (
f" ({ts:%H:%M})" if (ts - now_local) < timedelta(days=1) else ""
)
reply.append(msg)
return reply
# x = open_and_close()
# print(x)
t0 = time()
now = pandas.Timestamp.now(timezone.utc)
now_local = pandas.Timestamp.now(here)
today = date.today()
start = today - timedelta(days=1)
end = today + timedelta(days=30)
start = date(2024, 12, 20)
end = date(2025, 1, 5)
for code, label in markets:
print(f"{code} {label:6s}")
cal = exchange_calendars.get_calendar(code, start=start, end=end)
# print(cal.open_times, cal.close_times, cal.weekmask, cal.regular_holidays)
for session in cal.sessions:
o = cal.session_open(session).tz_convert(uk_tz)
c = cal.session_close(session).tz_convert(uk_tz)
print(f" {session.date()} {o} {c}")
continue
print(cal.sessions, cal.opens, cal.closes)
continue
prev_open = cal.previous_open(now).tz_convert(here)
next_open = cal.next_open(now).tz_convert(here)
next_close = cal.next_close(now).tz_convert(here)
print(f"{code} {label:6s} {prev_open} {next_open} {next_close}")
print()
print(f"{time() - t0:.1f} seconds")