feat(orchestration): nightly runner, rollover budgets, incremental checkpoints
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016DvdRZkyCy9NJpHYDdPqmS
This commit is contained in:
1 parent
b2ae3d6ced
commit
aa1ae0c95e
4 files changed
+161
No files matched your search
@@ -0,0 +1,43 @@
|
||||
"""Time budgeting for the nightly run.
|
||||
|
||||
Each agent gets a wall-clock deadline = its fair share of the remaining window, capped by
|
||||
the per-agent config, and never past the hard stop. If an agent finishes early the freed
|
||||
time rolls over to those remaining (bounded by the cap), and the hard stop always holds.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
|
||||
def local_hard_stop_ts(hard_stop_hhmm: str, local_tz: str) -> float:
|
||||
"""Epoch seconds of the next HH:MM in local time (today if still ahead, else tomorrow)."""
|
||||
tz = ZoneInfo(local_tz)
|
||||
now = datetime.now(tz)
|
||||
hh, mm = (int(x) for x in hard_stop_hhmm.split(":"))
|
||||
target = now.replace(hour=hh, minute=mm, second=0, microsecond=0)
|
||||
if target <= now:
|
||||
target += timedelta(days=1)
|
||||
return target.timestamp()
|
||||
|
||||
|
||||
def next_deadline(
|
||||
now_ts: float, hard_stop_ts: float, agents_remaining: int, per_agent_cap_s: float
|
||||
) -> float:
|
||||
"""Deadline for the current agent: min(fair share, cap), never past hard stop."""
|
||||
if agents_remaining <= 0 or now_ts >= hard_stop_ts:
|
||||
return hard_stop_ts
|
||||
fair_share = (hard_stop_ts - now_ts) / agents_remaining
|
||||
span = min(fair_share, per_agent_cap_s) if per_agent_cap_s else fair_share
|
||||
return now_ts + max(span, 60.0)
|
||||
|
||||
|
||||
def next_market_trade_date(market_tz: str) -> str:
|
||||
"""Best-effort next trading date (ET), rolling weekends to Monday. Holidays handled in
|
||||
Phase 3 via Alpaca's calendar; this is only for naming the nightly output folder."""
|
||||
tz = ZoneInfo(market_tz)
|
||||
d = datetime.now(tz).date()
|
||||
while d.weekday() >= 5: # 5 = Sat, 6 = Sun
|
||||
d += timedelta(days=1)
|
||||
return d.isoformat()
|
||||
Reference in new issue
Block a user