Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion qtrade/clock.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ class Job:
JOBS = [
Job("data-hoard.yml", "UTC", tuple(f"{h:02d}:{m:02d}" for h in range(24) for m in (7, 37)), weekdays=False,
window_min=20),
Job("hft-shadow.yml", NY, ("09:26",), window_min=300), # its own chain then runs the session
# its own chain runs the session; the hourly re-dispatch restarts it if a link fails (2026-11-09: a run that
# never started stopped it at 13:10) and otherwise only queues behind the running one
Job("hft-shadow.yml", NY, tuple(f"{h:02d}:26" for h in range(9, 16)), window_min=50),
Job("flip-sleeve.yml", NY, ("15:45",), window_min=400),
Job("auction-sheet.yml", NY, ("16:55",), window_min=400), # after Yahoo's ~16:30-16:45 refresh of Asian bars
Job("hoard-archive.yml", NY, ("16:45",), inputs=(("job", "eod"),), window_min=400),
Expand Down
6 changes: 6 additions & 0 deletions tests/test_clock.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,9 @@ def test_run_fires_each_slot_once(monkeypatch):
monkeypatch.setattr(C.time, "sleep", lambda s: clock.__setitem__("t", clock["t"] + 1800))
fired = C.run(1.0, "o/r", "main", dry_run=True) # polls at 0 s and 1800 s, both within the 17:15 slot
assert sum("foreign-sheet.yml" in f for f in fired) == 1


def test_hft_shadow_is_re_dispatched_every_hour_of_the_session():
j = _job("hft-shadow.yml")
keys = [k for h in range(14, 22) for k in C.due(j, pd.Timestamp(f"2026-11-09 {h}:30", tz="UTC"))]
assert len(keys) == 7 and keys[0].endswith("09:26") and keys[-1].endswith("15:26")
Loading