Skip to content

betting_combat.rounds.market.windows

Set 3: round-start market features from the Kalshi trades, one row per (fight_id, round_idx) like the round dataset, built only from what happened before the row’s time.

Ported from the research (ufc/dataset/set3.py: window_stats, Set3.row_times, Set3.windows, Set3.main, Set3.side, Set3.implied, Set3.write).

Row time t: the end of the break before round r+1 (round_idx r); for round_idx 0 the minute before the fight. A row for every round that started (no cut at the winner market’s snap, which is only known afterwards; the dataset keeps the rounds that started). Windows, with edges E = [start-60, start-30, start, start+6, start+12, …]:

last_ [E[r+1], t) the round just fought (round 1: the 30 minutes before the fight)
prev_ [E[r], E[r+1]) the window before that
sofar_ [start, t) the fight so far
pre_ [start-30, min(start, t)) (round 0 stops at its own time t)
lastmin_ [t-1, t)

Trades are read in (ts, trade_id) order (:func:~.trades.time_order): the last price of a window never depends on how a sort breaks ties.

Main market (A-framed: a trade in B’s market is its mirror in A’s): mid_a, spread (cents), oi, mins_since_trade, chg_since_pre, per window trades, contracts, dollars, avg_trade, big_trades (>= $500), blocks, flow, vwap_a, chg_a, range_a, vol_a, jumps; surprise. Side markets (:data:SIDE): _mid, _spread, _last_contracts/_dollars/_flow/_chg, _prev_contracts/_chg, and the implied probabilities (:func:implied) with their change over the last window. A window with no trades: counts 0, moves 0, prices carried from the last trade before it (else the book at t).

Functions

drop_unpriceable

drop_unpriceable(side: pd.DataFrame) -> tuple[pd.DataFrame, dict[str, list[str]]]

The side set’s complete-core rule: a listed side market that never had a book or a trade before a row cannot be priced, and its fight leaves the side set. Returns the kept rows and fight_id -> the columns that were empty.

implied

implied(mids: Mapping[str, Any], main_mid_a: float) -> dict[str, Any]

Probabilities implied by the side markets: p_dec_dist (distance), p_dec_mov and p_a_mov (shares of all MOV), p_finish_mov, ko_share (of the finishes), gap_dec, gap_a.

row_times

row_times(f: Any) -> list[tuple[int, pd.Timestamp, list[pd.Timestamp]]]

(round_idx, row time, window edges E) for every scheduled round of a fight (the dataset keys keep the rounds that started). f needs start, rounds.

set3_main

set3_main(trades_main: pd.DataFrame, minutes: pd.DataFrame, fights: pd.DataFrame, causal: bool = False) -> pd.DataFrame

The winner-market rows (research Set3.main), before the dataset keys are attached.

Args: trades_main: :func:~.trades.trade_tables main table. minutes: :func:~.minutes.set4_minutes. fights: :func:~.listing.live_fights rows. causal: no window of a row reaches past the row’s time (the round-0 sofar window, see :func:window_bounds); False = the research.

set3_side

set3_side(trades_side: pd.DataFrame, minutes: pd.DataFrame, fights: pd.DataFrame, markets: pd.DataFrame, main: pd.DataFrame) -> pd.DataFrame

The side-market rows (research Set3.side) for the fights listing all of :data:SIDE, before the dataset keys are attached.

Args: trades_side: :func:~.trades.trade_tables side table. minutes: :func:~.minutes.set4_minutes. fights: :func:~.listing.live_fights rows. markets: :func:~.listing.market_list rows (fight_id, name). main: :func:set3_main (its mid_a).

window_bounds

window_bounds(r: int, t: pd.Timestamp, edges: list[pd.Timestamp], causal: bool = False) -> dict[str, Window]

The row’s windows as (lo, hi), lo <= ts < hi. pre ends at min(start, t): the round-0 row (t = the minute before the start) does not read [t, start) (research fixed 2026-09-30).

causal: the research’s round-0 sofar is the empty window at the start, so its carried price (sofar_vwap_a) is the last trade before the START, not before t. True makes it [min(start, t), t), the live rule: nothing at or after t. False reproduces the research. Rows at or after the start are the same either way.

window_stats

window_stats(tr: pd.DataFrame, lo: Any, hi: Any, carry: float) -> dict[str, Any]

Trade statistics for trades with lo <= ts < hi. tr columns: ts, price (A-framed or the market’s own YES price), count, dollars, sign (+1 buying the priced side), block; carry is the price before the window.

with_keys

with_keys(keys: pd.DataFrame, rows: pd.DataFrame) -> pd.DataFrame

The dataset’s keys (fight_id, round_idx, event_id, event_date) inner-joined to Set 3 rows, in the dataset’s order.