Add an expiry-date predicate and guard venue session
lookups against expired contracts and empty session
lists in `.ib.venues`; use in `api.py` to skip gap
detection for expired tracts.
Deats,
- add `is_expired()` predicate using
`pendulum.parse()` on `realExpirationDate`.
- `sesh_times()`: raise `ValueError` if contract is
expired or has no session intervals (instead of
`StopIteration` from `next(iter(...))`).
- `is_venue_closure()`: handle `None` return from
`sesh_times()` with guard + `breakpoint()`.
Also in `api.py`,
- import and call `is_expired()` from `.venues`.
- gate gap-detection on `not _is_expired`.
- default `timeZoneId` to `'EST'` when IB returns
empty/`None`.
(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code