betting_combat.services.rounds_frames
Strategy 4’s research frames rebuilt from the store: the round datasets, the fight clock,
the market list, the minute panel (Set 4), the trade tables and the market windows (Set 3) —
everything the weekly refit trains on and the forward check replays. Research build order
(tests/fixtures/make_round_references.py: RoundDataset -> LiveSets -> trades
-> Set3); every step is the ported library’s (rounds.features, rounds.market):
tables services.rounds_inputs.history_tables (the mirror, Wikipedia, MMADecisions, the static files, fights_kalshi)datasets RoundDataset(RawData(tables)).build(model_features=<cache or None>)clock FightClock(distance minutes); fights = live_fights(fight_ids(build_fights( fights_kalshi, winner markets, UFCStats), bouts), winner minutes, clock, Dataset 1 keys, a_slot)markets market_list(fights, the side series, distance)set4 set4_minutes(fights, markets, every series' minutes, {}, a_slot)trades trade_tables(fights, markets, tapes): the research-seeded tapes as pulled, the production tapes cut to the design window (``design_trade_windows``)set3 set3_main / set3_side on the trade tables and Set 4, keyed on Dataset 1; side rows without a complete core dropped (``drop_unpriceable``)Two research inputs are left out, neither a model input: Group 6 (the dataset’s kalshi_* /
poly_* columns at each round break, evaluation only) and Polymarket’s price history (Set 4’s
poly_win_a; strategy 4 trades Kalshi only).
Classes
Frames
Sources
The store’s inputs as the research read them from its files.
Functions
build_clock
build_clock(sources: Sources, raw: RawData, keys: pd.DataFrame, a_slot: Mapping[str, int]) -> tuple[pd.DataFrame, pd.DataFrame](fights, markets): the Kalshi fight clock of the dataset’s fights and their markets.
build_datasets
build_datasets(tables: UfcTables, model_features: pd.DataFrame | None = None) -> tuple[RawData, dict[str, pd.DataFrame]](RawData, RoundDataset.build) without Group 6. model_features: a Group 5 cache
(rows it lacks are fitted; None fits every year, several minutes).
build_frames
build_frames(store: RoundsStore, tables: UfcTables, model_features: pd.DataFrame | None = None, clock_years: Sequence[int] = (), cached: bool = True, reuse: bool = True, now: Callable[[], dt.datetime] = lambda: dt.datetime.now(dt.UTC), guard: Callable[[Frames], None] | None = None) -> FramesEvery frame from the store (see the module doc), through the caches
(services.rounds_cache): Group 5 from the cached years’ fits (each year fitted once),
the market frames of every fight whose inputs did not change read back, the others built a
few cards at a time. cached=False: the same computation, nothing read from or written to
the caches. reuse=False (with cached): nothing read from the caches, every fight
rebuilt and every year refitted, and all of it written to them (a full rebuild).
model_features: a Group 5 table given whole (the research’s cache; the
known-answer tests), instead of the clock cache. clock_years: years whose fit is wanted
though no row is in them yet (the refit’s cutoff year). guard: run on the built frames
BEFORE either cache is written; when it raises, nothing is written (the refit’s cutoff
refusal).
build_market_sets
build_market_sets(sources: Sources, fights: pd.DataFrame, markets: pd.DataFrame, tapes: Mapping[str, list[list[Any]]], keys: pd.DataFrame, a_slot: Mapping[str, int]) -> dict[str, Any]Set 4, the trade tables and Set 3 (main; side without the unpriceable rows).
last_trades_used
last_trades_used(store: RoundsStore, fights: pd.DataFrame, markets: pd.DataFrame, pulls: Sequence[Mapping[str, Any]]) -> pd.DataFramePer fight, the last trade its frames read (fight_id, event_date, last_trade_at):
over its markets, the latest trade of each tape exactly as load_tapes serves it — a
research-seeded tape as the research had it, any other cut to the design window. A fight none of whose
markets has a trade there is absent.
load_sources
load_sources(store: RoundsStore, tables: UfcTables, minutes: Sequence[str] = (WINNER, DISTANCE)) -> SourcesEvery series’ markets, and the minute candles of minutes (default: the winner and
distance series, which the fight clock reads whole; the side series’ are read per fight),
each cut to the research’s window (rounds_windows.minute_windows), beside
tables.
load_tapes
load_tapes(store: RoundsStore, fights: pd.DataFrame, markets: pd.DataFrame) -> dict[str, list[list[Any]]]Every market’s trade tape: a research-seeded tape as the research had it (its seeded trades, whatever a later pull added), a production tape cut to the research’s design window out of the market’s full raw trades.
side_minutes
side_minutes(store: RoundsStore, tickers: Sequence[str], windows: Mapping[str, Window | None] | None = None) -> list[dict[str, list[dict[str, Any]]]]The side series’ candles of tickers (all_candles’ last argument), cut to the
research’s windows (windows, else read for them).