betting_combat.services.rounds_calendar
When strategy 4’s jobs run: the UFC calendar and the job chains, kept pure. The calendar
sensor in jobs.rounds reads the configs, Kalshi, the model versions and Dagster’s runs, and
asks these functions; it starts at most ONE chain per tick, a prep before a forward check.
prep every card Kalshi lists (its live-feed milestones, cancelled fights left out) in the next 8 days, from ``prep_days_before`` days before it at ``prep_time_utc`` (UTC), until its first fight minus ``card_lead_minutes`` minus a 3 h margin (``prep_window``). Due while not done (a model version locked to the card, or a prep chain whose refit succeeded); retried with a new chain after a failed one (``prep_chain``: up to ``PREP_ATTEMPTS``); it waits, never drops, while another rounds run is under way; past its deadline and not done it is an alert. The chain is the data update, the datasets update, then the refit locked to the card (the chain's ``betting/card_date`` tag). Kalshi decides the card and its date: a stale stored Wikipedia list neither hides a moved or added card nor delays its prep.forward ``forward_days_after`` days after a card a rounds card run traded (a run that succeeded, or one that recorded decisions), at ``forward_time_utc`` (UTC); one chain per card, ever (``forward_chain``). The chain is the data update, the datasets update, then the forward check.trade a card's first fight within ``card_lead_minutes`` (``services.cards.next_card``).A chain is one data update, one datasets update and one refit (or forward check), launched one
after the other by sensors and tied together by the run tag betting/chain. A stage starts
only after the stage before it succeeded, within CHAIN_STALE of its end; a failed or
cancelled stage stops the chain (re-execute it in the UI and the chain goes on).
Classes
Next
The stage a chain is waiting for (job), or why it waits for none (why).
Prep
The card whose prep chain is due now (card: Kalshi’s date, the refit’s cutoff), or
why none is (why). late: a card’s prep is still not done past its deadline (an
alert: the card will not be traded unless the refit is run by hand).
RunView
One Dagster run: its job, its state (queued / running / success / failed / canceled: a run cancelled by hand is not a failure), its tags, and when it was created and ended (None: not ended).
Functions
at_ny
at_ny(day: dt.date, at: dt.time) -> dt.datetimeday at the wall-clock time at in New York, as an aware instant (the offset in
force that day: EDT or EST).
at_utc
at_utc(day: dt.date, at: dt.time) -> dt.datetimeday at at in UTC (every configured time is UTC: no DST).
chain_kind
chain_kind(chain: str) -> strchain_runs
chain_runs(runs: Iterable[RunView]) -> dict[str, list[RunView]]The runs of each chain (by its betting/chain tag), oldest first.
forward_chain
forward_chain(card: dt.date) -> strforward_due
forward_due(traded: Iterable[dt.date], now: dt.datetime, at: dt.time, days_after: int, lookback_days: int) -> list[dt.date]The cards a rounds card run traded whose forward check is due at now:
days_after days after the card at at UTC, no more than lookback_days days after
it. Oldest first.
kalshi_card_dates
kalshi_card_dates(milestones: Iterable[Milestone]) -> dict[dt.date, dt.datetime | None]The cards Kalshi lists: the date code of each winner-event milestone not cancelled -> the card’s first scheduled start (None when no fight has one).
next_stage
next_stage(chain: str, runs: Sequence[RunView], now: dt.datetime) -> NextWhat chain does next, from its runs: a stage’s latest run decides (a re-executed
stage counts from its newest run).
ny_date
ny_date(now: dt.datetime) -> dt.dateThe New York calendar date at now (an aware instant).
open_chains
open_chains(runs: Iterable[RunView], now: dt.datetime) -> list[str]The chains still under way: a stage running, or one that succeeded and whose next stage
is still to start (next_stage).
prep_chain
prep_chain(card: dt.date, attempt: int) -> strThe id (and run key) of card’s attempt-th prep chain: prep-<card>, then
prep-<card>-2, -3 … (a new key for every attempt: Dagster drops a repeated key).
prep_due
prep_due(kalshi: Mapping[dt.date, dt.datetime | None], now: dt.datetime, at: dt.time, days_before: int, lead: dt.timedelta, done: Iterable[dt.date] = (), margin: dt.timedelta = PREP_MARGIN, horizon: dt.timedelta = PREP_HORIZON) -> PrepThe first card Kalshi lists (kalshi_card_dates) from today to horizon ahead whose
prep is not done and whose window (prep_window) is open at now. Cards are taken
in date order: a later card waits for the one before it. A card past its deadline and not
done, whose first fight is still to come, is late (an alert); one whose fights have
started is left behind.
prep_window
prep_window(card: dt.date, first: dt.datetime | None, at: dt.time, days_before: int, lead: dt.timedelta, margin: dt.timedelta = PREP_MARGIN) -> tuple[dt.datetime, dt.datetime](opens, deadline) of card’s prep: from at UTC days_before days before the
card, until its first fight minus the card run’s lead minus margin (the refit has to
be done before the card run starts). Without a first fight: midnight New York at the start
of the card’s date (cards are dated in New York).
wiki_card_dates
wiki_card_dates(list_json: str) -> list[dt.date]Every event date of the stored Wikipedia list (past and scheduled), sorted, unique.