betting_combat.rounds.live.upcoming
Dataset 1 feature rows for an UPCOMING card, before any of its fights has a result.
The training build (features.RoundDataset.build) keeps only fights with a result (it
needs the targets) and fits the clock every year from scratch. A card about to be traded has
no results, so this assembles the same feature columns with the training code itself:
UfcTables + UpcomingCard ─► with_upcoming ─► RawData ─► build_upcoming(raw, fights, clock)- the card’s bouts join the UFCStats tables as result-less rows (
with_upcoming): every as-of feature (fighter history, matchup, context, odds) is computed from strictly earlier dates exactly as in training; - the style records (
StyleSimilarity) count the card’s bouts as result-less records on their date (pending): a training row reads its pair’s record through a row of its own date, which only exists once the bout is recorded; without it an upcoming bout would miss the previous card’s fights; - Group 5 (the clock) comes from the year’s LOCKED models (
features.ClockYear, fitted on the fights before 1 January with seed = the year), as the training cache has them; - one row per scheduled round start (round_idx 0 .. R-1): which rounds happen is not known.
Nothing here reads a result: the rows carry no y_* column and no live-market (group 6)
column. tests/parity/test_rounds_live.py rebuilds the 2026-09-26 card this way
from inputs with its results removed and compares it with the training rows.
Classes
UpcomingCard
One card before it starts, as the data layer supplies it.
event UFCStats’ event name (ufcstats_ufc_event_details.EVENT)
event_url its UFCStats URL (.../event-details/<event_id>)
date the card’s date (UFCStats’ date, the US date of the card)
location ‘City, State, Country’ as UFCStats writes it
bouts one row per bout in UFCStats’ card order (main event first): fight_url
(.../fight-details/<fight_id>), name_1 / name_2 (UFCStats’ order),
weight_class (UFCStats’ text, e.g. ‘Lightweight Bout’, “Women’s
Strawweight Bout”, ‘UFC Lightweight Title Bout’), rounds (3 or 5)
kalshi the Kalshi card-start quotes in fights_kalshi form (date,
fighter_a, fighter_b, card_prob_a, card_quote_ok): the
pre-fight price p_mkt_a where no sportsbook line exists (card_quote)
segments Wikipedia’s card segments in card_segments form (date,
fighter_1, fighter_2, segment), or None
excluded the bouts the loader refused (services.rounds_upcoming): event_ticker
(the Kalshi fight, None for a Wikipedia bout without one), bout (the
names), reason; the engine must not trade any of them. None: not known
Functions
build_upcoming
build_upcoming(raw: RawData, fight_ids: list[str], clock: ClockYear) -> pd.DataFrameDataset 1’s feature columns (keys, context, both profiles, matchup, odds, the clock)
for every scheduled round start of the upcoming bouts fight_ids (in raw, without
results), in the training table’s column order without targets and live markets.
clock: the card year’s locked Group 5 models.
card_quote
card_quote(bid_a: float, ask_a: float, bid_b: float, ask_b: float) -> tuple[float, bool](card_prob_a, card_quote_ok) from the two winner books, the research’s card-start rule
(ufc/pull.py): each side’s mid, normalised across the two books; a quote at the
extremes (a result already known) or with a side missing is not ok.
upcoming_ids
upcoming_ids(card: UpcomingCard) -> list[str]The card’s UFCStats fight ids, in card order.
with_upcoming
with_upcoming(tables: UfcTables, card: UpcomingCard) -> UfcTablestables with the card’s bouts added as result-less rows (and its quotes and
segments). Refuses a card whose bouts are already in the tables, or tables holding any
result on or after the card’s date: every input must predate the card.